Index: user/alc/PQ_LAUNDRY/contrib/openbsm/.travis.yml =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/.travis.yml (nonexistent) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/.travis.yml (revision 292449) @@ -0,0 +1,18 @@ +language: c + +compiler: + - clang + - gcc + +os: + - linux + - osx + +before_install: + - if [ $TRAVIS_OS_NAME == "linux" ]; then + sudo apt-get -qq update; + sudo apt-get -qq install byacc flex; + elif [ $TRAVIS_OS_NAME == "osx" ]; then + brew update; + brew install byacc flex; + fi Property changes on: user/alc/PQ_LAUNDRY/contrib/openbsm/.travis.yml ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: user/alc/PQ_LAUNDRY/contrib/openbsm/INSTALL =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/INSTALL (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/INSTALL (revision 292449) @@ -1,40 +1,40 @@ OpenBSM Build and Installation Instructions OpenBSM is currently built using autoconf and automake, which should allow for building on a range of operating systems, including FreeBSD, Mac OS X, and Linux. Some components are built only if appropriate kernel audit -suppport is found. Typical builds will be performed using: +support is found. Typical builds will be performed using: ./configure make If doing development work on OpenBSM with gcc, the following invocation of configure is preferred in order to generate full compiler warnings and force the compile to fail if a warning is found: CFLAGS="-Wall -Werror" ./configure On Linux systems, OpenSSL headers may have to be installed to support encryption of on-the-wire audit streams using auditdistd; the following appears to work on Ubuntu: sudo apt-get install libssl-dev To install the library, binaries, and man pages, use: make install The OpenBSM install will not install files in /etc; these have to be manually installed or merged. Currently, the locations of these files are not configurable. You may wish to specify that the OpenBSM components not be installed in the base system, rather in a specific directory. This may be done using the --prefix argument to configure. If installing to a specific directory, -remember to update your library path so that running tools from that +remember to update your library path so that when running tools from that directory the correct libbsm is used: ./configure --prefix=/home/rwatson/openbsm make make install LD_LIBRARY_PATH=/home/rwatson/openbsm/libbsm ; export LD_LIBRARY_PATH Index: user/alc/PQ_LAUNDRY/contrib/openbsm/LICENSE =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/LICENSE (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/LICENSE (revision 292449) @@ -1,38 +1,36 @@ OpenBSM Copyrights and Licensing OpenBSM is covered by a number of copyrights, with licenses being either two or three clause BSD licenses. Individual file headers should be consulted for copyrights on specific elements of the distribution. The following copyright and license are asserted over the OpenBSM distribution as a whole: Copyright (c) 2005-2012 Robert N.M. Watson 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 AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The TrustedBSD Project would appreciate the contribution of fixes and enhancements under an identical license in order to avoid potentially confusing license proliferation. - -$P4: //depot/projects/trustedbsd/openbsm/LICENSE#6 $ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/Makefile.am (revision 292449) @@ -1,27 +1,23 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/Makefile.am#5 $ -## - SUBDIRS = \ bsm if HAVE_AUDIT_SYSCALLS SUBDIRS += \ libauditd endif SUBDIRS += \ libbsm \ bin \ man \ modules \ sys ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = \ CHANGELOG \ LICENSE \ README \ TODO \ VERSION Index: user/alc/PQ_LAUNDRY/contrib/openbsm/Makefile.in =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/Makefile.in (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/Makefile.in (revision 292449) @@ -1,777 +1,777 @@ # Makefile.in generated by automake 1.12.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 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__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } 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@ @HAVE_AUDIT_SYSCALLS_TRUE@am__append_1 = \ @HAVE_AUDIT_SYSCALLS_TRUE@ libauditd subdir = . DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(top_srcdir)/config/config.guess \ $(top_srcdir)/config/config.h.in \ $(top_srcdir)/config/config.sub \ $(top_srcdir)/config/install-sh $(top_srcdir)/config/ltmain.sh \ $(top_srcdir)/config/missing $(top_srcdir)/configure INSTALL \ - NEWS TODO config/config.guess config/config.sub config/depcomp \ - config/install-sh config/ltmain.sh config/missing \ - config/ylwrap + NEWS TODO config/compile config/config.guess config/config.sub \ + config/depcomp config/install-sh config/ltmain.sh \ + config/missing config/ylwrap ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-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 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=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ cscope distdir dist dist-all distcheck ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = bsm libauditd libbsm bin man modules sys 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 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@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ 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@ 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@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MIG = @MIG@ 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@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ 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_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@ 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@ 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 = bsm $(am__append_1) libbsm bin man modules sys ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = \ CHANGELOG \ LICENSE \ README \ TODO \ VERSION all: all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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 .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config/config.h: config/stamp-h1 @if test ! -f $@; then rm -f config/stamp-h1; else :; fi @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) config/stamp-h1; else :; fi config/stamp-h1: $(top_srcdir)/config/config.h.in $(top_builddir)/config.status @rm -f config/stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config/config.h $(top_srcdir)/config/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f config/stamp-h1 touch $@ distclean-hdr: -rm -f config/config.h config/stamp-h1 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. $(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ 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" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done cscopelist-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) 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; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ 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 CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ 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-recursive cscopelist cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ 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: $(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) | GZIP=$(GZIP_ENV) gzip -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-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -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*) \ GZIP=$(GZIP_ENV) gzip -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*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir); chmod u+w $(distdir) mkdir $(distdir)/_build mkdir $(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 \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(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." 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-hdr \ 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: 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: .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \ cscopelist-recursive ctags-recursive install-am install-strip \ tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am am--refresh check check-am clean clean-cscope \ clean-generic clean-libtool cscope cscopelist \ cscopelist-recursive ctags ctags-recursive dist dist-all \ dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ dist-xz \ dist-zip distcheck distclean distclean-generic distclean-hdr \ 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-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-recursive uninstall uninstall-am # 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: Index: user/alc/PQ_LAUNDRY/contrib/openbsm/NEWS =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/NEWS (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/NEWS (revision 292449) @@ -1,498 +1,507 @@ OpenBSM Version History +OpenBSM 1.2 alpha 4 + +- Fix praudit to emit correct XML. +- Fix auditdistd bugs related to IPv6 support, locking, and a kqueue-related + descriptor leak. +- Add audit event definitions for Capsicum-related syscalls, as well as + AUE_BINDAT and AUE_CONNECTAT. +- Manpage symlinks for all libbsm functions are installed again after the + move to autotools in OpenBSM 1.0 Alpha 5. +- A variety of minor documentation cleanups. + OpenBSM 1.2 alpha 3 - Various minor tweaks to the auditdistd build to make it fit the FreeBSD build environment better. - AUE_WAIT6 merged from FreeBSD 9. OpenBSM 1.2 alpha 2 - auditdistd, a distributed audit trail management daemon, has now been merged. This allows trail files to be securely and reliably synced from audited hosts to an audit server, and employs TLS encryption. Where available, it uses Capsicum to sandbox the service. This work was contributed by Pawel Jakub Dawidek under sponsorship from the FreeBSD Foundation. OpenBSM 1.2 alpha 1 - Add Capsicum-related error numbers for FreeBSD: ENOTCAPABLE, ECAPMODE. - Add Capsicum, process descriptor audit events for FreeBSD. - Allow 0% minspace. - Fixes from the clang static analyser. - Fix expiration of trail files when the host parameter is used. - Various typo fixes. - Support for Solaris privilege and privilege set tokens. - Documentation for getachost(), improvements for getacfilesz(). - Fix a directory descriptor leak that happened when audit trail partitions filled. - Support for more Linux distributions with a partial contemporary endian.h. - Improved escaping of XML-encapsulated BSM. - A variety of minor documentation, style, and functional. OpenBSM 1.1p2 - Fix audit_event definitions of AUE_OPENAT_RWT and AUE_OPENAT_RWTC. - Fix build on Linux. - Fix printing of class masks in the audump tool. OpenBSM 1.1p1 - Fixes to AUT_SOCKUNIX token parsing. - IPv6 support for au_to_me(3). - Improved robustness in the parsing of audit_control, especially long flags/naflags strings and whitespace in all fields. - Add missing conversion of a number of FreeBSD/Mac OS X errnos to/from BSM error number space. OpenBSM 1.1 - Change auditon(2) parameters and data structures to be 32/64-bit architecture independent. Add more information to man page about auditon(2) parameters. - Add wrapper functions for auditon(2) to use legacy commands when the new commands are not supported. - Add default for 'expire-after' in audit_control to expire trail files when the audit directory is more than 10 megabytes ('10M'). - Interface to convert between local and BSM fcntl(2) command values has been added: au_bsm_to_fcntl_cmd(3) and au_fcntl_cmd_to_bsm(3), along with definitions of constants in audit_fcntl.h. - A bug, introduced in OpenBSM 1.1 alpha 4, in which AUT_RETURN32 tokens generated by audit_submit(3) were improperly encoded has been fixed. - Fix example in audit_submit(3) man page. Also, make it clear that we want the audit ID as the argument. - A new audit event class 'aa', for post-login authentication and authorization events, has been added. OpenBSM 1.1 beta 1 - The filesz parameter in audit_control(5) now accepts suffixes: 'B' for Bytes, 'K' for Kilobytes, 'M' for Megabytes, and 'G' for Gigabytes. For legacy support no suffix defaults to bytes. - Audit trail log expiration support added. It is configured in audit_control(5) with the expire-after parameter. If there is no expire-after parameter in audit_control(5), the default, then the audit trail files are not expired and removed. See audit_control(5) for more information. - Change defaults in audit_control: warn at 5% rather than 20% free for audit partitions, rotate automatically at 2mb, and set the default policy to cnt,argv rather than cnt so that execve(2) arguments are captured if AUE_EXECVE events are audited. These may provide more usable defaults for many users. - Use au_domain_to_bsm(3) and au_socket_type_to_bsm(3) to convert au_to_socket_ex(3) arguments to BSM format. - Fix error encoding AUT_IPC_PERM tokens. OpenBSM 1.1 alpha 5 - Stub libauditd(3) man page added. - All BSM error number constants with BSM_ERRNO_. - Interfaces to convert between local and BSM socket types and protocol families have been added: au_bsm_to_domain(3), au_bsm_to_socket_type(3), au_domain_to_bsm(3), and au_socket_type_to_bsm(3), along with definitions of constants in audit_domain.h and audit_socket_type.h. This improves interoperability by converting local constant spaces, which vary by OS, to and from Solaris constants (where available) or OpenBSM constants for protocol domains not present in Solaris (a fair number). These routines should be used when generating and interpreting extended socket tokens. - Fix build warnings with full gcc warnings enabled on most supported platforms. - Don't compile error strings into bsm_errno.c when building it in the kernel environment. - When started by launchd, use the label com.apple.auditd rather than org.trustedbsd.auditd. OpenBSM 1.1 alpha 4 - With the addition of BSM error number mapping, we also need to map the local error number passed to audit_submit(3) to a BSM error number, rather than have the caller perform that conversion. - Reallocate user audit events to avoid collisions with Solaris; adopt a more formal allocation scheme, and add some events allocated in Solaris that will be of immediate use on other platforms. - Add an event for Calife. - Add au_strerror(3), which allows generating strings for BSM errors directly, rather than requiring applications to map to the local error space, which might not be able to entirely represent the BSM error number space. - Major auditd rewrite for launchd(8) support. Add libauditd library that is shared between launchd and auditd. - Add AUDIT_TRIGGER_INITIALIZE trigger (sent via 'audit -i') for (re)starting auditing under launchd(8) on Mac OS X. - Add 'current' symlink to active audit trail. - Add crash recovery of previous audit trail file when detected on audit startup that it has not been properly terminated. - Add the event AUE_audit_recovery to indicated when an audit trail file has been recovered from not being properly terminated. This event is stored in the new audit trail file and includes the path of recovered audit trail file. - Mac OS X and FreeBSD dependent code in auditd.c is separated into auditd_darwin.c and auditd_fbsd.c files. - Add an event for the posix_spawn(2) and fsgetpath(2) Mac OS X system calls. - For Mac OS X, we use ASL(3) instead of syslog(3) for logging. - Add support for NOTICE level logging. OpenBSM 1.1 alpha 3 - Add two new functions, au_bsm_to_errno() and au_errno_to_bsm(), to map between BSM error numbers (largely the Solaris definitions) and local errno(2) values for 32-bit and 64-bit return tokens. This is required as operating systems don't agree on some of the values of more recent error numbers. - Fix a bug how au_to_exec_args(3) and au_to_exec_env(3) calculates the total size for the token. This bug resulted in "unknown" tokens being printed after the exec args/env tokens. - Support for AUT_SOCKET_EX extended socket tokens, which describe a socket using a pair of IPv4/IPv6 and port tuples. - OpenBSM BSM file header version bumped for 1.1 release. - Deprecated Darwin constants, such as TRAILER_PAD_MAGIC, removed. OpenBSM 1.1 alpha 2 - Include files in OpenBSM are now broken out into two parts: library builds required solely for user space, and system includes, which may also be required for use in the kernels of systems integrating OpenBSM. Submitted by Stacey Son. - Configure option --with-native-includes allows forcing the use of native include for system includes, rather than the versions bundled with OpenBSM. This is intended specifically for platforms that ship OpenBSM, have adapted versions of the system includes in a kernel source tree, and will use the OpenBSM build infrastructure with an unmodified OpenBSM distribution, allowing the customized system includes to be used with the OpenBSM build. Submitted by Stacey Son. - Various strcpy()'s/strcat()'s have been changed to strlcpy()'s/strlcat()'s or asprintf(). Added compat/strlcpy.h for Linux. - Remove compatibility defines for old Darwin token constant names; now only BSM token names are provided and used. - Add support for extended header tokens, which contain space for information on the host generating the record. - Add support for setting extended host information in the kernel, which is used for setting host information in extended header tokens. The audit_control file now supports a "host" parameter which can be used by auditd to set the information; if not present, the kernel parameters won't be set and auditd uses unextended headers for records that it generates. OpenBSM 1.1 alpha 1 - Add option to auditreduce(1) which allows users to invert sense of matching, such that BSM records that do not match, are selected. - Fix bug in audit_write() where we commit an incomplete record in the event there is an error writing the subject token. This was submitted by Diego Giagio. - Build support for Mac OS X 10.5.1 submitted by Eric Hall. - Fix a bug which resulted in host XML attributes not being printed while processing extended header tokens. This patch was submitted by Martin Voros. - Constification of function arguments so that const strings can be passed as arguments to tokens. This patch was submitted by Xin LI. - Modify the -m option so users can select more then one audit event. - For Mac OS X, added Mach IPC support for audit trigger messages. - Fixed a bug in getacna() which resulted in a locking problem on Mac OS X. - Added LOG_PERROR flag to openlog when -d option is used with auditd. - AUE events added for Mac OS X Leopard system calls. OpenBSM 1.0 - Fix bug in auditreduce(1) which resulted in a memory fault/crash when the user specified an event name with -m. - Remove AU_.* hard-coded audit class constants, as audit classes are now entirely dynamically configured using /etc/security/audit_class. OpenBSM 1.0 alpha 15 - Fix bug when processing in_addr_ex tokens. - Restore the behavior of printing the string/text specified while auditing arg32 tokens. - Synchronized audit event list to Solaris, picking up the *at(2) system call definitions, now required for FreeBSD and Linux. Added additional events for *at(2) system calls not present in Solaris. - Bugs in auditreduce(1) fixed allowing partial date strings to be used in filtering events. OpenBSM 1.0 alpha 14 - Fix endian issues when processing IPv6 addresses for extended subject and process tokens. - gcc41 warnings clean. - Teach audit_submit(3) about getaudit_addr(2). - Add support for zonename tokens. OpenBSM 1.0 alpha 13 - compat/clock_gettime.h now provides a compatibility implementation of clock_gettime(), which fixes building on Mac OS X. - Countless man page improvements, markup fixes, content fixs, etc. - XML printing support via "praudit -x". - audit.log.5 expanded to include additional BSM token types. - Added encoding and decoding routines for process64_ex, process32_ex, subject32_ex, header64, and attr64 tokens. - Additional audit event identifiers for listen, mlockall/munlockall, getpath, POSIX message queues, and mandatory access control. OpenBSM 1.0 alpha 12 - Correct bug in auditreduce which prevented the -c option from working correctly when the user specifies to process successful or failed events. The problem stemmed from not having access to the return token at the time the initial preselection occurred, but now a second preselection process occurs while processing the return token. - getacfilesz(3) API added to read new audit_control(5) filesz setting, which auditd(8) now sets the kernel audit trail rotation size to. - auditreduce(1) now uses stdin if no file names are specified on the command line; this was the documented behavior previously, but it was not implemented. Be more specific in auditreduce(1)'s examples section about what might be done with the output of auditreduce. - Add audit_warn(5) closefile event so that administrators can hook termination of an audit trail file. For example, this might be used to compress the trail file after it is closed. - auditreduce(1) now uses regular expressions for pathname matching. Users can now supply one or more (comma delimited) regular expressions for searching the pathnames. If one of the regular expressions is prefixed with a tilde (~), and a path matches, it will be excluded from the search results. OpenBSM 1.0 alpha 11 - Reclassify certain read/write operations as having no class rather than the fr/fw class; our default classes audit intent (open) not operations (read, write). - Introduce AUE_SYSCTL_WRITE event so that BSD/Darwin systems can audit reads and writes of sysctls as separate events. Add additional kernel environment and jail events for FreeBSD. - Break AUDIT_TRIGGER_OPEN_NEW into two events, AUDIT_TRIGGER_ROTATE_USER (issued by the user audit(8) tool) and AUDIT_TRIGGER_ROTATE_KERNEL (issued by the kernel audit implementation) so that they can be distinguished. - Disable rate limiting of rotate requests; as the kernel doesn't retransmit a dropped request, the log file will otherwise grow indefinitely if the trigger is dropped. - Improve auditd debugging output. - Fix a number of threading related bugs in audit_control file reading routines. - Add APIs au_poltostr() and au_strtopol() to convert between text representations of audit_control policy flags and the flags passed to auditon(A_SETPOLICY) and retrieved from auditon(A_GETPOLICY). - Add API getacpol() to return the 'policy:' entry from audit_control, an extension to the Solaris file format to allow specification of policy persistent flags. - Update audump to print the audit_control policy field. - Update auditd to read the audit_control policy field and set the kernel policy to match it when configuring/reconfiguring. Remove the -s and -h arguments as these policies are now set via the configuration file. If a policy line is not found in the configuration file, continue with the current default of setting AUDIT_CNT. - Fix bugs in the parsing of large execve(2) arguments and environmental variable tokens; increase maximum parsed argument and variable count. - configure now detects strlcat(), used by policy-related functions. - Reference token and record sample files added to test tree. OpenBSM 1.0 alpha 10 - auditd now generates complete audit records for its events, as required for application-submitted audit records in the FreeBSD kernel audit implementation. OpenBSM 1.0 alpha 9 - Rename many OpenBSM-specific constants and API elements containing the strings "BSM" and "bsm" to "AUDIT" and "audit", observing that this is true for almost all existing constants and APIs. - Instead of passing a per-instance cookie directly into all audit filter APIs, pass in the audit filter daemon state pointer, which is then used by the module using an audit_filter_{get,set}cookie() API. This will allow future service APIs provided by the filter daemon to maintain their own state -- for example, per-module preselection state. OpenBSM 1.0 alpha 8 - Correct typo in definition of AUR_INT. - Adopt OpenSolaris constant values for AUDIT_* configuration flags. - Arguments to au_to_exec_args() and au_to_exec_env() no longer const. - Add kernel versions of au_to_exec_args() and au_to_exec_env(). - Fix exec argument type that is printed for env strings from 'arg' to 'env'. - New OpenBSM token version number assigned, constants added for other commonly seen version numbers. - OpenBSM-specific events assigned numbers in the 43xxx range to avoid future collisions with Solaris. Darwin events renamed to AUE_DARWIN_foo, as they are now deprecated numberings. - autoconf now detects clock_gettime(), which is not available on Darwin. - praudit output fixes relating to arg32 and arg64 tokens. - Maximum record size updated to 64k-1 to match Solaris record size limit. - Various style and comment cleanups in include files. OpenBSM 1.0 alpha 7 - Adopted Solaris-compatible format for subject32_ex and subject64_ex tokens, which previously did not correctly implement variable length address storage. - Prefer inttypes.h to stdint.h; enhance queue.h detection to test for TAILQ_FOREACH_SAFE(), which is present in recent BSD queue.h's, but not older ones. OpenBSM now builds on some FreeBSD 4.x versions. - New event types for extended attributes, ACLs, and scheduling. OpenBSM 1.0 alpha 6 - Use AU_TO_WRITE and AU_NO_TO_WRITE for the 'keep' argument to au_close(); previously we used hard-coded 0 and 1 values. - Add man page for au_open(), au_write(), au_close(), and au_close_buffer(). - Support a more complete range of data types for the arbitrary data token: add AUR_CHAR (alias to AUR_BYTE), remove AUR_LONG, add AUR_INT32 (alias to AUR_INT), add AUR_INT64. - Add au_close_token(), which allows writing a single token_t to a memory buffer. Not likely to be used much by applications, but useful for writing test tools. - Modify au_to_file() so that it accepts a timeval in user space, not just kernel -- this is not a Solaris BSM API so can be modified without causing compatibility issues. - Define a new API, au_to_header32_tm(), which adds a struct timeval argument to the ordinary au_to_header32(), which is now implemented by wrapping au_to_header32_tm() and calling gettimeofday(). #ifndef KERNEL the APIs that invoke gettimeofday(), rather than having a variable definition. Don't try to retrieve time zone information using gettimeofday(), as it's not needed, and introduces possible failure modes. - Don't perform byte order transformations on the addr/machine fields of the terminal ID that appears in the process32/subject32 tokens. These are assumed to be IP addresses, and as such, to be in network byte order. - Universally, APIs now assume that IP addresses and ports are provided in network byte order. APIs now generally provide these types in network byte order when decoding. - Beginnings of an OpenBSM test framework can now be found in openbsm/test. This code is not built or installed by default. - auditd now assigns more appropriate syslog levels to its debugging and error information. - Support for audit filters introduced: audit filters are dynamically loaded shared objects that run in the context of a new daemon, auditfilterd. The daemon reads from an audit pipe and feeds both BSM and parsed versions of records to shared objects using a module API. This will provide a framework for the writing of intrusion detection services. - New utility API, audit_submit(), added to capture common elements of audit record submission for many applications. OpenBSM 1.0 alpha 5 - Update install notes to indicate /etc files are to be installed manually. - On systems without LOG_SECURITY, use LOG_AUTH. - Convert to autoconf/automake in order to move to a more portable (not BSD-specific) build infrastructure, and more easy conditional building of components. Currently, the primary feature loss is that automake does not have native support for manual symlinks. This will be addressed in a future OpenBSM release. - Add compat/queue.h, to be used on systems dated BSD queue macro libraries (as found on Linux). - Rename CHANGELOG to HISTORY, as our change log doesn't follow some of the existing conventions for a CHANGELOG. - Some private data structures moved from audit.h to audit_internal.h to prevent inappropriate use by applications and name space pollution. - Improved detection and use of endian macros using autoconf. - Avoid non-portable use of struct in6_addr, which is largely opaque. - Avoid leaking BSD kernel socket related token code to user space in bsm_token.c. - Teach System V IPC calls to look for Linux naming variations for certain struct ipc_perm fields. - Test for audit system calls, and if not present, don't build bsm_wrappers.c, bsm_notify.c, audit(8), and auditd(8), which rely on those system calls. - au_close() is not implemented on systems that don't have audit system calls, but au_close_buffer() is. - Work around missing BSDisms in bsm_wrapper.c. - Fix nested includes so including libbsm.h in an application on Linux picks up the necessary definitions. OpenBSM 1.0 alpha 4 - Remove "audit" user example from audit_user, as it's not present on most systems. - Add cannot_audit() function non-Darwin systems that wraps auditon(); required by OpenSSH BSM support. Convert Darwin cannot_audit() into a function rather than a macro. - Library build fixed on Darwin following include file tweaks. The native Darwin sys/audit.h conflicts with bsm/audit.h due to duplicate types, so for now we force bsm_wrappers.c to not perform a nested include of sys/audit.h. OpenBSM 1.0 alpha 3 - Man page formatting, cross reference, mlinks, and accuracy improvements. - auditd and tools now compile and run on FreeBSD/arm. - auditd will now fchown() the trail file to the audit review group, if defined at compile-time. - Added AUE_SYSARCH for FreeBSD. - Definition of AUE_SETFSGID fixed for Linux. OpenBSM 1.0 alpha 2 - Man page formatting improvements. - A number of new audit event identifiers for FreeBSD, Linux, and POSIX.1b events. - Remove 'tfm' class, unused in OpenBSM. OpenBSM 1.0 alpha 1 - Import of Darwin74 BSM drop - Use 'syslog' for audit log warnings, rather than echoing to a file in audit_warn. - Compile using BSD make infrastructure. - Integrate bsm/ include files from Darwin74 XNU drop into OpenBSM. - Narrow set of symbols and defines that are exposed in user space: don't compile in code relying on kernel-only types such as 'struct socket'. - Add README, including basic build documentation. - Compilation of Apple-specific notify and Machroutines now #ifdef __APPLE__. - Staticize libbsm global variables to avoid leakage into applications. - Add free_au_user_ent() so that au_user_ent's don't have to be leaked. - Clean up bogus nul-termination checks in libbsm. - Add libbsm API man pages: au_class.3 au_control.3 au_event.3 au_free_token.3 au_io.3 au_mask.3 au_token.3 au_user.3 libbsm.3. - Add man pages for BSM system calls: audit.2 auditctl.2 auditon.2 getaudit.2 getauid.2 setaudit.2 setauid.2 - Modify various libbsm interfaces to more consistently return 'errno' values on failure. - Break out au_close() into constituent parts, allowing records to be written to memory as well as files. - Prefix various defines with 'BSM_' to reduce name space pollution. - Added audit_internal.h, which can be used by a kernel audit implementation wanting to rely on libbsm components. - Build with warnings, and eliminate warnings. - Make libbsm endian-independent, storing and reading BSM are big endian (network byte order) rather than native byte order. More consistently print IP addresses using the IP address print routine. These changes make use of sys/endian.h from *BSD; since this isn't present on Darwin, add it to OpenBSM as compat/endian.h, which is used only on Darwin. - Import of Darwin80 BSM drop, including 64-bit file IDs, better documentation of private APIs, and bug fixes. - White space cleanup. - Add audit.log.5, a first cut at a man page documenting the BSM file format. - Teach au_read_rec() to recognize stand-alone file tokens, which are present at the beginning and end of Solaris audit trails. Technically, these appear to violate the high level BSM spec, which suggests that all tokens are present in records, but need to be supported. - Implement HEADER64, ATTR64, SUBJECT64 token types, which make it possible to run praudit(1) on basic Solaris BSM streams. - Switched to Solaris spelling of token names; Darwin spellings are now deprecated and will be removed in a future version of OpenBSM. - Adopt Solaris model for representing IPv4 and IPv6 addresses. - Prefer C99 types. - Attempt to universally adopt the BSD style(9) coding style for consistency. - auditreduce(1) now has a usage message. - Update support for auditctl(2) system call to support FreeBSD. - Add support for /dev/audit as the trigger source on FreeBSD. - Add additional event types for Darwin, FreeBSD, and Solaris. Annotate conflicts (there are a few, unfortunately). Correct spellings, comment, sort, etc. These include {get,set}res[ug]id(), sendfile(), lchflags(), eaccess(), kqueue(), kevent(), poll(), lchmod(). - Relicensed under a BSD license, many thanks to Apple, Inc! - Many bug fixes, cleanups, thread safety in the class, control, event, and user system audit databases. Annotate some persisting atomicity bugs associated with the API and implementation. - Add audump test tool. - Adopt OpenSolaris BSM API memory semantics: caller allocates memory, or static memory is returned for non-_r() versions of API calls. _free() calls dropped as a result, and source code compatibility with OpenSolaris improved significantly. - Annotate BSM events with origin OS and compatibility information. - auditd(8), audit(8) added to the OpenBSM distribution. auditd extended to support reloading of kernel event table. - Allow comments in /etc/security configuration files. - -$P4: //depot/projects/trustedbsd/openbsm/NEWS#55 $ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/README =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/README (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/README (revision 292449) @@ -1,68 +1,66 @@ -OpenBSM 1.2a2 +OpenBSM Introduction OpenBSM is an open source implementation of Sun's BSM event auditing file format and API. Originally created for Apple Computer by McAfee Research, OpenBSM is now maintained by volunteers and through the generous contribution of several organizations. OpenBSM includes several command line tools, including auditreduce(8) and praudit(8) for reducing and printing audit trails, as well as the libbsm(3) library to manage configuration files, generate audit records, and parse and -print audit trils. +print audit trails. Coupled with a kernel audit implementation, OpenBSM can be used to maintain system audit streams, and is a foundation for a full audit-enabled system. Portions of OpenBSM, including include files and token-building routines, are reusable in a kernel audit implementation, and may be found in the FreeBSD and Mac OS X kernels. Contents OpenBSM consists of several directories: bin/ Audit-related command line tools bsm/ Library include files for BSM compat/ Compatibility code to build on various operating systems etc/ Sample /etc/security configuration files libauditd Common audit management functions for auditd and launchd libbsm/ Implementation of BSM library interfaces and man pages man/ System call and configuration file man pages modules/ Directory for auditfilterd module source sys/ System include files for BSM test/ Test token sets and geneneration program tools/ Tool directory, including audump to dump databases The following programs are included with OpenBSM: audit Command line audit control tool auditd Audit management daemon auditdistd Audit trail distribution daemon auditfilterd Experimental event monitoring framework auditreduce Audit trail reduction tool audump Debugging tool to parse and print audit databases praudit Tool to print audit trails Build and Installation Please see the file INSTALL for build and installation instructions. Contributions The TrustedBSD Project would appreciate the contribution of bug fixes, enhancements, etc, under identically or substantially similar licenses to those present on the remainder of the OpenBSM source code. Please see the file CREDITS to learn more about who has contributed to the project. Location Information on OpenBSM may be found on the OpenBSM home page: http://www.OpenBSM.org/ Information on TrustedBSD may be found on the TrustedBSD home page: http://www.TrustedBSD.org/ - -$P4: //depot/projects/trustedbsd/openbsm/README#41 $ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/TODO =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/TODO (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/TODO (revision 292449) @@ -1,27 +1,23 @@ OpenBSM TODO - Build a regression test suite for libbsm that generates each token type and then compares the results with known good data. Make sure to test that things work properly with respect to endianness of the local platform. - Document contents of libbsm "public" data structures in libbsm man pages. - The audit.log.5 man page is incomplete, as it does not describe all token types. -- With the move to autoconf/automake, man page symlinks are no longer - installed. This needs to be fixed. - It might be desirable to be able to provide EOPNOTSUPP system call stubs on systems that don't have the necessary audit system calls; that would allow the full libbsm and tool set to build, just not run. - Teach praudit how to begin printing at any point in a token stream, not just at the beginning of a record. This will make it easier to use praudit in test suites processing single-token files without header and trailer context. - Document audit_warn event arguments. - Allow the path /etc/security to be configured at configure-time so that alternative locations can be used. - NLS support for au_strerror(3), which provides error strings for BSM errors not available on the local OS platform. - Support for client certificates in auditdistd, to include certificate chain validation. - -$P4: //depot/projects/trustedbsd/openbsm/TODO#14 $ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/VERSION =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/VERSION (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/VERSION (revision 292449) @@ -1 +1 @@ -OPENBSM_1_2_alpha3 +OPENBSM_1_2_alpha4 Index: user/alc/PQ_LAUNDRY/contrib/openbsm/autogen.sh =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/autogen.sh (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/autogen.sh (revision 292449) @@ -1,10 +1,7 @@ #!/bin/sh -# -# $P4: //depot/projects/trustedbsd/openbsm/autogen.sh#2 $ -# libtoolize --copy --force aclocal autoheader automake -a -c --foreign autoconf Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/Makefile.am (revision 292449) @@ -1,15 +1,11 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/bin/Makefile.am#4 $ -## - SUBDIRS = \ auditdistd \ auditfilterd \ auditreduce \ praudit if HAVE_AUDIT_SYSCALLS SUBDIRS += \ audit \ auditd endif Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/audit/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/audit/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/audit/Makefile.am (revision 292449) @@ -1,23 +1,19 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/bin/audit/Makefile.am#7 $ -## - if USE_NATIVE_INCLUDES INCLUDES = -I$(top_builddir) -I$(top_srcdir) else INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys endif sbin_PROGRAMS = audit audit_LDADD = $(top_builddir)/libbsm/libbsm.la man8_MANS = audit.8 if USE_MACH_IPC audit_SOURCES = auditd_controlUser.c audit.c CLEANFILES = auditd_controlUser.c auditd_control.h auditd_controlUser.c auditd_control.h: $(top_srcdir)/bin/auditd/auditd_control.defs $(MIG) -user auditd_controlUser.c -header auditd_control.h -server /dev/null -sheader /dev/null $(top_srcdir)/bin/auditd/auditd_control.defs else audit_SOURCES = audit.c endif Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/audit/audit.8 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/audit/audit.8 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/audit/audit.8 (revision 292449) @@ -1,107 +1,105 @@ .\" Copyright (c) 2004-2009 Apple Inc. .\" 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY .\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED .\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE .\" DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY .\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES .\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; .\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND .\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/bin/audit/audit.8#16 $ -.\" -.Dd January 29, 2009 +.Dd July 25, 2015 .Dt AUDIT 8 .Os .Sh NAME .Nm audit .Nd audit management utility .Sh SYNOPSIS .Nm .Fl e | i | n | s | t .Sh DESCRIPTION The .Nm utility controls the state of the audit system. One of the following flags is required as an argument to .Nm : .Bl -tag -width indent .It Fl e Forces the audit system to immediately remove audit log files that meet the expiration criteria specified in the audit control file without doing a log rotation. .It Fl i Initializes and starts auditing. This option is currently for Mac OS X only and requires .Xr auditd 8 to be configured to run under .Xr launchd 8 . .It Fl n Forces the audit system to close the existing audit log file and rotate to a new log file in a location specified in the audit control file. Also, audit log files that meet the expiration criteria specified in the audit control file will be removed. .It Fl s Specifies that the audit system should [re]synchronize its configuration from the audit control file. A new log file will be created. .It Fl t Specifies that the audit system should terminate. Log files are closed and renamed to indicate the time of the shutdown. .El .Sh NOTES The .Xr auditd 8 daemon must already be running. Optionally, it can be configured to be started on-demand by .Xr launchd 8 (Mac OS X only). The .Nm utility requires audit administrator privileges for successful operation. .Sh FILES .Bl -tag -width ".Pa /etc/security/audit_control" -compact .It Pa /etc/security/audit_control Audit policy file used to configure the auditing system. .El .Sh SEE ALSO .Xr audit 4 , .Xr audit_control 5 , .Xr auditd 8 , -.Xr launchd 8 +.Xr launchd 8 (Mac OS X) .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer Inc. Additional authors include .An Wayne Salamon , .An Robert Watson , and SPARTA Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/audit/audit.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/audit/audit.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/audit/audit.c (revision 292449) @@ -1,181 +1,179 @@ /*- * Copyright (c) 2005-2009 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/audit/audit.c#15 $ */ /* * Program to trigger the audit daemon with a message that is either: * - Open a new audit log file * - Read the audit control file and take action on it * - Close the audit log file and exit * */ #include #include #ifdef HAVE_FULL_QUEUE_H #include #else /* !HAVE_FULL_QUEUE_H */ #include #endif /* !HAVE_FULL_QUEUE_H */ #include #include #include #include #include #include #include static int send_trigger(int); #ifdef USE_MACH_IPC #include #include #include #include #include #include #include #include "auditd_control.h" /* * XXX The following are temporary until these can be added to the kernel * audit.h header. */ #ifndef AUDIT_TRIGGER_INITIALIZE #define AUDIT_TRIGGER_INITIALIZE 7 #endif #ifndef AUDIT_TRIGGER_EXPIRE_TRAILS #define AUDIT_TRIGGER_EXPIRE_TRAILS 8 #endif static int send_trigger(int trigger) { mach_port_t serverPort; kern_return_t error; error = host_get_audit_control_port(mach_host_self(), &serverPort); if (error != KERN_SUCCESS) { if (geteuid() != 0) { errno = EPERM; perror("audit requires root privileges"); } else mach_error("Cannot get auditd_control Mach port:", error); return (-1); } error = auditd_control(serverPort, trigger); if (error != KERN_SUCCESS) { mach_error("Error sending trigger: ", error); return (-1); } return (0); } #else /* ! USE_MACH_IPC */ static int send_trigger(int trigger) { int error; error = audit_send_trigger(&trigger); if (error != 0) { if (error == EPERM) perror("audit requires root privileges"); else perror("Error sending trigger"); return (-1); } return (0); } #endif /* ! USE_MACH_IPC */ static void usage(void) { (void)fprintf(stderr, "Usage: audit -e | -i | -n | -s | -t \n"); exit(-1); } /* * Main routine to process command line options. */ int main(int argc, char **argv) { int ch; unsigned int trigger = 0; if (argc != 2) usage(); while ((ch = getopt(argc, argv, "einst")) != -1) { switch(ch) { case 'e': trigger = AUDIT_TRIGGER_EXPIRE_TRAILS; break; case 'i': trigger = AUDIT_TRIGGER_INITIALIZE; break; case 'n': trigger = AUDIT_TRIGGER_ROTATE_USER; break; case 's': trigger = AUDIT_TRIGGER_READ_FILE; break; case 't': trigger = AUDIT_TRIGGER_CLOSE_AND_DIE; break; case '?': default: usage(); break; } } if (send_trigger(trigger) < 0) exit(-1); printf("Trigger sent.\n"); exit (0); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/Makefile.am (revision 292449) @@ -1,26 +1,22 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/Makefile.am#6 $ -## - if USE_NATIVE_INCLUDES INCLUDES = -I$(top_builddir) -I$(top_srcdir) else INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys endif sbin_PROGRAMS = auditd auditd_LDADD = $(top_builddir)/libbsm/libbsm.la $(top_builddir)/libauditd/libauditd.la man8_MANS = auditd.8 if USE_MACH_IPC auditd_SOURCES = auditd_controlServer.c audit_triggersServer.c audit_warn.c auditd.c auditd_darwin.c CLEANFILES = auditd_control_server.c auditd_controlServer.h audit_triggersServer.c audit_triggersServer.h auditd_controlServer.c auditd_controlServer.h: auditd_control.defs $(MIG) -user /dev/null -header /dev/null -server auditd_controlServer.c -sheader auditd_controlServer.h $(top_srcdir)/bin/auditd/auditd_control.defs audit_triggersServer.c audit_triggersServer.h: audit_triggers.defs $(MIG) -user /dev/null -header /dev/null -server audit_triggersServer.c -sheader audit_triggersServer.h $(top_srcdir)/bin/auditd/audit_triggers.defs else auditd_SOURCES = audit_warn.c auditd.c auditd_fbsd.c endif Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/audit_triggers.defs =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/audit_triggers.defs (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/audit_triggers.defs (revision 292449) @@ -1,5 +1 @@ -/* - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/audit_triggers.defs#1 $ - */ - #include Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/audit_warn.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/audit_warn.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/audit_warn.c (revision 292449) @@ -1,253 +1,251 @@ /*- * Copyright (c) 2005-2009 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/audit_warn.c#11 $ */ #include #include #include #include #include "auditd.h" /* * Write an audit-related error to the system log via syslog(3). */ static int auditwarnlog(char *args[]) { char *loc_args[9]; pid_t pid; int i; loc_args[0] = AUDITWARN_SCRIPT; for (i = 0; args[i] != NULL && i < 8; i++) loc_args[i+1] = args[i]; loc_args[i+1] = NULL; pid = fork(); if (pid == -1) return (-1); if (pid == 0) { /* * Child. */ execv(AUDITWARN_SCRIPT, loc_args); syslog(LOG_ERR, "Could not exec %s (%m)\n", AUDITWARN_SCRIPT); exit(1); } /* * Parent. */ return (0); } /* * Indicates that the hard limit for all filesystems has been exceeded. */ int audit_warn_allhard(void) { char *args[2]; args[0] = HARDLIM_ALL_WARN; args[1] = NULL; return (auditwarnlog(args)); } /* * Indicates that the soft limit for all filesystems has been exceeded. */ int audit_warn_allsoft(void) { char *args[2]; args[0] = SOFTLIM_ALL_WARN; args[1] = NULL; return (auditwarnlog(args)); } /* * Indicates that someone other than the audit daemon turned off auditing. * XXX Its not clear at this point how this function will be invoked. * * XXXRW: This function is not used. */ int audit_warn_auditoff(void) { char *args[2]; args[0] = AUDITOFF_WARN; args[1] = NULL; return (auditwarnlog(args)); } /* * Indicate that a trail file has been closed, so can now be post-processed. */ int audit_warn_closefile(char *filename) { char *args[3]; args[0] = CLOSEFILE_WARN; args[1] = filename; args[2] = NULL; return (auditwarnlog(args)); } /* * Indicates that the audit deammn is already running */ int audit_warn_ebusy(void) { char *args[2]; args[0] = EBUSY_WARN; args[1] = NULL; return (auditwarnlog(args)); } /* * Indicates that there is a problem getting the directory from * audit_control. * * XXX Note that we take the filename instead of a count as the argument here * (different from BSM). */ int audit_warn_getacdir(char *filename) { char *args[3]; args[0] = GETACDIR_WARN; args[1] = filename; args[2] = NULL; return (auditwarnlog(args)); } /* * Indicates that the hard limit for this file has been exceeded. */ int audit_warn_hard(char *filename) { char *args[3]; args[0] = HARDLIM_WARN; args[1] = filename; args[2] = NULL; return (auditwarnlog(args)); } /* * Indicates that auditing could not be started. */ int audit_warn_nostart(void) { char *args[2]; args[0] = NOSTART_WARN; args[1] = NULL; return (auditwarnlog(args)); } /* * Indicaes that an error occrred during the orderly shutdown of the audit * daemon. */ int audit_warn_postsigterm(void) { char *args[2]; args[0] = POSTSIGTERM_WARN; args[1] = NULL; return (auditwarnlog(args)); } /* * Indicates that the soft limit for this file has been exceeded. */ int audit_warn_soft(char *filename) { char *args[3]; args[0] = SOFTLIM_WARN; args[1] = filename; args[2] = NULL; return (auditwarnlog(args)); } /* * Indicates that the temporary audit file already exists indicating a fatal * error. */ int audit_warn_tmpfile(void) { char *args[2]; args[0] = TMPFILE_WARN; args[1] = NULL; return (auditwarnlog(args)); } /* * Indicates that this trail file has expired and was removed. */ int audit_warn_expired(char *filename) { char *args[3]; args[0] = EXPIRED_WARN; args[1] = filename; args[2] = NULL; return (auditwarnlog(args)); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd.8 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd.8 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd.8 (revision 292449) @@ -1,142 +1,140 @@ .\" Copyright (c) 2004 Apple Inc. .\" 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY .\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED .\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE .\" DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY .\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES .\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; .\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND .\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.8#19 $ -.\" -.Dd December 11, 2008 +.Dd July 25, 2015 .Dt AUDITD 8 .Os .Sh NAME .Nm auditd .Nd audit log management daemon .Sh SYNOPSIS .Nm .Op Fl d | l .Sh DESCRIPTION The .Nm daemon responds to requests from the .Xr audit 8 utility and notifications from the kernel. It manages the resulting audit log files and specified log file locations. .Pp The options are as follows: .Bl -tag -width indent .It Fl d Starts the daemon in debug mode \[em] it will not daemonize. .It Fl l This option is for when .Nm is configured to start on-demand using .Xr launchd 8 . .El .Pp Optionally, the audit review group "audit" may be created. Non-privileged users that are members of this group may read the audit trail log files. .Sh NOTE To assure uninterrupted audit support, the .Nm daemon should not be started and stopped manually. Instead, the .Xr audit 8 command should be used to inform the daemon to change state/configuration after altering the .Pa audit_control file. .Pp If .Nm is started on-demand by .Xr launchd 8 then auditing should only be started and stopped with .Xr audit 8 . .Pp On Mac OS X, .Nm uses the .Xr asl 3 API for writing system log messages. Therefore, only the audit administrator and members of the audit review group will be able to read the system log entries. .Sh FILES .Bl -tag -width ".Pa /etc/security" -compact .It Pa /var/audit Default directory for storing audit log files. .Pp .It Pa /etc/security The directory containing the auditing configuration files .Xr audit_class 5 , .Xr audit_control 5 , .Xr audit_event 5 , and .Xr audit_warn 5 . .El .Sh COMPATIBILITY The historical .Fl h and .Fl s flags are now configured using .Xr audit_control 5 policy flags .Cm ahlt and .Cm cnt , and are no longer available as arguments to .Nm . .Sh SEE ALSO .Xr asl 3 , .Xr libauditd 3 , .Xr audit 4 , .Xr audit_class 5 , .Xr audit_control 5 , .Xr audit_event 5 , .Xr audit_warn 5 , .Xr audit 8 , .Xr auditdistd 8 , -.Xr launchd 8 +.Xr launchd 8 (Mac OS X) .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer Inc. Additional authors include .An Wayne Salamon , .An Robert Watson , and SPARTA Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd.c (revision 292449) @@ -1,852 +1,850 @@ /*- * Copyright (c) 2004-2009 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#50 $ */ #include #include #include #ifdef HAVE_FULL_QUEUE_H #include #else /* !HAVE_FULL_QUEUE_H */ #include #endif /* !HAVE_FULL_QUEUE_H */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "auditd.h" #ifndef HAVE_STRLCPY #include #endif /* * XXX The following are temporary until these can be added to the kernel * audit.h header. */ #ifndef AUDIT_TRIGGER_INITIALIZE #define AUDIT_TRIGGER_INITIALIZE 7 #endif #ifndef AUDIT_TRIGGER_EXPIRE_TRAILS #define AUDIT_TRIGGER_EXPIRE_TRAILS 8 #endif /* * LaunchD flag (Mac OS X and, maybe, FreeBSD only.) See launchd(8) and * http://wiki.freebsd.org/launchd for more information. * * In order for auditd to work "on demand" with launchd(8) it can't: * call daemon(3) * call fork and having the parent process exit * change uids or gids. * set up the current working directory or chroot. * set the session id * change stdio to /dev/null. * call setrusage(2) * call setpriority(2) * Ignore SIGTERM. * auditd (in 'launchd mode') is launched on demand so it must catch * SIGTERM to exit cleanly. */ static int launchd_flag = 0; /* * The GID of the audit review group (if used). The audit trail files and * system logs (Mac OS X only) can only be reviewed by members of this group * or the audit administrator (aka. "root"). */ static gid_t audit_review_gid = -1; /* * The path and file name of the last audit trail file. */ static char *lastfile = NULL; /* * Error starting auditd. Run warn script and exit. */ static void fail_exit(void) { audit_warn_nostart(); exit(1); } /* * Follow the 'current' symlink to get the active trail file name. */ static char * get_curfile(void) { char *cf; int len; cf = malloc(MAXPATHLEN); if (cf == NULL) { auditd_log_err("malloc failed: %m"); return (NULL); } len = readlink(AUDIT_CURRENT_LINK, cf, MAXPATHLEN - 1); if (len < 0) { free(cf); return (NULL); } /* readlink() doesn't terminate string. */ cf[len] = '\0'; return (cf); } /* * Close the previous audit trail file. */ static int close_lastfile(char *TS) { char *ptr; char *oldname; /* If lastfile is NULL try to get it from the 'current' link. */ if (lastfile == NULL) lastfile = get_curfile(); if (lastfile != NULL) { oldname = strdup(lastfile); if (oldname == NULL) return (-1); /* Rename the last file -- append timestamp. */ if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) { memcpy(ptr, TS, POSTFIX_LEN); if (auditd_rename(oldname, lastfile) != 0) auditd_log_err( "Could not rename %s to %s: %m", oldname, lastfile); else { /* * Remove the 'current' symlink since the link * is now invalid. */ (void) unlink(AUDIT_CURRENT_LINK); auditd_log_notice("renamed %s to %s", oldname, lastfile); audit_warn_closefile(lastfile); } } else auditd_log_err("Could not rename %s to %s", oldname, lastfile); free(lastfile); free(oldname); lastfile = NULL; } return (0); } /* * Create the new file name, swap with existing audit file. */ static int swap_audit_file(void) { int err; char *newfile, *name; char TS[TIMESTAMP_LEN + 1]; time_t tt; if (getTSstr(tt, TS, sizeof(TS)) != 0) return (-1); /* * If prefix and suffix are the same, it means that records are * being produced too fast. We don't want to rename now, because * next trail file can get the same name and once that one is * terminated also within one second it will overwrite the current * one. Just keep writing to the same trail and wait for the next * trigger from the kernel. * FREEBSD KERNEL WAS UPDATED TO KEEP SENDING TRIGGERS, WHICH MIGHT * NOT BE THE CASE FOR OTHER OSES. * If the kernel will not keep sending triggers, trail file will not * be terminated. */ if (lastfile == NULL) { name = NULL; } else { name = strrchr(lastfile, '/'); if (name != NULL) name++; } if (name != NULL && strncmp(name, TS, TIMESTAMP_LEN) == 0) { auditd_log_debug("Not ready to terminate trail file yet."); return (0); } err = auditd_swap_trail(TS, &newfile, audit_review_gid, audit_warn_getacdir); if (err != ADE_NOERR) { auditd_log_err("%s: %m", auditd_strerror(err)); if (err != ADE_ACTL) return (-1); } /* * Only close the last file if were in an auditing state before * calling swap_audit_file(). We may need to recover from a crash. */ if (auditd_get_state() == AUD_STATE_ENABLED) close_lastfile(TS); /* * auditd_swap_trail() potentially enables auditing (if not already * enabled) so updated the cached state as well. */ auditd_set_state(AUD_STATE_ENABLED); /* * Create 'current' symlink. Recover from crash, if needed. */ if (auditd_new_curlink(newfile) != 0) auditd_log_err("auditd_new_curlink(\"%s\") failed: %s: %m", newfile, auditd_strerror(err)); lastfile = newfile; auditd_log_notice("New audit file is %s", newfile); return (0); } /* * Create a new audit log trail file and swap with the current one, if any. */ static int do_trail_file(void) { int err; /* * First, refresh the list of audit log directories. */ err = auditd_read_dirs(audit_warn_soft, audit_warn_hard); if (err) { auditd_log_err("auditd_read_dirs(): %s", auditd_strerror(err)); if (err == ADE_HARDLIM) audit_warn_allhard(); if (err != ADE_SOFTLIM) return (-1); else audit_warn_allsoft(); /* continue on with soft limit error */ } /* * Create a new file and swap with the one being used in kernel. */ if (swap_audit_file() == -1) { /* * XXX Faulty directory listing? - user should be given * XXX an opportunity to change the audit_control file * XXX switch to a reduced mode of auditing? */ return (-1); } /* * Finally, see if there are any trail files to expire. */ err = auditd_expire_trails(audit_warn_expired); if (err) auditd_log_err("auditd_expire_trails(): %s", auditd_strerror(err)); return (0); } /* * Start up auditing. */ static void audit_setup(void) { int err; /* Configure trail files distribution. */ err = auditd_set_dist(); if (err) { auditd_log_err("auditd_set_dist() %s: %m", auditd_strerror(err)); } else auditd_log_debug("Configured trail files distribution."); if (do_trail_file() == -1) { auditd_log_err("Error creating audit trail file"); fail_exit(); } /* Generate an audit record. */ err = auditd_gen_record(AUE_audit_startup, NULL); if (err) auditd_log_err("auditd_gen_record(AUE_audit_startup) %s: %m", auditd_strerror(err)); if (auditd_config_controls() == 0) auditd_log_info("Audit controls init successful"); else auditd_log_err("Audit controls init failed"); } /* * Close auditd pid file and trigger mechanism. */ static int close_misc(void) { auditd_close_dirs(); if (unlink(AUDITD_PIDFILE) == -1 && errno != ENOENT) { auditd_log_err("Couldn't remove %s: %m", AUDITD_PIDFILE); return (1); } endac(); if (auditd_close_trigger() != 0) { auditd_log_err("Error closing trigger messaging mechanism"); return (1); } return (0); } /* * Close all log files, control files, and tell the audit system. */ static int close_all(void) { int err_ret = 0; char TS[TIMESTAMP_LEN + 1]; int err; int cond; time_t tt; err = auditd_gen_record(AUE_audit_shutdown, NULL); if (err) auditd_log_err("auditd_gen_record(AUE_audit_shutdown) %s: %m", auditd_strerror(err)); /* Flush contents. */ cond = AUC_DISABLED; err_ret = audit_set_cond(&cond); if (err_ret != 0) { auditd_log_err("Disabling audit failed! : %s", strerror(errno)); err_ret = 1; } /* * Updated the cached state that auditing has been disabled. */ auditd_set_state(AUD_STATE_DISABLED); if (getTSstr(tt, TS, sizeof(TS)) == 0) close_lastfile(TS); if (lastfile != NULL) free(lastfile); err_ret += close_misc(); if (err_ret) { auditd_log_err("Could not unregister"); audit_warn_postsigterm(); } auditd_log_info("Finished"); return (err_ret); } /* * Register the daemon with the signal handler and the auditd pid file. */ static int register_daemon(void) { FILE * pidfile; int fd; pid_t pid; /* Set up the signal hander. */ if (signal(SIGTERM, auditd_relay_signal) == SIG_ERR) { auditd_log_err( "Could not set signal handler for SIGTERM"); fail_exit(); } if (signal(SIGCHLD, auditd_relay_signal) == SIG_ERR) { auditd_log_err( "Could not set signal handler for SIGCHLD"); fail_exit(); } if (signal(SIGHUP, auditd_relay_signal) == SIG_ERR) { auditd_log_err( "Could not set signal handler for SIGHUP"); fail_exit(); } if (signal(SIGALRM, auditd_relay_signal) == SIG_ERR) { auditd_log_err( "Could not set signal handler for SIGALRM"); fail_exit(); } if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) { auditd_log_err("Could not open PID file"); audit_warn_tmpfile(); return (-1); } /* Attempt to lock the pid file; if a lock is present, exit. */ fd = fileno(pidfile); if (flock(fd, LOCK_EX | LOCK_NB) < 0) { auditd_log_err( "PID file is locked (is another auditd running?)."); audit_warn_ebusy(); return (-1); } pid = getpid(); ftruncate(fd, 0); if (fprintf(pidfile, "%u\n", pid) < 0) { /* Should not start the daemon. */ fail_exit(); } fflush(pidfile); return (0); } /* * Handle the audit trigger event. * * We suppress (ignore) duplicated triggers in close succession in order to * try to avoid thrashing-like behavior. However, not all triggers can be * ignored, as triggers generally represent edge triggers, not level * triggers, and won't be retransmitted if the condition persists. Of * specific concern is the rotate trigger -- if one is dropped, then it will * not be retransmitted, and the log file will grow in an unbounded fashion. */ #define DUPLICATE_INTERVAL 30 void auditd_handle_trigger(int trigger) { static int last_trigger, last_warning; static time_t last_time; struct timeval ts; struct timezone tzp; time_t tt; int au_state; int err = 0; /* * Suppress duplicate messages from the kernel within the specified * interval. */ if (gettimeofday(&ts, &tzp) == 0) { tt = (time_t)ts.tv_sec; switch (trigger) { case AUDIT_TRIGGER_LOW_SPACE: case AUDIT_TRIGGER_NO_SPACE: /* * Triggers we can suppress. Of course, we also need * to rate limit the warnings, so apply the same * interval limit on syslog messages. */ if ((trigger == last_trigger) && (tt < (last_time + DUPLICATE_INTERVAL))) { if (tt >= (last_warning + DUPLICATE_INTERVAL)) auditd_log_info( "Suppressing duplicate trigger %d", trigger); return; } last_warning = tt; break; case AUDIT_TRIGGER_ROTATE_KERNEL: case AUDIT_TRIGGER_ROTATE_USER: case AUDIT_TRIGGER_READ_FILE: case AUDIT_TRIGGER_CLOSE_AND_DIE: case AUDIT_TRIGGER_INITIALIZE: /* * Triggers that we cannot suppress. */ break; } /* * Only update last_trigger after aborting due to a duplicate * trigger, not before, or we will never allow that trigger * again. */ last_trigger = trigger; last_time = tt; } au_state = auditd_get_state(); /* * Message processing is done here. */ switch(trigger) { case AUDIT_TRIGGER_LOW_SPACE: auditd_log_notice("Got low space trigger"); if (do_trail_file() == -1) auditd_log_err("Error swapping audit file"); break; case AUDIT_TRIGGER_NO_SPACE: auditd_log_notice("Got no space trigger"); if (do_trail_file() == -1) auditd_log_err("Error swapping audit file"); break; case AUDIT_TRIGGER_ROTATE_KERNEL: case AUDIT_TRIGGER_ROTATE_USER: auditd_log_info("Got open new trigger from %s", trigger == AUDIT_TRIGGER_ROTATE_KERNEL ? "kernel" : "user"); if (au_state == AUD_STATE_ENABLED && do_trail_file() == -1) auditd_log_err("Error swapping audit file"); break; case AUDIT_TRIGGER_READ_FILE: auditd_log_info("Got read file trigger"); if (au_state == AUD_STATE_ENABLED) { if (auditd_config_controls() == -1) auditd_log_err("Error setting audit controls"); else if (do_trail_file() == -1) auditd_log_err("Error swapping audit file"); } break; case AUDIT_TRIGGER_CLOSE_AND_DIE: auditd_log_info("Got close and die trigger"); if (au_state == AUD_STATE_ENABLED) err = close_all(); /* * Running under launchd don't exit. Wait for launchd to * send SIGTERM. */ if (!launchd_flag) { auditd_log_info("auditd exiting."); exit (err); } break; case AUDIT_TRIGGER_INITIALIZE: auditd_log_info("Got audit initialize trigger"); if (au_state == AUD_STATE_DISABLED) audit_setup(); break; case AUDIT_TRIGGER_EXPIRE_TRAILS: auditd_log_info("Got audit expire trails trigger"); err = auditd_expire_trails(audit_warn_expired); if (err) auditd_log_err("auditd_expire_trails(): %s", auditd_strerror(err)); break; default: auditd_log_err("Got unknown trigger %d", trigger); break; } } /* * Reap our children. */ void auditd_reap_children(void) { pid_t child; int wstatus; while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) { if (!wstatus) continue; auditd_log_info("warn process [pid=%d] %s %d.", child, ((WIFEXITED(wstatus)) ? "exited with non-zero status" : "exited as a result of signal"), ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) : WTERMSIG(wstatus))); } } /* * Reap any children and terminate. If under launchd don't shutdown auditing * but just the other stuff. */ void auditd_terminate(void) { int ret; auditd_reap_children(); if (launchd_flag) ret = close_misc(); else ret = close_all(); exit(ret); } /* * Configure the audit controls in the kernel: the event to class mapping, * kernel preselection mask, etc. */ int auditd_config_controls(void) { int cnt, err; int ret = 0; /* * Configure event to class mappings in kernel. */ cnt = auditd_set_evcmap(); if (cnt < 0) { auditd_log_err("auditd_set_evcmap() failed: %m"); ret = -1; } else if (cnt == 0) { auditd_log_err("No events to class mappings registered."); ret = -1; } else auditd_log_debug("Registered %d event to class mappings.", cnt); /* * Configure non-attributable event mask in kernel. */ err = auditd_set_namask(); if (err) { auditd_log_err("auditd_set_namask() %s: %m", auditd_strerror(err)); ret = -1; } else auditd_log_debug("Registered non-attributable event mask."); /* * Configure audit policy in kernel. */ err = auditd_set_policy(); if (err) { auditd_log_err("auditd_set_policy() %s: %m", auditd_strerror(err)); ret = -1; } else auditd_log_debug("Set audit policy in kernel."); /* * Configure audit trail log size in kernel. */ err = auditd_set_fsize(); if (err) { auditd_log_err("audit_set_fsize() %s: %m", auditd_strerror(err)); ret = -1; } else auditd_log_debug("Set audit trail size in kernel."); /* * Configure audit trail volume minimum free percentage of blocks in * kernel. */ err = auditd_set_minfree(); if (err) { auditd_log_err("auditd_set_minfree() %s: %m", auditd_strerror(err)); ret = -1; } else auditd_log_debug( "Set audit trail min free percent in kernel."); /* * Configure host address in the audit kernel information. */ err = auditd_set_host(); if (err) { if (err == ADE_PARSE) { auditd_log_notice( "audit_control(5) may be missing 'host:' field"); } else { auditd_log_err("auditd_set_host() %s: %m", auditd_strerror(err)); ret = -1; } } else auditd_log_debug( "Set audit host address information in kernel."); return (ret); } /* * Setup and initialize auditd. */ static void setup(void) { int err; if (auditd_open_trigger(launchd_flag) < 0) { auditd_log_err("Error opening trigger messaging mechanism"); fail_exit(); } /* * To prevent event feedback cycles and avoid auditd becoming * stalled if auditing is suspended, auditd and its children run * without their events being audited. We allow the uid, tid, and * mask fields to be implicitly set to zero, but do set the pid. We * run this after opening the trigger device to avoid configuring * audit state without audit present in the system. */ err = auditd_prevent_audit(); if (err) { auditd_log_err("auditd_prevent_audit() %s: %m", auditd_strerror(err)); fail_exit(); } /* * Make sure auditd auditing state is correct. */ auditd_set_state(AUD_STATE_INIT); /* * If under launchd, don't start auditing. Wait for a trigger to * do so. */ if (!launchd_flag) audit_setup(); } int main(int argc, char **argv) { int ch; int debug = 0; #ifdef AUDIT_REVIEW_GROUP struct group *grp; #endif while ((ch = getopt(argc, argv, "dl")) != -1) { switch(ch) { case 'd': /* Debug option. */ debug = 1; break; case 'l': /* Be launchd friendly. */ launchd_flag = 1; break; case '?': default: (void)fprintf(stderr, "usage: auditd [-d] [-l]\n"); exit(1); } } audit_review_gid = getgid(); #ifdef AUDIT_REVIEW_GROUP /* * XXXRW: Currently, this code falls back to the daemon gid, which is * likely the wheel group. Is there a better way to deal with this? */ grp = getgrnam(AUDIT_REVIEW_GROUP); if (grp != NULL) audit_review_gid = grp->gr_gid; #endif auditd_openlog(debug, audit_review_gid); if (launchd_flag) auditd_log_info("started by launchd..."); else auditd_log_info("starting..."); #ifdef AUDIT_REVIEW_GROUP if (grp == NULL) auditd_log_info( "Audit review group '%s' not available, using daemon gid (%d)", AUDIT_REVIEW_GROUP, audit_review_gid); #endif if (debug == 0 && launchd_flag == 0 && daemon(0, 0) == -1) { auditd_log_err("Failed to daemonize"); exit(1); } if (register_daemon() == -1) { auditd_log_err("Could not register as daemon"); exit(1); } setup(); /* * auditd_wait_for_events() shouldn't return unless something is wrong. */ auditd_wait_for_events(); auditd_log_err("abnormal exit."); close_all(); exit(-1); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd.h (revision 292449) @@ -1,102 +1,100 @@ /*- * Copyright (c) 2005-2009 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.h#13 $ */ #ifndef _AUDITD_H_ #define _AUDITD_H_ #include #include #include #define MAX_DIR_SIZE 255 #define AUDITD_NAME "auditd" /* * If defined, then the audit daemon will attempt to chown newly created logs * to this group. Otherwise, they will be the default for the user running * auditd, likely the audit group. */ #define AUDIT_REVIEW_GROUP "audit" #define HARDLIM_ALL_WARN "allhard" #define SOFTLIM_ALL_WARN "allsoft" #define AUDITOFF_WARN "auditoff" #define CLOSEFILE_WARN "closefile" #define EBUSY_WARN "ebusy" #define GETACDIR_WARN "getacdir" #define HARDLIM_WARN "hard" #define NOSTART_WARN "nostart" #define POSTSIGTERM_WARN "postsigterm" #define SOFTLIM_WARN "soft" #define TMPFILE_WARN "tmpfile" #define EXPIRED_WARN "expired" #define AUDITWARN_SCRIPT "/etc/security/audit_warn" #define AUDITD_PIDFILE "/var/run/auditd.pid" #define AUD_STATE_INIT -1 #define AUD_STATE_DISABLED 0 #define AUD_STATE_ENABLED 1 int audit_warn_allhard(void); int audit_warn_allsoft(void); int audit_warn_auditoff(void); int audit_warn_closefile(char *filename); int audit_warn_ebusy(void); int audit_warn_getacdir(char *filename); int audit_warn_hard(char *filename); int audit_warn_nostart(void); int audit_warn_postsigterm(void); int audit_warn_soft(char *filename); int audit_warn_tmpfile(void); int audit_warn_expired(char *filename); void auditd_openlog(int debug, gid_t gid); void auditd_log_err(const char *fmt, ...); void auditd_log_debug(const char *fmt, ...); void auditd_log_info(const char *fmt, ...); void auditd_log_notice(const char *fmt, ...); void auditd_set_state(int state); int auditd_get_state(void); int auditd_open_trigger(int launchd_flag); int auditd_close_trigger(void); void auditd_handle_trigger(int trigger); void auditd_wait_for_events(void); void auditd_relay_signal(int signal); void auditd_terminate(void); int auditd_config_controls(void); void auditd_reap_children(void); #endif /* !_AUDITD_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd_control.defs =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd_control.defs (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd_control.defs (revision 292449) @@ -1,49 +1,47 @@ /*- * Copyright (c) 1999-2007 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd_control.defs#2 $ */ /* * Exported client calls to the auditd facility. */ Subsystem KernelUser auditd_control 456; #ifndef __MigTypeCheck #define __MigTypeCheck 1 #endif #include #include simpleroutine auditd_control( auditd_port : mach_port_t; in trigger : int); Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd_darwin.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd_darwin.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd_darwin.c (revision 292449) @@ -1,484 +1,482 @@ /*- * Copyright (c) 2004-2009 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd_darwin.c#5 $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "auditd.h" #include "auditd_controlServer.h" #include "audit_triggersServer.h" /* * Apple System Logger Handles. */ static aslmsg au_aslmsg = NULL; static aslclient au_aslclient = NULL; static mach_port_t control_port = MACH_PORT_NULL; static mach_port_t signal_port = MACH_PORT_NULL; static mach_port_t port_set = MACH_PORT_NULL; /* * Current auditing state (cache). */ static int auditing_state = AUD_STATE_INIT; /* * Maximum idle time before auditd terminates under launchd. * If it is zero then auditd does not timeout while idle. */ static int max_idletime = 0; #ifndef __BSM_INTERNAL_NOTIFY_KEY #define __BSM_INTERNAL_NOTIFY_KEY "com.apple.audit.change" #endif /* __BSM_INTERNAL_NOTIFY_KEY */ #ifndef __AUDIT_LAUNCHD_LABEL #define __AUDIT_LAUNCHD_LABEL "com.apple.auditd" #endif /* __AUDIT_LAUNCHD_LABEL */ #define MAX_MSG_SIZE 4096 /* * Open and set up system logging. */ void auditd_openlog(int debug, gid_t gid) { uint32_t opt = 0; char *cp = NULL; if (debug) opt = ASL_OPT_STDERR; au_aslclient = asl_open("auditd", "com.apple.auditd", opt); au_aslmsg = asl_new(ASL_TYPE_MSG); #ifdef ASL_KEY_READ_UID /* * Make it only so the audit administrator and members of the audit * review group (if used) have access to the auditd system log messages. */ asl_set(au_aslmsg, ASL_KEY_READ_UID, "0"); asprintf(&cp, "%u", gid); if (cp != NULL) { #ifdef ASL_KEY_READ_GID asl_set(au_aslmsg, ASL_KEY_READ_GID, cp); #endif free(cp); } #endif /* * Set the client-side system log filtering. */ if (debug) asl_set_filter(au_aslclient, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG)); else asl_set_filter(au_aslclient, ASL_FILTER_MASK_UPTO(ASL_LEVEL_INFO)); } /* * Log messages at different priority levels. */ void auditd_log_err(const char *fmt, ...) { va_list ap; va_start(ap, fmt); asl_vlog(au_aslclient, au_aslmsg, ASL_LEVEL_ERR, fmt, ap); va_end(ap); } void auditd_log_notice(const char *fmt, ...) { va_list ap; va_start(ap, fmt); asl_vlog(au_aslclient, au_aslmsg, ASL_LEVEL_NOTICE, fmt, ap); va_end(ap); } void auditd_log_info(const char *fmt, ...) { va_list ap; va_start(ap, fmt); asl_vlog(au_aslclient, au_aslmsg, ASL_LEVEL_INFO, fmt, ap); va_end(ap); } void auditd_log_debug(const char *fmt, ...) { va_list ap; va_start(ap, fmt); asl_vlog(au_aslclient, au_aslmsg, ASL_LEVEL_DEBUG, fmt, ap); va_end(ap); } /* * Get the auditing state from the kernel and cache it. */ static void init_audit_state(void) { int au_cond; if (audit_get_cond(&au_cond) < 0) { if (errno != ENOSYS) { auditd_log_err("Audit status check failed (%s)", strerror(errno)); } auditing_state = AUD_STATE_DISABLED; } else if (au_cond == AUC_NOAUDIT || au_cond == AUC_DISABLED) auditing_state = AUD_STATE_DISABLED; else auditing_state = AUD_STATE_ENABLED; } /* * Update the cached auditing state. Let other tasks that may be caching it * as well to update their state via notify(3). */ void auditd_set_state(int state) { int old_auditing_state = auditing_state; if (state == AUD_STATE_INIT) init_audit_state(); else auditing_state = state; if (auditing_state != old_auditing_state) { notify_post(__BSM_INTERNAL_NOTIFY_KEY); if (auditing_state == AUD_STATE_ENABLED) auditd_log_notice("Auditing enabled"); if (auditing_state == AUD_STATE_DISABLED) auditd_log_notice("Auditing disabled"); } } /* * Get the cached auditing state. */ int auditd_get_state(void) { if (auditing_state == AUD_STATE_INIT) { init_audit_state(); notify_post(__BSM_INTERNAL_NOTIFY_KEY); } return (auditing_state); } /* * Lookup the audit mach port in the launchd dictionary. */ static mach_port_t lookup_machport(const char *label) { launch_data_t msg, msd, ld, cdict, to; mach_port_t mp = MACH_PORT_NULL; msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); cdict = launch_msg(msg); if (cdict == NULL) { auditd_log_err("launch_msg(\"" LAUNCH_KEY_CHECKIN "\") IPC failure: %m"); return (MACH_PORT_NULL); } if (launch_data_get_type(cdict) == LAUNCH_DATA_ERRNO) { errno = launch_data_get_errno(cdict); auditd_log_err("launch_data_get_type() can't get dict: %m"); return (MACH_PORT_NULL); } to = launch_data_dict_lookup(cdict, LAUNCH_JOBKEY_TIMEOUT); if (to) { max_idletime = launch_data_get_integer(to); auditd_log_debug("launchd timeout set to %d", max_idletime); } else { auditd_log_debug("launchd timeout not set, setting to 60"); max_idletime = 60; } msd = launch_data_dict_lookup(cdict, LAUNCH_JOBKEY_MACHSERVICES); if (msd == NULL) { auditd_log_err( "launch_data_dict_lookup() can't get mach services"); return (MACH_PORT_NULL); } ld = launch_data_dict_lookup(msd, label); if (ld == NULL) { auditd_log_err("launch_data_dict_lookup can't find %s", label); return (MACH_PORT_NULL); } mp = launch_data_get_machport(ld); return (mp); } static int mach_setup(int launchd_flag) { mach_msg_type_name_t poly; /* * Allocate a port set. */ if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &port_set) != KERN_SUCCESS) { auditd_log_err("Allocation of port set failed"); return (-1); } /* * Allocate a signal reflection port. */ if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &signal_port) != KERN_SUCCESS || mach_port_move_member(mach_task_self(), signal_port, port_set) != KERN_SUCCESS) { auditd_log_err("Allocation of signal port failed"); return (-1); } /* * Allocate a trigger port. */ if (launchd_flag) { /* * If started under launchd, lookup port in launchd dictionary. */ if ((control_port = lookup_machport(__AUDIT_LAUNCHD_LABEL)) == MACH_PORT_NULL || mach_port_move_member(mach_task_self(), control_port, port_set) != KERN_SUCCESS) { auditd_log_err("Cannot get Mach control port" " via launchd"); return (-1); } else auditd_log_debug("Mach control port registered" " via launchd"); } else { /* * If not started under launchd, allocate port and register. */ if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &control_port) != KERN_SUCCESS || mach_port_move_member(mach_task_self(), control_port, port_set) != KERN_SUCCESS) auditd_log_err("Allocation of trigger port failed"); /* * Create a send right on our trigger port. */ mach_port_extract_right(mach_task_self(), control_port, MACH_MSG_TYPE_MAKE_SEND, &control_port, &poly); /* * Register the trigger port with the kernel. */ if (host_set_audit_control_port(mach_host_self(), control_port) != KERN_SUCCESS) { auditd_log_err("Cannot set Mach control port"); return (-1); } else auditd_log_debug("Mach control port registered"); } return (0); } /* * Open the trigger messaging mechanism. */ int auditd_open_trigger(int launchd_flag) { return (mach_setup(launchd_flag)); } /* * Close the trigger messaging mechanism. */ int auditd_close_trigger(void) { return (0); } /* * Combined server handler. Called by the mach message loop when there is * a trigger or signal message. */ static boolean_t auditd_combined_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP) { mach_port_t local_port = InHeadP->msgh_local_port; /* Reset the idle time alarm, if used. */ if (max_idletime) alarm(max_idletime); if (local_port == signal_port) { int signo = InHeadP->msgh_id; switch(signo) { case SIGTERM: case SIGALRM: auditd_terminate(); /* Not reached. */ case SIGCHLD: auditd_reap_children(); return (TRUE); case SIGHUP: auditd_config_controls(); return (TRUE); default: auditd_log_info("Received signal %d", signo); return (TRUE); } } else if (local_port == control_port) { boolean_t result; result = audit_triggers_server(InHeadP, OutHeadP); if (!result) result = auditd_control_server(InHeadP, OutHeadP); return (result); } auditd_log_info("Recevied msg on bad port 0x%x.", local_port); return (FALSE); } /* * The main event loop. Wait for trigger messages or signals and handle them. * It should not return unless there is a problem. */ void auditd_wait_for_events(void) { kern_return_t result; /* * Call the mach messaging server loop. */ result = mach_msg_server(auditd_combined_server, MAX_MSG_SIZE, port_set, MACH_MSG_OPTION_NONE); } /* * Implementation of the audit_triggers() MIG simpleroutine. Simply a * wrapper function. This handles input from the kernel on the host * special mach port. */ kern_return_t audit_triggers(mach_port_t __unused audit_port, int trigger) { auditd_handle_trigger(trigger); return (KERN_SUCCESS); } /* * Implementation of the auditd_control() MIG simpleroutine. Simply a * wrapper function. This handles input from the audit(1) tool. */ kern_return_t auditd_control(mach_port_t __unused auditd_port, int trigger) { auditd_handle_trigger(trigger); return (KERN_SUCCESS); } /* * When we get a signal, we are often not at a clean point. So, little can * be done in the signal handler itself. Instead, we send a message to the * main servicing loop to do proper handling from a non-signal-handler * context. */ void auditd_relay_signal(int signal) { mach_msg_empty_send_t msg; msg.header.msgh_id = signal; msg.header.msgh_remote_port = signal_port; msg.header.msgh_local_port = MACH_PORT_NULL; msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0); mach_msg(&(msg.header), MACH_SEND_MSG|MACH_SEND_TIMEOUT, sizeof(msg), 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd_fbsd.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd_fbsd.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditd/auditd_fbsd.c (revision 292449) @@ -1,274 +1,272 @@ /*- * Copyright (c) 2004-2009 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd_fbsd.c#4 $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "auditd.h" /* * Current auditing state (cache). */ static int auditing_state = AUD_STATE_INIT; /* * Maximum idle time before auditd terminates under launchd. * If it is zero then auditd does not timeout while idle. */ static int max_idletime = 0; static int sigchlds, sigchlds_handled; static int sighups, sighups_handled; static int sigterms, sigterms_handled; static int sigalrms, sigalrms_handled; static int triggerfd = 0; /* * Open and set up system logging. */ void auditd_openlog(int debug, gid_t __unused gid) { int logopts = LOG_CONS | LOG_PID; if (debug) logopts |= LOG_PERROR; #ifdef LOG_SECURITY openlog("auditd", logopts, LOG_SECURITY); #else openlog("auditd", logopts, LOG_AUTH); #endif } /* * Log messages at different priority levels. */ void auditd_log_err(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vsyslog(LOG_ERR, fmt, ap); va_end(ap); } void auditd_log_notice(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vsyslog(LOG_NOTICE, fmt, ap); va_end(ap); } void auditd_log_info(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vsyslog(LOG_INFO, fmt, ap); va_end(ap); } void auditd_log_debug(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vsyslog(LOG_DEBUG, fmt, ap); va_end(ap); } /* * Get the auditing state from the kernel and cache it. */ static void init_audit_state(void) { int au_cond; if (audit_get_cond(&au_cond) < 0) { if (errno != ENOSYS) { auditd_log_err("Audit status check failed (%s)", strerror(errno)); } auditing_state = AUD_STATE_DISABLED; } else if (au_cond == AUC_NOAUDIT || au_cond == AUC_DISABLED) auditing_state = AUD_STATE_DISABLED; else auditing_state = AUD_STATE_ENABLED; } /* * Update the cached auditing state. */ void auditd_set_state(int state) { int old_auditing_state = auditing_state; if (state == AUD_STATE_INIT) init_audit_state(); else auditing_state = state; if (auditing_state != old_auditing_state) { if (auditing_state == AUD_STATE_ENABLED) auditd_log_notice("Auditing enabled"); if (auditing_state == AUD_STATE_DISABLED) auditd_log_notice("Auditing disabled"); } } /* * Get the cached auditing state. */ int auditd_get_state(void) { if (auditing_state == AUD_STATE_INIT) init_audit_state(); return (auditing_state); } /* * Open the trigger messaging mechanism. */ int auditd_open_trigger(int __unused launchd_flag) { return ((triggerfd = open(AUDIT_TRIGGER_FILE, O_RDONLY, 0))); } /* * Close the trigger messaging mechanism. */ int auditd_close_trigger(void) { return (close(triggerfd)); } /* * The main event loop. Wait for trigger messages or signals and handle them. * It should not return unless there is a problem. */ void auditd_wait_for_events(void) { int num; unsigned int trigger; for (;;) { num = read(triggerfd, &trigger, sizeof(trigger)); if ((num == -1) && (errno != EINTR)) { auditd_log_err("%s: error %d", __FUNCTION__, errno); return; } /* Reset the idle time alarm, if used. */ if (max_idletime) alarm(max_idletime); if (sigterms != sigterms_handled) { auditd_log_debug("%s: SIGTERM", __FUNCTION__); auditd_terminate(); /* not reached */ } if (sigalrms != sigalrms_handled) { auditd_log_debug("%s: SIGALRM", __FUNCTION__); auditd_terminate(); /* not reached */ } if (sigchlds != sigchlds_handled) { sigchlds_handled = sigchlds; auditd_reap_children(); } if (sighups != sighups_handled) { auditd_log_debug("%s: SIGHUP", __FUNCTION__); sighups_handled = sighups; auditd_config_controls(); } if ((num == -1) && (errno == EINTR)) continue; if (num == 0) { auditd_log_err("%s: read EOF", __FUNCTION__); return; } auditd_handle_trigger(trigger); } } /* * When we get a signal, we are often not at a clean point. So, little can * be done in the signal handler itself. Instead, we send a message to the * main servicing loop to do proper handling from a non-signal-handler * context. */ void auditd_relay_signal(int signal) { if (signal == SIGHUP) sighups++; if (signal == SIGTERM) sigterms++; if (signal == SIGCHLD) sigchlds++; if (signal == SIGALRM) sigalrms++; } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/Makefile.am (revision 292449) @@ -1,33 +1,29 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/Makefile.am#1 $ -## - if USE_NATIVE_INCLUDES INCLUDES = -I$(top_builddir) -I$(top_srcdir) else INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys endif sbin_PROGRAMS = auditdistd man5_MANS = auditdistd.conf.5 man8_MANS = auditdistd.8 CFLAGS = -Wno-format YFLAGS = -d auditdistd_LDFLAGS = -lcrypto auditdistd_SOURCES = \ auditdistd.c \ parse.y \ pjdlog.c \ proto.c \ proto_common.c \ proto_socketpair.c \ proto_tcp.c \ proto_tls.c \ proto_uds.c \ receiver.c \ sandbox.c \ sender.c \ subr.c \ token.l \ trail.c Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/auditdistd.8 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/auditdistd.8 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/auditdistd.8 (revision 292449) @@ -1,106 +1,106 @@ .\" Copyright (c) 2012 The FreeBSD Foundation .\" All rights reserved. .\" .\" This documentation was written by Pawel Jakub Dawidek under sponsorship .\" from the FreeBSD Foundation. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" .Dd March 5, 2012 .Dt AUDITDISTD 8 .Os .Sh NAME .Nm auditdistd .Nd "Audit trail files distribution daemon" .Sh SYNOPSIS .Nm .Op Fl dFhl .Op Fl c Ar config .Op Fl P Ar pidfile .Sh DESCRIPTION The .Nm -daemon is responsible for distributing audit trail files over TCP/IP network in +daemon is responsible for distributing audit trail files over a TCP/IP network in a secure and reliable way. .Pp The .Nm daemon can be started with the following command line arguments: .Bl -tag -width ".Fl P Ar pidfile" .It Fl c Ar config -Specify alternative location of the configuration file. +Specify an alternative location of the configuration file. The default location is .Pa /etc/security/auditdistd.conf . Note: the configuration file may contain passwords. Care should be taken to configure proper permissions on this file .Li ( eg. 0600 ) . .It Fl d Print or log debugging information. This option can be specified multiple times to raise the verbosity level. .It Fl F Start the .Nm daemon in the foreground. By default .Nm starts in the background. .It Fl h Print the .Nm usage message. .It Fl l Start in a launchd-friendly mode, ie. do not use .Xr daemon 3 . .It Fl P Ar pidfile -Specify alternative location of a file where main process PID will be +Specify an alternative location of a file where main process PID will be stored. The default location is .Pa /var/run/auditdistd.pid . .El .Sh FILES .Bl -tag -width ".Pa /etc/security/auditdistd.conf" -compact .It Pa /etc/security/auditdistd.conf The configuration file for .Nm . .It Pa /var/run/auditdistd.pid The default location of the .Nm PID file. .El .Sh EXIT STATUS Exit status is 0 on success, or one of the values described in .Xr sysexits 3 on failure. .Sh SEE ALSO .Xr sysexits 3 , .Xr audit 4 , .Xr auditdistd.conf 5 , .Xr auditd 8 .Sh AUTHORS The .Nm was developed by .An Pawel Jakub Dawidek Aq pawel@dawidek.net under sponsorship of the FreeBSD Foundation. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/auditdistd.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/auditdistd.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/auditdistd.c (revision 292449) @@ -1,800 +1,798 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/auditdistd.c#3 $ */ #include #include #if defined(HAVE_SYS_ENDIAN_H) && defined(HAVE_BSWAP) #include #else /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */ #ifdef HAVE_MACHINE_ENDIAN_H #include #else /* !HAVE_MACHINE_ENDIAN_H */ #ifdef HAVE_ENDIAN_H #include #else /* !HAVE_ENDIAN_H */ #error "No supported endian.h" #endif /* !HAVE_ENDIAN_H */ #endif /* !HAVE_MACHINE_ENDIAN_H */ #include #endif /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */ #include #include #include #include #include #include #ifdef HAVE_LIBUTIL_H #include #endif #include #include #include #include #include #include #include #ifndef HAVE_PIDFILE_OPEN #include #endif #ifndef HAVE_STRLCPY #include #endif #ifndef HAVE_SIGTIMEDWAIT #include "sigtimedwait.h" #endif #include "auditdistd.h" #include "pjdlog.h" #include "proto.h" #include "subr.h" #include "synch.h" /* Path to configuration file. */ const char *cfgpath = ADIST_CONFIG; /* Auditdistd configuration. */ static struct adist_config *adcfg; /* Was SIGINT or SIGTERM signal received? */ bool sigexit_received = false; /* PID file handle. */ struct pidfh *pfh; /* How often check for hooks running for too long. */ #define SIGNALS_CHECK_INTERVAL 5 static void usage(void) { errx(EX_USAGE, "[-dFhl] [-c config] [-P pidfile]"); } void descriptors_cleanup(struct adist_host *adhost) { struct adist_host *adh; struct adist_listen *lst; TAILQ_FOREACH(adh, &adcfg->adc_hosts, adh_next) { if (adh == adhost) continue; if (adh->adh_remote != NULL) { proto_close(adh->adh_remote); adh->adh_remote = NULL; } } TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) { if (lst->adl_conn != NULL) proto_close(lst->adl_conn); } (void)pidfile_close(pfh); pjdlog_fini(); } static void child_cleanup(struct adist_host *adhost) { if (adhost->adh_conn != NULL) { PJDLOG_ASSERT(adhost->adh_role == ADIST_ROLE_SENDER); proto_close(adhost->adh_conn); adhost->adh_conn = NULL; } adhost->adh_worker_pid = 0; } static void child_exit_log(const char *type, unsigned int pid, int status) { if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { pjdlog_debug(1, "%s process exited gracefully (pid=%u).", type, pid); } else if (WIFSIGNALED(status)) { pjdlog_error("%s process killed (pid=%u, signal=%d).", type, pid, WTERMSIG(status)); } else { pjdlog_error("%s process exited ungracefully (pid=%u, exitcode=%d).", type, pid, WIFEXITED(status) ? WEXITSTATUS(status) : -1); } } static void child_exit(void) { struct adist_host *adhost; bool restart; int status; pid_t pid; restart = false; while ((pid = wait3(&status, WNOHANG, NULL)) > 0) { /* Find host related to the process that just exited. */ TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { if (pid == adhost->adh_worker_pid) break; } if (adhost == NULL) { child_exit_log("Sandbox", pid, status); } else { if (adhost->adh_role == ADIST_ROLE_SENDER) restart = true; pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, role2str(adhost->adh_role)); child_exit_log("Worker", pid, status); child_cleanup(adhost); pjdlog_prefix_set("%s", ""); } } if (!restart) return; /* We have some sender processes to restart. */ sleep(1); TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { if (adhost->adh_role != ADIST_ROLE_SENDER) continue; if (adhost->adh_worker_pid != 0) continue; pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, role2str(adhost->adh_role)); pjdlog_info("Restarting sender process."); adist_sender(adcfg, adhost); pjdlog_prefix_set("%s", ""); } } /* TODO */ static void adist_reload(void) { pjdlog_info("Reloading configuration is not yet implemented."); } static void terminate_workers(void) { struct adist_host *adhost; pjdlog_info("Termination signal received, exiting."); TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { if (adhost->adh_worker_pid == 0) continue; pjdlog_info("Terminating worker process (adhost=%s, role=%s, pid=%u).", adhost->adh_name, role2str(adhost->adh_role), adhost->adh_worker_pid); if (kill(adhost->adh_worker_pid, SIGTERM) == 0) continue; pjdlog_errno(LOG_WARNING, "Unable to send signal to worker process (adhost=%s, role=%s, pid=%u).", adhost->adh_name, role2str(adhost->adh_role), adhost->adh_worker_pid); } } static void listen_accept(struct adist_listen *lst) { unsigned char rnd[32], hash[32], resp[32]; struct adist_host *adhost; struct proto_conn *conn; char adname[ADIST_HOSTSIZE]; char laddr[256], raddr[256]; char welcome[8]; int status, version; pid_t pid; proto_local_address(lst->adl_conn, laddr, sizeof(laddr)); pjdlog_debug(1, "Accepting connection to %s.", laddr); if (proto_accept(lst->adl_conn, &conn) == -1) { pjdlog_errno(LOG_ERR, "Unable to accept connection to %s", laddr); return; } proto_local_address(conn, laddr, sizeof(laddr)); proto_remote_address(conn, raddr, sizeof(raddr)); pjdlog_info("Connection from %s to %s.", raddr, laddr); /* Error in setting timeout is not critical, but why should it fail? */ if (proto_timeout(conn, ADIST_TIMEOUT) < 0) pjdlog_errno(LOG_WARNING, "Unable to set connection timeout"); /* * Before receiving any data see if remote host is known. */ TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { if (adhost->adh_role != ADIST_ROLE_RECEIVER) continue; if (!proto_address_match(conn, adhost->adh_remoteaddr)) continue; break; } if (adhost == NULL) { pjdlog_error("Client %s is not known.", raddr); goto close; } /* Ok, remote host is known. */ /* Exchange welcome message, which include version number. */ bzero(welcome, sizeof(welcome)); if (proto_recv(conn, welcome, sizeof(welcome)) == -1) { pjdlog_errno(LOG_WARNING, "Unable to receive welcome message from %s", adhost->adh_remoteaddr); goto close; } if (strncmp(welcome, "ADIST", 5) != 0 || !isdigit(welcome[5]) || !isdigit(welcome[6]) || welcome[7] != '\0') { pjdlog_warning("Invalid welcome message from %s.", adhost->adh_remoteaddr); goto close; } version = MIN(ADIST_VERSION, atoi(welcome + 5)); (void)snprintf(welcome, sizeof(welcome), "ADIST%02d", version); if (proto_send(conn, welcome, sizeof(welcome)) == -1) { pjdlog_errno(LOG_WARNING, "Unable to send welcome message to %s", adhost->adh_remoteaddr); goto close; } if (proto_recv(conn, adname, sizeof(adhost->adh_name)) < 0) { pjdlog_errno(LOG_ERR, "Unable to receive hostname from %s", raddr); goto close; } /* Find host now that we have hostname. */ TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { if (adhost->adh_role != ADIST_ROLE_RECEIVER) continue; if (!proto_address_match(conn, adhost->adh_remoteaddr)) continue; if (strcmp(adhost->adh_name, adname) != 0) continue; break; } if (adhost == NULL) { pjdlog_error("No configuration for host %s from address %s.", adname, raddr); goto close; } adhost->adh_version = version; pjdlog_debug(1, "Version %d negotiated with %s.", adhost->adh_version, adhost->adh_remoteaddr); /* Now that we know host name setup log prefix. */ pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, role2str(adhost->adh_role)); if (adist_random(rnd, sizeof(rnd)) == -1) { pjdlog_error("Unable to generate challenge."); goto close; } pjdlog_debug(1, "Challenge generated."); if (proto_send(conn, rnd, sizeof(rnd)) == -1) { pjdlog_errno(LOG_ERR, "Unable to send challenge to %s", adhost->adh_remoteaddr); goto close; } pjdlog_debug(1, "Challenge sent."); if (proto_recv(conn, resp, sizeof(resp)) == -1) { pjdlog_errno(LOG_ERR, "Unable to receive response from %s", adhost->adh_remoteaddr); goto close; } pjdlog_debug(1, "Response received."); if (HMAC(EVP_sha256(), adhost->adh_password, (int)strlen(adhost->adh_password), rnd, (int)sizeof(rnd), hash, NULL) == NULL) { pjdlog_error("Unable to generate hash."); goto close; } pjdlog_debug(1, "Hash generated."); if (memcmp(resp, hash, sizeof(hash)) != 0) { pjdlog_error("Invalid response from %s (wrong password?).", adhost->adh_remoteaddr); goto close; } pjdlog_info("Sender authenticated."); if (proto_recv(conn, rnd, sizeof(rnd)) == -1) { pjdlog_errno(LOG_ERR, "Unable to receive challenge from %s", adhost->adh_remoteaddr); goto close; } pjdlog_debug(1, "Challenge received."); if (HMAC(EVP_sha256(), adhost->adh_password, (int)strlen(adhost->adh_password), rnd, (int)sizeof(rnd), hash, NULL) == NULL) { pjdlog_error("Unable to generate response."); goto close; } pjdlog_debug(1, "Response generated."); if (proto_send(conn, hash, sizeof(hash)) == -1) { pjdlog_errno(LOG_ERR, "Unable to send response to %s", adhost->adh_remoteaddr); goto close; } pjdlog_debug(1, "Response sent."); if (adhost->adh_worker_pid != 0) { pjdlog_debug(1, "Receiver process exists (pid=%u), stopping it.", (unsigned int)adhost->adh_worker_pid); /* Stop child process. */ if (kill(adhost->adh_worker_pid, SIGINT) == -1) { pjdlog_errno(LOG_ERR, "Unable to stop worker process (pid=%u)", (unsigned int)adhost->adh_worker_pid); /* * Other than logging the problem we * ignore it - nothing smart to do. */ } /* Wait for it to exit. */ else if ((pid = waitpid(adhost->adh_worker_pid, &status, 0)) != adhost->adh_worker_pid) { /* We can only log the problem. */ pjdlog_errno(LOG_ERR, "Waiting for worker process (pid=%u) failed", (unsigned int)adhost->adh_worker_pid); } else { child_exit_log("Worker", adhost->adh_worker_pid, status); } child_cleanup(adhost); } adhost->adh_remote = conn; adist_receiver(adcfg, adhost); pjdlog_prefix_set("%s", ""); return; close: proto_close(conn); pjdlog_prefix_set("%s", ""); } static void connection_migrate(struct adist_host *adhost) { struct proto_conn *conn; int16_t val = 0; pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, role2str(adhost->adh_role)); PJDLOG_ASSERT(adhost->adh_role == ADIST_ROLE_SENDER); if (proto_recv(adhost->adh_conn, &val, sizeof(val)) < 0) { pjdlog_errno(LOG_WARNING, "Unable to receive connection command"); return; } if (proto_set("tls:fingerprint", adhost->adh_fingerprint) == -1) { val = errno; pjdlog_errno(LOG_WARNING, "Unable to set fingerprint"); goto out; } if (proto_connect(adhost->adh_localaddr[0] != '\0' ? adhost->adh_localaddr : NULL, adhost->adh_remoteaddr, -1, &conn) < 0) { val = errno; pjdlog_errno(LOG_WARNING, "Unable to connect to %s", adhost->adh_remoteaddr); goto out; } val = 0; out: if (proto_send(adhost->adh_conn, &val, sizeof(val)) < 0) { pjdlog_errno(LOG_WARNING, "Unable to send reply to connection request"); } if (val == 0 && proto_connection_send(adhost->adh_conn, conn) < 0) pjdlog_errno(LOG_WARNING, "Unable to send connection"); pjdlog_prefix_set("%s", ""); } static void check_signals(void) { struct timespec sigtimeout; sigset_t mask; int signo; sigtimeout.tv_sec = 0; sigtimeout.tv_nsec = 0; PJDLOG_VERIFY(sigemptyset(&mask) == 0); PJDLOG_VERIFY(sigaddset(&mask, SIGHUP) == 0); PJDLOG_VERIFY(sigaddset(&mask, SIGINT) == 0); PJDLOG_VERIFY(sigaddset(&mask, SIGTERM) == 0); PJDLOG_VERIFY(sigaddset(&mask, SIGCHLD) == 0); while ((signo = sigtimedwait(&mask, NULL, &sigtimeout)) != -1) { switch (signo) { case SIGINT: case SIGTERM: sigexit_received = true; terminate_workers(); exit(EX_OK); break; case SIGCHLD: child_exit(); break; case SIGHUP: adist_reload(); break; default: PJDLOG_ABORT("Unexpected signal (%d).", signo); } } } static void main_loop(void) { struct adist_host *adhost; struct adist_listen *lst; struct timeval seltimeout; int fd, maxfd, ret; fd_set rfds; seltimeout.tv_sec = SIGNALS_CHECK_INTERVAL; seltimeout.tv_usec = 0; pjdlog_info("Started successfully."); for (;;) { check_signals(); /* Setup descriptors for select(2). */ FD_ZERO(&rfds); maxfd = -1; TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) { if (lst->adl_conn == NULL) continue; fd = proto_descriptor(lst->adl_conn); PJDLOG_ASSERT(fd >= 0); FD_SET(fd, &rfds); maxfd = fd > maxfd ? fd : maxfd; } TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { if (adhost->adh_role == ADIST_ROLE_SENDER) { /* Only sender workers asks for connections. */ PJDLOG_ASSERT(adhost->adh_conn != NULL); fd = proto_descriptor(adhost->adh_conn); PJDLOG_ASSERT(fd >= 0); FD_SET(fd, &rfds); maxfd = fd > maxfd ? fd : maxfd; } else { PJDLOG_ASSERT(adhost->adh_conn == NULL); } } PJDLOG_ASSERT(maxfd + 1 <= (int)FD_SETSIZE); ret = select(maxfd + 1, &rfds, NULL, NULL, &seltimeout); if (ret == 0) { /* * select(2) timed out, so there should be no * descriptors to check. */ continue; } else if (ret == -1) { if (errno == EINTR) continue; KEEP_ERRNO((void)pidfile_remove(pfh)); pjdlog_exit(EX_OSERR, "select() failed"); } PJDLOG_ASSERT(ret > 0); /* * Check for signals before we do anything to update our * info about terminated workers in the meantime. */ check_signals(); TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) { if (lst->adl_conn == NULL) continue; if (FD_ISSET(proto_descriptor(lst->adl_conn), &rfds)) listen_accept(lst); } TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { if (adhost->adh_role == ADIST_ROLE_SENDER) { PJDLOG_ASSERT(adhost->adh_conn != NULL); if (FD_ISSET(proto_descriptor(adhost->adh_conn), &rfds)) { connection_migrate(adhost); } } else { PJDLOG_ASSERT(adhost->adh_conn == NULL); } } } } static void adist_config_dump(struct adist_config *cfg) { struct adist_host *adhost; struct adist_listen *lst; pjdlog_debug(2, "Configuration:"); pjdlog_debug(2, " Global:"); pjdlog_debug(2, " pidfile: %s", cfg->adc_pidfile); pjdlog_debug(2, " timeout: %d", cfg->adc_timeout); if (TAILQ_EMPTY(&cfg->adc_listen)) { pjdlog_debug(2, " Sender only, not listening."); } else { pjdlog_debug(2, " Listening on:"); TAILQ_FOREACH(lst, &cfg->adc_listen, adl_next) { pjdlog_debug(2, " listen: %s", lst->adl_addr); pjdlog_debug(2, " conn: %p", lst->adl_conn); } } pjdlog_debug(2, " Hosts:"); TAILQ_FOREACH(adhost, &cfg->adc_hosts, adh_next) { pjdlog_debug(2, " name: %s", adhost->adh_name); pjdlog_debug(2, " role: %s", role2str(adhost->adh_role)); pjdlog_debug(2, " version: %d", adhost->adh_version); pjdlog_debug(2, " localaddr: %s", adhost->adh_localaddr); pjdlog_debug(2, " remoteaddr: %s", adhost->adh_remoteaddr); pjdlog_debug(2, " remote: %p", adhost->adh_remote); pjdlog_debug(2, " directory: %s", adhost->adh_directory); pjdlog_debug(2, " compression: %d", adhost->adh_compression); pjdlog_debug(2, " checksum: %d", adhost->adh_checksum); pjdlog_debug(2, " pid: %ld", (long)adhost->adh_worker_pid); pjdlog_debug(2, " conn: %p", adhost->adh_conn); } } static void dummy_sighandler(int sig __unused) { /* Nothing to do. */ } int main(int argc, char *argv[]) { struct adist_host *adhost; struct adist_listen *lst; const char *execpath, *pidfile; bool foreground, launchd; pid_t otherpid; int debuglevel; sigset_t mask; execpath = argv[0]; if (execpath[0] != '/') { errx(EX_USAGE, "auditdistd requires execution with an absolute path."); } /* * We are executed from proto to create sandbox. */ if (argc > 1 && strcmp(argv[1], "proto") == 0) { argc -= 2; argv += 2; if (proto_exec(argc, argv) == -1) err(EX_USAGE, "Unable to execute proto"); } foreground = false; debuglevel = 0; launchd = false; pidfile = NULL; for (;;) { int ch; ch = getopt(argc, argv, "c:dFhlP:"); if (ch == -1) break; switch (ch) { case 'c': cfgpath = optarg; break; case 'd': debuglevel++; break; case 'F': foreground = true; break; case 'l': launchd = true; break; case 'P': pidfile = optarg; break; case 'h': default: usage(); } } argc -= optind; argv += optind; pjdlog_init(PJDLOG_MODE_STD); pjdlog_debug_set(debuglevel); if (proto_set("execpath", execpath) == -1) pjdlog_exit(EX_TEMPFAIL, "Unable to set executable name"); if (proto_set("user", ADIST_USER) == -1) pjdlog_exit(EX_TEMPFAIL, "Unable to set proto user"); if (proto_set("tcp:port", ADIST_TCP_PORT) == -1) pjdlog_exit(EX_TEMPFAIL, "Unable to set default TCP port"); /* * When path to the configuration file is relative, obtain full path, * so we can always find the file, even after daemonizing and changing * working directory to /. */ if (cfgpath[0] != '/') { const char *newcfgpath; newcfgpath = realpath(cfgpath, NULL); if (newcfgpath == NULL) { pjdlog_exit(EX_CONFIG, "Unable to obtain full path of %s", cfgpath); } cfgpath = newcfgpath; } adcfg = yy_config_parse(cfgpath, true); PJDLOG_ASSERT(adcfg != NULL); adist_config_dump(adcfg); if (proto_set("tls:certfile", adcfg->adc_certfile) == -1) pjdlog_exit(EX_TEMPFAIL, "Unable to set certfile path"); if (proto_set("tls:keyfile", adcfg->adc_keyfile) == -1) pjdlog_exit(EX_TEMPFAIL, "Unable to set keyfile path"); if (pidfile != NULL) { if (strlcpy(adcfg->adc_pidfile, pidfile, sizeof(adcfg->adc_pidfile)) >= sizeof(adcfg->adc_pidfile)) { pjdlog_exitx(EX_CONFIG, "Pidfile path is too long."); } } if (foreground && pidfile == NULL) { pfh = NULL; } else { pfh = pidfile_open(adcfg->adc_pidfile, 0600, &otherpid); if (pfh == NULL) { if (errno == EEXIST) { pjdlog_exitx(EX_TEMPFAIL, "Another auditdistd is already running, pid: %jd.", (intmax_t)otherpid); } /* * If we cannot create pidfile from other reasons, * only warn. */ pjdlog_errno(LOG_WARNING, "Unable to open or create pidfile %s", adcfg->adc_pidfile); } } /* * Restore default actions for interesting signals in case parent * process (like init(8)) decided to ignore some of them (like SIGHUP). */ PJDLOG_VERIFY(signal(SIGHUP, SIG_DFL) != SIG_ERR); PJDLOG_VERIFY(signal(SIGINT, SIG_DFL) != SIG_ERR); PJDLOG_VERIFY(signal(SIGTERM, SIG_DFL) != SIG_ERR); /* * Because SIGCHLD is ignored by default, setup dummy handler for it, * so we can mask it. */ PJDLOG_VERIFY(signal(SIGCHLD, dummy_sighandler) != SIG_ERR); PJDLOG_VERIFY(sigemptyset(&mask) == 0); PJDLOG_VERIFY(sigaddset(&mask, SIGHUP) == 0); PJDLOG_VERIFY(sigaddset(&mask, SIGINT) == 0); PJDLOG_VERIFY(sigaddset(&mask, SIGTERM) == 0); PJDLOG_VERIFY(sigaddset(&mask, SIGCHLD) == 0); PJDLOG_VERIFY(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); /* Listen for remote connections. */ TAILQ_FOREACH(lst, &adcfg->adc_listen, adl_next) { if (proto_server(lst->adl_addr, &lst->adl_conn) == -1) { KEEP_ERRNO((void)pidfile_remove(pfh)); pjdlog_exit(EX_OSERR, "Unable to listen on address %s", lst->adl_addr); } } if (!foreground) { if (!launchd && daemon(0, 0) == -1) { KEEP_ERRNO((void)pidfile_remove(pfh)); pjdlog_exit(EX_OSERR, "Unable to daemonize"); } /* Start logging to syslog. */ pjdlog_mode_set(PJDLOG_MODE_SYSLOG); } if (pfh != NULL) { /* Write PID to a file. */ if (pidfile_write(pfh) < 0) { pjdlog_errno(LOG_WARNING, "Unable to write PID to a file"); } } TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { if (adhost->adh_role == ADIST_ROLE_SENDER) adist_sender(adcfg, adhost); } main_loop(); exit(0); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/auditdistd.conf.5 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/auditdistd.conf.5 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/auditdistd.conf.5 (revision 292449) @@ -1,361 +1,364 @@ .\" Copyright (c) 2012 The FreeBSD Foundation .\" All rights reserved. .\" .\" This documentation was written by Pawel Jakub Dawidek under sponsorship .\" from the FreeBSD Foundation. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" -.Dd March 22, 2011 +.Dd July 1, 2015 .Dt AUDITDISTD.CONF 5 .Os .Sh NAME .Nm auditdistd.conf .Nd configuration file for the .Xr auditdistd 8 daemon. .Sh DESCRIPTION Note: the configuration file may contain passwords. -Care should be taken to configure proper permissions on this file -.Li ( eg. 0600 ) . +Care should be taken to configure proper permissions for this file +.Li ( e.g., 0600 ) . .Pp -Every line starting with # is treated as comment and ignored. +Every line starting with +.Li # +gets treated as a comment and is ignored. .Sh CONFIGURATION FILE SYNTAX -General syntax of the +The general syntax of the .Nm -file is following: -.Bd -literal -offset +file is as follows: +.Bd -literal ## Global section. # Our name. -# The default is first part of the hostname. +# The default is the first part of the hostname. name "" # Connection timeout. # The default is 5. timeout # Path to pidfile. # The default is "/var/run/auditdistd.pid". pidfile "" sender { ## Sender section. # Source address for connections. # Optional. source "" # Directory with audit trail files managed by auditdistd. # The default is /var/audit/dist. directory "" .\" -.\" # Checksum algorithm for data send over the wire. +.\" # Checksum algorithm for data sent over the wire. .\" # The default is none. .\" checksum "" .\" -.\" # Compression algorithm for data send over the wire. +.\" # Compression algorithm for data sent over the wire. .\" # The default is none. .\" compression "" # Configuration for the target system we want to send audit trail # files to. host "" { # Source address for connections. # Optional. source "" - # Address of auditdistd receiver. + # Address of the auditdistd receiver. # No default. Obligatory. remote "" # Directory with audit trail files managed by auditdistd. # The default is /var/audit/dist. directory "" # Fingerprint of the receiver's public key when using TLS - # for connection. + # for connections. # Example fingerprint: # SHA256=8F:0A:FC:8A:3D:09:80:AF:D9:AA:38:CC:8A:86:53:E6:8F:B6:1C:55:30:14:D7:F9:AA:8B:3E:73:CD:F5:76:2B fingerprint "" # Password used to authenticate in front of the receiver. password "" .\" -.\" # Checksum algorithm for data send over the wire. +.\" # Checksum algorithm for data sent over the wire. .\" # The default is none. .\" checksum "" .\" -.\" # Compression algorithm for data send over the wire. +.\" # Compression algorithm for data sent over the wire. .\" # The default is none. .\" compression "" } - # Currently local audit trail files can be send only to one remote + # Currently local audit trail files can be sent only to one remote # auditdistd receiver, but this can change in the future. } receiver { ## Receiver section. - # Address to listen on. Multiple listen addresses might be specified. + # Address to listen on. Multiple listen addresses may be specified. # The defaults are "tcp4://0.0.0.0:7878" and "tcp6://[::]:7878". listen "" # Base directory. - # If directory in host section is no absolute, it will be concatenated - # with this base directory. + # If the directory in the host section is not absolute, it will be + # concatenated with this base directory. # The default is "/var/audit/remote". directory "" - # Path to receiver's certificate file. + # Path to the receiver's certificate file. # The default is "/etc/security/auditdistd.cert.pem". certfile "" - # Path to receiver's private key file. + # Path to the receiver's private key file. # The default is "/etc/security/auditdistd.key.pem". keyfile "" # Configuration for a source system we want to receive audit trail # files from. host "" { # Sender address. # No default. Obligatory. remote "" # Directory where to store audit trail files received # from system . # The default is "/". directory "" # Password used by the sender to authenticate. password "" } # Multiple hosts to receive from can be configured. } .Ed .Pp Most of the various available configuration parameters are optional. -If parameter is not defined in the particular section, it will be +If a parameter is not defined in the particular section, it will be inherited from the parent section if possible. For example, if the .Ic source parameter is not defined in the .Ic host section, it will be inherited from the .Ic sender section. In case the .Ic global section does not define the .Ic source parameter at all, the default value will be used. -.Sh CONFIGURATION FILE DESCRIPTION +.Sh CONFIGURATION OPTION DESCRIPTION The following statements are available: .Bl -tag -width ".Ic xxxx" .It Ic name Aq name .Pp This host's name. -It is send to the receiver, so it can properly recognize us if there are -more than one sender coming from the same IP address. +It is sent to the receiver, so it can properly recognize us if there are +multiple senders coming from the same IP address. .It Ic timeout Aq seconds .Pp Connection timeout in seconds. The default value is .Va 5 . .It Ic pidfile Aq path .Pp File in which to store the process ID of the main .Xr auditdistd 8 process. .Pp The default value is .Pa /var/run/auditdistd.pid . .It Ic source Aq addr .Pp Local address to bind to before connecting to the remote .Nm auditdistd daemon. -Format is the same as for the +The format is the same as for the .Ic listen statement. .It Ic directory Aq path .Pp -Directory where to look for audit trail files in case of sender mode or -directory where to store received audit trail files. +The directory where to look for audit trail files in case of sender mode, or +the directory where to store received audit trail files. The provided path has to be an absolute path. -The only exception is when directory is provided in the +The only exception is when the directory is provided in the .Ic receiver -section, then path provided in the +section; then the path provided in the .Ic host subsections can be relative to the directory in the .Ic receiver section. The default value is .Pa /var/audit/dist for the entire .Ic sender section, .Pa /var/audit/remote for the non-host .Ic receiver section and .Pa /var/audit/remote/ for the .Ic host subsections in the .Ic receiver section where .Aq name -is host's name. +is the host's name. .\".It Ic checksum Aq algorithm .\".Pp .\"Checksum algorithm should be one of the following: .\".Bl -tag -width ".Ic sha256" .\".It Ic none -.\"No checksum will be calculated for the data being send over the network. +.\"No checksum will be calculated for the data being sent over the network. .\"This is the default setting. .\".It Ic crc32 .\"CRC32 checksum will be calculated. .\".It Ic sha256 .\"SHA256 checksum will be calculated. .\".El .\".It Ic compression Aq algorithm .\".Pp .\"Compression algorithm should be one of the following: .\".Bl -tag -width ".Ic none" .\".It Ic none -.\"Data send over the network will not be compressed. +.\"Data sent over the network will not be compressed. .\"This is the default setting. .\".It Ic lzf .\"The .\".Nm LZF .\"algorithm by .\".An Marc Alexander Lehmann -.\"will be used to compress the data send over the network. +.\"will be used to compress the data sent over the network. .\".Nm LZF -.\"is very fast, general purpose compression algorithm. +.\"is a very fast, general purpose compression algorithm. .\".El .It Ic remote Aq addr .Pp Address of the remote .Nm auditdistd daemon. -Format is the same as for the +The format is the same as for the .Ic listen statement. -When operating in the +When operating in .Ic sender mode this address will be used to connect to the .Ic receiver . -When operating in the +When operating in .Ic receiver mode only connections from this address will be accepted. .It Ic listen Aq addr .Pp Address to listen on in form of: .Bd -literal -offset indent protocol://protocol-specific-address .Ed .Pp Each of the following examples defines the same listen address: .Bd -literal -offset indent 0.0.0.0 0.0.0.0:7878 tcp://0.0.0.0 tcp://0.0.0.0:7878 tcp4://0.0.0.0 tcp4://0.0.0.0:7878 .Ed .Pp Multiple listen addresses can be specified. By default .Nm auditdistd listens on .Pa tcp4://0.0.0.0:7878 and -.Pa tcp6://[::]:7878 -if kernel supports IPv4 and IPv6 respectively. +.Pa tcp6://[::]:7878 , +if the kernel supports IPv4 and IPv6 respectively. .It Ic keyfile Aq path .Pp -Path to a file that contains private key for TLS communication. +Path to a file that contains the private key for TLS communication. .It Ic certfile Aq path .Pp -Path to a file that contains certificate for TLS communication. +Path to a file that contains the certificate for TLS communication. .It Ic fingerprint Aq algo=hash .Pp -Finger print of the receiver's public key. -Currently only SHA256 algorithm is supported. -Certificate public key's fingerprint ready to be pasted into auditdistd +Fingerprint of the receiver's public key. +Currently only the SHA256 algorithm is supported. +The certificate public key's fingerprint ready to be pasted into the +.Nm auditdistd configuration file can be obtained by running: -.Bd -literal -offset +.Bd -literal # openssl x509 -in /etc/security/auditdistd.cert.pem -noout -fingerprint -sha256 | awk -F '[ =]' '{printf("%s=%s\\n", $1, $3)}' .Ed .It Ic password Aq password .Pp Password used to authenticate the sender in front of the receiver. .El .Sh FILES .Bl -tag -width ".Pa /etc/security/auditdistd.conf" -compact .It Pa /etc/security/auditdistd.conf The default .Nm auditdistd configuration file. .El .Sh EXAMPLES The example configuration files can look as follows. .Pp Web server: .Bd -literal -offset indent sender { host backup { remote 10.0.0.4 } } .Ed .Pp Audit backup server: .Bd -literal -offset indent receiver { host webserv { remote 10.0.0.1 } host mailserv { remote 10.0.0.2 } host dnsserv { remote 10.0.0.3 } } .Ed .Sh SEE ALSO .Xr audit 4 , -.Xr auditdistd 8 . +.Xr auditdistd 8 .Sh AUTHORS The .Nm auditdistd -was developed by +daemon was developed by .An Pawel Jakub Dawidek Aq pawel@dawidek.net under sponsorship of the FreeBSD Foundation. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/auditdistd.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/auditdistd.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/auditdistd.h (revision 292449) @@ -1,276 +1,274 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/auditdistd.h#2 $ */ #ifndef _AUDITDISTD_H_ #define _AUDITDISTD_H_ #include #include #include #include #include #include #include #include #include #include #include #include "proto.h" /* * Version history: * 0 - initial version */ #define ADIST_VERSION 0 #define ADIST_ROLE_UNDEF 0 #define ADIST_ROLE_SENDER 1 #define ADIST_ROLE_RECEIVER 2 #define ADIST_USER "auditdistd" #define ADIST_TIMEOUT 20 #define ADIST_CONFIG "/etc/security/auditdistd.conf" #define ADIST_TCP_PORT "7878" #define ADIST_LISTEN_TLS_TCP4 "tls://0.0.0.0:" ADIST_TCP_PORT #define ADIST_LISTEN_TLS_TCP6 "tls://[::]:" ADIST_TCP_PORT #define ADIST_PIDFILE "/var/run/auditdistd.pid" #define ADIST_DIRECTORY_SENDER "/var/audit/dist" #define ADIST_DIRECTORY_RECEIVER "/var/audit/remote" #define ADIST_CERTFILE "/etc/security/auditdistd.cert.pem" #define ADIST_KEYFILE "/etc/security/auditdistd.key.pem" #define ADIST_ERROR_WRONG_ORDER 1 #define ADIST_ERROR_INVALID_NAME 2 #define ADIST_ERROR_OPEN_OLD 3 #define ADIST_ERROR_CREATE 4 #define ADIST_ERROR_OPEN 5 #define ADIST_ERROR_READ 6 #define ADIST_ERROR_WRITE 7 #define ADIST_ERROR_RENAME 8 #define ADIST_ADDRSIZE 1024 #define ADIST_HOSTSIZE 256 #define ADIST_PATHSIZE 256 #define ADIST_PASSWORDSIZE 128 #define ADIST_FINGERPRINTSIZE 256 /* Number of seconds to sleep between reconnect retries or keepalive packets. */ #define ADIST_KEEPALIVE 10 struct adist_listen { /* Address to listen on. */ char adl_addr[ADIST_ADDRSIZE]; /* Protocol-specific data. */ struct proto_conn *adl_conn; TAILQ_ENTRY(adist_listen) adl_next; }; struct adist_config { /* Our name. */ char adc_name[ADIST_HOSTSIZE]; /* PID file path. */ char adc_pidfile[PATH_MAX]; /* Connection timeout. */ int adc_timeout; /* Path to receiver's certificate file. */ char adc_certfile[PATH_MAX]; /* Path to receiver's private key file. */ char adc_keyfile[PATH_MAX]; /* List of addresses to listen on. */ TAILQ_HEAD(, adist_listen) adc_listen; /* List of hosts. */ TAILQ_HEAD(, adist_host) adc_hosts; }; #define ADIST_COMPRESSION_NONE 0 #define ADIST_COMPRESSION_LZF 1 #define ADIST_CHECKSUM_NONE 0 #define ADIST_CHECKSUM_CRC32 1 #define ADIST_CHECKSUM_SHA256 2 /* * Structure that describes single host (either sender or receiver). */ struct adist_host { /* Host name. */ char adh_name[ADIST_HOSTSIZE]; /* Host role: ADIST_ROLE_{SENDER,RECEIVER}. */ int adh_role; /* Protocol version negotiated. */ int adh_version; /* Local address to bind to. */ char adh_localaddr[ADIST_ADDRSIZE]; /* Address of the remote component. */ char adh_remoteaddr[ADIST_ADDRSIZE]; /* Connection with remote host. */ struct proto_conn *adh_remote; /* Connection was reestablished, reset the state. */ bool adh_reset; /* * Directory from which audit trail files should be send in * ADIST_ROLE_SENDER case or stored into in ADIST_ROLE_RECEIVER case. */ char adh_directory[PATH_MAX]; /* Compression algorithm. Currently unused. */ int adh_compression; /* Checksum algorithm. Currently unused. */ int adh_checksum; /* Sender's password. */ char adh_password[ADIST_PASSWORDSIZE]; /* Fingerprint of receiver's public key. */ char adh_fingerprint[ADIST_FINGERPRINTSIZE]; /* PID of child worker process. 0 - no child. */ pid_t adh_worker_pid; /* Connection requests from sender to main. */ struct proto_conn *adh_conn; /* Receiver-specific fields. */ char adh_trail_name[ADIST_PATHSIZE]; int adh_trail_fd; int adh_trail_dirfd; DIR *adh_trail_dirfp; /* Sender-specific fields. */ uint64_t adh_trail_offset; /* Next resource. */ TAILQ_ENTRY(adist_host) adh_next; }; #define ADIST_BYTEORDER_UNDEFINED 0 #define ADIST_BYTEORDER_LITTLE_ENDIAN 1 #define ADIST_BYTEORDER_BIG_ENDIAN 2 #if _BYTE_ORDER == _LITTLE_ENDIAN #define ADIST_BYTEORDER ADIST_BYTEORDER_LITTLE_ENDIAN #elif _BYTE_ORDER == _BIG_ENDIAN #define ADIST_BYTEORDER ADIST_BYTEORDER_BIG_ENDIAN #else #error Unknown byte order. #endif struct adpkt { uint8_t adp_byteorder; #define ADIST_CMD_UNDEFINED 0 #define ADIST_CMD_OPEN 1 #define ADIST_CMD_APPEND 2 #define ADIST_CMD_CLOSE 3 #define ADIST_CMD_KEEPALIVE 4 #define ADIST_CMD_ERROR 5 uint8_t adp_cmd; uint64_t adp_seq; uint32_t adp_datasize; unsigned char adp_data[0]; } __packed; struct adreq { int adr_error; TAILQ_ENTRY(adreq) adr_next; struct adpkt adr_packet; }; #define adr_byteorder adr_packet.adp_byteorder #define adr_cmd adr_packet.adp_cmd #define adr_seq adr_packet.adp_seq #define adr_datasize adr_packet.adp_datasize #define adr_data adr_packet.adp_data #define ADPKT_SIZE(adreq) (sizeof((adreq)->adr_packet) + (adreq)->adr_datasize) struct adrep { uint8_t adrp_byteorder; uint64_t adrp_seq; uint16_t adrp_error; } __packed; #define ADIST_QUEUE_SIZE 16 #define ADIST_BUF_SIZE 65536 #define QUEUE_TAKE(adreq, list, timeout) do { \ mtx_lock(list##_lock); \ if ((timeout) == 0) { \ while (((adreq) = TAILQ_FIRST(list)) == NULL) \ cv_wait(list##_cond, list##_lock); \ } else { \ (adreq) = TAILQ_FIRST(list); \ if ((adreq) == NULL) { \ cv_timedwait(list##_cond, list##_lock, \ (timeout)); \ (adreq) = TAILQ_FIRST(list); \ } \ } \ if ((adreq) != NULL) \ TAILQ_REMOVE((list), (adreq), adr_next); \ mtx_unlock(list##_lock); \ } while (0) #define QUEUE_INSERT(adreq, list) do { \ bool _wakeup; \ \ mtx_lock(list##_lock); \ _wakeup = TAILQ_EMPTY(list); \ TAILQ_INSERT_TAIL((list), (adreq), adr_next); \ mtx_unlock(list##_lock); \ if (_wakeup) \ cv_signal(list##_cond); \ } while (0) #define QUEUE_WAIT(list) do { \ mtx_lock(list##_lock); \ while (TAILQ_EMPTY(list)) \ cv_wait(list##_cond, list##_lock); \ mtx_unlock(list##_lock); \ } while (0) extern const char *cfgpath; extern bool sigexit_received; extern struct pidfh *pfh; void descriptors_cleanup(struct adist_host *adhost); void descriptors_assert(const struct adist_host *adhost, int pjdlogmode); void adist_sender(struct adist_config *config, struct adist_host *adhost); void adist_receiver(struct adist_config *config, struct adist_host *adhost); struct adist_config *yy_config_parse(const char *config, bool exitonerror); void yy_config_free(struct adist_config *config); void yyerror(const char *); int yylex(void); #endif /* !_AUDITDISTD_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/faccessat.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/faccessat.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/faccessat.h (revision 292449) @@ -1,69 +1,67 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/faccessat.h#1 $ */ #ifndef _FACCESSAT_H_ #define _FACCESSAT_H_ #include #define AT_EACCESS 0x01 static int faccessat(int fd, const char *path, int mode, int flag) { int cfd, error, ret; if (flag == AT_EACCESS) { errno = EINVAL; return (-1); } cfd = open(".", O_RDONLY | O_DIRECTORY); if (cfd == -1) return (-1); if (fchdir(fd) == -1) { error = errno; (void)close(cfd); errno = error; return (-1); } ret = access(path, mode); error = errno; (void)fchdir(cfd); (void)close(cfd); errno = error; return (ret); } #endif /* !_FACCESSAT_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/fstatat.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/fstatat.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/fstatat.h (revision 292449) @@ -1,69 +1,67 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/fstatat.h#1 $ */ #ifndef _FSTATAT_H_ #define _FSTATAT_H_ #include #include #define AT_SYMLINK_NOFOLLOW 0x01 static int fstatat(int fd, const char *path, struct stat *buf, int flag) { int cfd, error, ret; cfd = open(".", O_RDONLY | O_DIRECTORY); if (cfd == -1) return (-1); if (fchdir(fd) == -1) { error = errno; (void)close(cfd); errno = error; return (-1); } if (flag == AT_SYMLINK_NOFOLLOW) ret = lstat(path, buf); else ret = stat(path, buf); error = errno; (void)fchdir(cfd); (void)close(cfd); errno = error; return (ret); } #endif /* !_FSTATAT_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/openat.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/openat.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/openat.h (revision 292449) @@ -1,75 +1,73 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/openat.h#1 $ */ #ifndef _OPENAT_H_ #define _OPENAT_H_ #include #include #include static int openat(int fd, const char *path, int flags, ...) { int cfd, ffd, error; cfd = open(".", O_RDONLY | O_DIRECTORY); if (cfd == -1) return (-1); if (fchdir(fd) == -1) { error = errno; (void)close(cfd); errno = error; return (-1); } if ((flags & O_CREAT) != 0) { va_list ap; int mode; va_start(ap, flags); mode = va_arg(ap, int); va_end(ap); ffd = open(path, flags, mode); } else { ffd = open(path, flags); } error = errno; (void)fchdir(cfd); (void)close(cfd); errno = error; return (ffd); } #endif /* !_OPENAT_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/parse.y =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/parse.y (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/parse.y (revision 292449) @@ -1,856 +1,854 @@ %{ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/parse.y#5 $ */ #include #include #include #include #include #include #include #include #include #include #include #ifndef HAVE_STRLCPY #include #endif #include "auditdistd.h" #include "pjdlog.h" extern int depth; extern int lineno; extern FILE *yyin; extern char *yytext; static struct adist_config *lconfig; static struct adist_host *curhost; #define SECTION_GLOBAL 0 #define SECTION_SENDER 1 #define SECTION_RECEIVER 2 static int cursection; /* Sender section. */ static char depth1_source[ADIST_ADDRSIZE]; static int depth1_checksum; static int depth1_compression; /* Sender and receiver sections. */ static char depth1_directory[PATH_MAX]; static bool adjust_directory(char *path); static bool family_supported(int family); extern void yyrestart(FILE *); %} %token CB %token CERTFILE %token DIRECTORY %token FINGERPRINT %token HOST %token KEYFILE %token LISTEN %token NAME %token OB %token PASSWORD %token PIDFILE %token RECEIVER REMOTE %token SENDER SOURCE %token TIMEOUT /* %type checksum_type %type compression_type */ %union { int num; char *str; } %token NUM %token STR %% statements: | statements statement ; statement: name_statement | pidfile_statement | timeout_statement | sender_statement | receiver_statement ; name_statement: NAME STR { PJDLOG_RASSERT(depth == 0, "The name variable can only be specificed in the global section."); if (lconfig->adc_name[0] != '\0') { pjdlog_error("The name variable is specified twice."); free($2); return (1); } if (strlcpy(lconfig->adc_name, $2, sizeof(lconfig->adc_name)) >= sizeof(lconfig->adc_name)) { pjdlog_error("The name value is too long."); free($2); return (1); } free($2); } ; pidfile_statement: PIDFILE STR { PJDLOG_RASSERT(depth == 0, "The pidfile variable can only be specificed in the global section."); if (lconfig->adc_pidfile[0] != '\0') { pjdlog_error("The pidfile variable is specified twice."); free($2); return (1); } if (strcmp($2, "none") != 0 && $2[0] != '/') { pjdlog_error("The pidfile variable must be set to absolute pathname or \"none\"."); free($2); return (1); } if (strlcpy(lconfig->adc_pidfile, $2, sizeof(lconfig->adc_pidfile)) >= sizeof(lconfig->adc_pidfile)) { pjdlog_error("The pidfile value is too long."); free($2); return (1); } free($2); } ; timeout_statement: TIMEOUT NUM { PJDLOG_ASSERT(depth == 0); lconfig->adc_timeout = $2; } ; sender_statement: SENDER sender_start sender_entries CB { PJDLOG_ASSERT(depth == 0); PJDLOG_ASSERT(cursection == SECTION_SENDER); /* Configure defaults. */ if (depth1_checksum == -1) depth1_checksum = ADIST_CHECKSUM_NONE; if (depth1_compression == -1) depth1_compression = ADIST_COMPRESSION_NONE; if (depth1_directory[0] == '\0') { (void)strlcpy(depth1_directory, ADIST_DIRECTORY_SENDER, sizeof(depth1_directory)); } /* Empty depth1_source is ok. */ TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) { if (curhost->adh_role != ADIST_ROLE_SENDER) continue; if (curhost->adh_checksum == -1) curhost->adh_checksum = depth1_checksum; if (curhost->adh_compression == -1) curhost->adh_compression = depth1_compression; if (curhost->adh_directory[0] == '\0') { (void)strlcpy(curhost->adh_directory, depth1_directory, sizeof(curhost->adh_directory)); } if (curhost->adh_localaddr[0] == '\0') { (void)strlcpy(curhost->adh_localaddr, depth1_source, sizeof(curhost->adh_localaddr)); } } cursection = SECTION_GLOBAL; } ; sender_start: OB { PJDLOG_ASSERT(depth == 1); PJDLOG_ASSERT(cursection == SECTION_GLOBAL); cursection = SECTION_SENDER; depth1_checksum = -1; depth1_compression = -1; depth1_source[0] = '\0'; depth1_directory[0] = '\0'; #ifndef HAVE_AUDIT_SYSCALLS pjdlog_error("Sender functionality is not available."); return (1); #endif } ; sender_entries: | sender_entries sender_entry ; sender_entry: source_statement | directory_statement /* | checksum_statement | compression_statement */ | sender_host_statement ; receiver_statement: RECEIVER receiver_start receiver_entries CB { PJDLOG_ASSERT(depth == 0); PJDLOG_ASSERT(cursection == SECTION_RECEIVER); /* * If not listen addresses were specified, * configure default ones. */ if (TAILQ_EMPTY(&lconfig->adc_listen)) { struct adist_listen *lst; if (family_supported(AF_INET)) { lst = calloc(1, sizeof(*lst)); if (lst == NULL) { pjdlog_error("Unable to allocate memory for listen address."); return (1); } (void)strlcpy(lst->adl_addr, ADIST_LISTEN_TLS_TCP4, sizeof(lst->adl_addr)); TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next); } else { pjdlog_debug(1, "No IPv4 support in the kernel, not listening on IPv4 address."); } if (family_supported(AF_INET6)) { lst = calloc(1, sizeof(*lst)); if (lst == NULL) { pjdlog_error("Unable to allocate memory for listen address."); return (1); } (void)strlcpy(lst->adl_addr, ADIST_LISTEN_TLS_TCP6, sizeof(lst->adl_addr)); TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next); } else { pjdlog_debug(1, "No IPv6 support in the kernel, not listening on IPv6 address."); } if (TAILQ_EMPTY(&lconfig->adc_listen)) { pjdlog_error("No address to listen on."); return (1); } } /* Configure defaults. */ if (depth1_directory[0] == '\0') { (void)strlcpy(depth1_directory, ADIST_DIRECTORY_RECEIVER, sizeof(depth1_directory)); } TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) { if (curhost->adh_role != ADIST_ROLE_RECEIVER) continue; if (curhost->adh_directory[0] == '\0') { if (snprintf(curhost->adh_directory, sizeof(curhost->adh_directory), "%s/%s", depth1_directory, curhost->adh_name) >= (ssize_t)sizeof(curhost->adh_directory)) { pjdlog_error("Directory value is too long."); return (1); } } } cursection = SECTION_GLOBAL; } ; receiver_start: OB { PJDLOG_ASSERT(depth == 1); PJDLOG_ASSERT(cursection == SECTION_GLOBAL); cursection = SECTION_RECEIVER; depth1_directory[0] = '\0'; } ; receiver_entries: | receiver_entries receiver_entry ; receiver_entry: listen_statement | directory_statement | certfile_statement | keyfile_statement | receiver_host_statement ; /* checksum_statement: CHECKSUM checksum_type { PJDLOG_ASSERT(cursection == SECTION_SENDER); switch (depth) { case 1: depth1_checksum = $2; break; case 2: PJDLOG_ASSERT(curhost != NULL); curhost->adh_checksum = $2; break; default: PJDLOG_ABORT("checksum at wrong depth level"); } } ; checksum_type: NONE { $$ = ADIST_CHECKSUM_NONE; } | CRC32 { $$ = ADIST_CHECKSUM_CRC32; } | SHA256 { $$ = ADIST_CHECKSUM_SHA256; } ; compression_statement: COMPRESSION compression_type { PJDLOG_ASSERT(cursection == SECTION_SENDER); switch (depth) { case 1: depth1_compression = $2; break; case 2: PJDLOG_ASSERT(curhost != NULL); curhost->adh_compression = $2; break; default: PJDLOG_ABORT("compression at wrong depth level"); } } ; compression_type: NONE { $$ = ADIST_COMPRESSION_NONE; } | LZF { $$ = ADIST_COMPRESSION_LZF; } ; */ directory_statement: DIRECTORY STR { PJDLOG_ASSERT(cursection == SECTION_SENDER || cursection == SECTION_RECEIVER); switch (depth) { case 1: if (strlcpy(depth1_directory, $2, sizeof(depth1_directory)) >= sizeof(depth1_directory)) { pjdlog_error("Directory value is too long."); free($2); return (1); } if (!adjust_directory(depth1_directory)) return (1); break; case 2: if (cursection == SECTION_SENDER || $2[0] == '/') { if (strlcpy(curhost->adh_directory, $2, sizeof(curhost->adh_directory)) >= sizeof(curhost->adh_directory)) { pjdlog_error("Directory value is too long."); free($2); return (1); } } else /* if (cursection == SECTION_RECEIVER) */ { if (depth1_directory[0] == '\0') { pjdlog_error("Directory path must be absolute."); free($2); return (1); } if (snprintf(curhost->adh_directory, sizeof(curhost->adh_directory), "%s/%s", depth1_directory, $2) >= (ssize_t)sizeof(curhost->adh_directory)) { pjdlog_error("Directory value is too long."); free($2); return (1); } } break; default: PJDLOG_ABORT("directory at wrong depth level"); } free($2); } ; source_statement: SOURCE STR { PJDLOG_RASSERT(cursection == SECTION_SENDER, "The source variable must be in sender section."); switch (depth) { case 1: if (strlcpy(depth1_source, $2, sizeof(depth1_source)) >= sizeof(depth1_source)) { pjdlog_error("Source value is too long."); free($2); return (1); } break; case 2: if (strlcpy(curhost->adh_localaddr, $2, sizeof(curhost->adh_localaddr)) >= sizeof(curhost->adh_localaddr)) { pjdlog_error("Source value is too long."); free($2); return (1); } break; } free($2); } ; fingerprint_statement: FINGERPRINT STR { PJDLOG_ASSERT(cursection == SECTION_SENDER); PJDLOG_ASSERT(depth == 2); if (strncasecmp($2, "SHA256=", 7) != 0) { pjdlog_error("Invalid fingerprint value."); free($2); return (1); } if (strlcpy(curhost->adh_fingerprint, $2, sizeof(curhost->adh_fingerprint)) >= sizeof(curhost->adh_fingerprint)) { pjdlog_error("Fingerprint value is too long."); free($2); return (1); } free($2); } ; password_statement: PASSWORD STR { PJDLOG_ASSERT(cursection == SECTION_SENDER || cursection == SECTION_RECEIVER); PJDLOG_ASSERT(depth == 2); if (strlcpy(curhost->adh_password, $2, sizeof(curhost->adh_password)) >= sizeof(curhost->adh_password)) { pjdlog_error("Password value is too long."); bzero($2, strlen($2)); free($2); return (1); } bzero($2, strlen($2)); free($2); } ; certfile_statement: CERTFILE STR { PJDLOG_ASSERT(cursection == SECTION_RECEIVER); PJDLOG_ASSERT(depth == 1); if (strlcpy(lconfig->adc_certfile, $2, sizeof(lconfig->adc_certfile)) >= sizeof(lconfig->adc_certfile)) { pjdlog_error("Certfile value is too long."); free($2); return (1); } free($2); } ; keyfile_statement: KEYFILE STR { PJDLOG_ASSERT(cursection == SECTION_RECEIVER); PJDLOG_ASSERT(depth == 1); if (strlcpy(lconfig->adc_keyfile, $2, sizeof(lconfig->adc_keyfile)) >= sizeof(lconfig->adc_keyfile)) { pjdlog_error("Keyfile value is too long."); free($2); return (1); } free($2); } ; listen_statement: LISTEN STR { struct adist_listen *lst; PJDLOG_ASSERT(depth == 1); PJDLOG_ASSERT(cursection == SECTION_RECEIVER); lst = calloc(1, sizeof(*lst)); if (lst == NULL) { pjdlog_error("Unable to allocate memory for listen address."); free($2); return (1); } if (strlcpy(lst->adl_addr, $2, sizeof(lst->adl_addr)) >= sizeof(lst->adl_addr)) { pjdlog_error("listen argument is too long."); free($2); free(lst); return (1); } TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next); free($2); } ; sender_host_statement: HOST host_start OB sender_host_entries CB { /* Put it onto host list. */ TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next); curhost = NULL; } ; receiver_host_statement: HOST host_start OB receiver_host_entries CB { /* Put it onto host list. */ TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next); curhost = NULL; } ; host_start: STR { /* Check if there is no duplicate entry. */ TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) { if (strcmp(curhost->adh_name, $1) != 0) continue; if (curhost->adh_role == ADIST_ROLE_SENDER && cursection == SECTION_RECEIVER) { continue; } if (curhost->adh_role == ADIST_ROLE_RECEIVER && cursection == SECTION_SENDER) { continue; } pjdlog_error("%s host %s is configured more than once.", curhost->adh_role == ADIST_ROLE_SENDER ? "Sender" : "Receiver", curhost->adh_name); free($1); return (1); } curhost = calloc(1, sizeof(*curhost)); if (curhost == NULL) { pjdlog_error("Unable to allocate memory for host configuration."); free($1); return (1); } if (strlcpy(curhost->adh_name, $1, sizeof(curhost->adh_name)) >= sizeof(curhost->adh_name)) { pjdlog_error("Host name is too long."); free($1); return (1); } free($1); curhost->adh_role = cursection == SECTION_SENDER ? ADIST_ROLE_SENDER : ADIST_ROLE_RECEIVER; curhost->adh_version = ADIST_VERSION; curhost->adh_localaddr[0] = '\0'; curhost->adh_remoteaddr[0] = '\0'; curhost->adh_remote = NULL; curhost->adh_directory[0] = '\0'; curhost->adh_password[0] = '\0'; curhost->adh_fingerprint[0] = '\0'; curhost->adh_worker_pid = 0; curhost->adh_conn = NULL; } ; sender_host_entries: | sender_host_entries sender_host_entry ; sender_host_entry: source_statement | remote_statement | directory_statement | fingerprint_statement | password_statement /* | checksum_statement | compression_statement */ ; receiver_host_entries: | receiver_host_entries receiver_host_entry ; receiver_host_entry: remote_statement | directory_statement | password_statement ; remote_statement: REMOTE STR { PJDLOG_ASSERT(depth == 2); PJDLOG_ASSERT(cursection == SECTION_SENDER || cursection == SECTION_RECEIVER); if (strlcpy(curhost->adh_remoteaddr, $2, sizeof(curhost->adh_remoteaddr)) >= sizeof(curhost->adh_remoteaddr)) { pjdlog_error("Remote value is too long."); free($2); return (1); } free($2); } ; %% static bool family_supported(int family) { int sock; sock = socket(family, SOCK_STREAM, 0); if (sock == -1 && errno == EPROTONOSUPPORT) return (false); if (sock >= 0) (void)close(sock); return (true); } static bool adjust_directory(char *path) { size_t len; len = strlen(path); for (;;) { if (len == 0) { pjdlog_error("Directory path is empty."); return (false); } if (path[len - 1] != '/') break; len--; path[len] = '\0'; } if (path[0] != '/') { pjdlog_error("Directory path must be absolute."); return (false); } return (true); } static int my_name(char *name, size_t size) { char buf[MAXHOSTNAMELEN]; char *pos; if (gethostname(buf, sizeof(buf)) < 0) { pjdlog_errno(LOG_ERR, "gethostname() failed"); return (-1); } /* First component of the host name. */ pos = strchr(buf, '.'); if (pos == NULL) (void)strlcpy(name, buf, size); else (void)strlcpy(name, buf, MIN((size_t)(pos - buf + 1), size)); if (name[0] == '\0') { pjdlog_error("Empty host name."); return (-1); } return (0); } void yyerror(const char *str) { pjdlog_error("Unable to parse configuration file at line %d near '%s': %s", lineno, yytext, str); } struct adist_config * yy_config_parse(const char *config, bool exitonerror) { int ret; curhost = NULL; cursection = SECTION_GLOBAL; depth = 0; lineno = 0; lconfig = calloc(1, sizeof(*lconfig)); if (lconfig == NULL) { pjdlog_error("Unable to allocate memory for configuration."); if (exitonerror) exit(EX_TEMPFAIL); return (NULL); } TAILQ_INIT(&lconfig->adc_hosts); TAILQ_INIT(&lconfig->adc_listen); lconfig->adc_name[0] = '\0'; lconfig->adc_timeout = -1; lconfig->adc_pidfile[0] = '\0'; lconfig->adc_certfile[0] = '\0'; lconfig->adc_keyfile[0] = '\0'; yyin = fopen(config, "r"); if (yyin == NULL) { pjdlog_errno(LOG_ERR, "Unable to open configuration file %s", config); yy_config_free(lconfig); if (exitonerror) exit(EX_OSFILE); return (NULL); } yyrestart(yyin); ret = yyparse(); fclose(yyin); if (ret != 0) { yy_config_free(lconfig); if (exitonerror) exit(EX_CONFIG); return (NULL); } /* * Let's see if everything is set up. */ if (lconfig->adc_name[0] == '\0' && my_name(lconfig->adc_name, sizeof(lconfig->adc_name)) == -1) { yy_config_free(lconfig); if (exitonerror) exit(EX_CONFIG); return (NULL); } if (lconfig->adc_timeout == -1) lconfig->adc_timeout = ADIST_TIMEOUT; if (lconfig->adc_pidfile[0] == '\0') { (void)strlcpy(lconfig->adc_pidfile, ADIST_PIDFILE, sizeof(lconfig->adc_pidfile)); } if (lconfig->adc_certfile[0] == '\0') { (void)strlcpy(lconfig->adc_certfile, ADIST_CERTFILE, sizeof(lconfig->adc_certfile)); } if (lconfig->adc_keyfile[0] == '\0') { (void)strlcpy(lconfig->adc_keyfile, ADIST_KEYFILE, sizeof(lconfig->adc_keyfile)); } return (lconfig); } void yy_config_free(struct adist_config *config) { struct adist_host *adhost; struct adist_listen *lst; while ((lst = TAILQ_FIRST(&config->adc_listen)) != NULL) { TAILQ_REMOVE(&config->adc_listen, lst, adl_next); free(lst); } while ((adhost = TAILQ_FIRST(&config->adc_hosts)) != NULL) { TAILQ_REMOVE(&config->adc_hosts, adhost, adh_next); bzero(adhost, sizeof(*adhost)); free(adhost); } free(config); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/pjdlog.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/pjdlog.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/pjdlog.c (revision 292449) @@ -1,621 +1,619 @@ /*- * Copyright (c) 2009-2010 The FreeBSD Foundation * Copyright (c) 2011 Pawel Jakub Dawidek * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/pjdlog.c#1 $ */ #include #include #include #include #include #include #ifdef __FreeBSD__ #include #include #endif #include #include #include #include #include #include #include #include "pjdlog.h" #define PJDLOG_NEVER_INITIALIZED 0 #define PJDLOG_NOT_INITIALIZED 1 #define PJDLOG_INITIALIZED 2 static int pjdlog_initialized = PJDLOG_NEVER_INITIALIZED; static int pjdlog_mode, pjdlog_debug_level; static char pjdlog_prefix[128]; #ifdef __FreeBSD__ static int pjdlog_printf_arginfo_humanized_number(const struct printf_info *pi __unused, size_t n, int *argt) { assert(n >= 1); argt[0] = PA_INT | PA_FLAG_INTMAX; return (1); } static int pjdlog_printf_render_humanized_number(struct __printf_io *io, const struct printf_info *pi, const void * const *arg) { char buf[5]; intmax_t num; int ret; num = *(const intmax_t *)arg[0]; humanize_number(buf, sizeof(buf), (int64_t)num, "", HN_AUTOSCALE, HN_NOSPACE | HN_DECIMAL); ret = __printf_out(io, pi, buf, strlen(buf)); __printf_flush(io); return (ret); } static int pjdlog_printf_arginfo_sockaddr(const struct printf_info *pi __unused, size_t n, int *argt) { assert(n >= 1); argt[0] = PA_POINTER; return (1); } static int pjdlog_printf_render_sockaddr(struct __printf_io *io, const struct printf_info *pi, const void * const *arg) { const struct sockaddr_storage *ss; char buf[64]; int ret; ss = *(const struct sockaddr_storage * const *)arg[0]; switch (ss->ss_family) { case AF_INET: { char addr[INET_ADDRSTRLEN]; const struct sockaddr_in *sin; unsigned int port; sin = (const struct sockaddr_in *)ss; port = ntohs(sin->sin_port); if (inet_ntop(ss->ss_family, &sin->sin_addr, addr, sizeof(addr)) == NULL) { PJDLOG_ABORT("inet_ntop(AF_INET) failed: %s.", strerror(errno)); } snprintf(buf, sizeof(buf), "%s:%u", addr, port); break; } case AF_INET6: { char addr[INET6_ADDRSTRLEN]; const struct sockaddr_in6 *sin; unsigned int port; sin = (const struct sockaddr_in6 *)ss; port = ntohs(sin->sin6_port); if (inet_ntop(ss->ss_family, &sin->sin6_addr, addr, sizeof(addr)) == NULL) { PJDLOG_ABORT("inet_ntop(AF_INET6) failed: %s.", strerror(errno)); } snprintf(buf, sizeof(buf), "[%s]:%u", addr, port); break; } default: snprintf(buf, sizeof(buf), "[unsupported family %hhu]", ss->ss_family); break; } ret = __printf_out(io, pi, buf, strlen(buf)); __printf_flush(io); return (ret); } #endif /* __FreeBSD__ */ void pjdlog_init(int mode) { int saved_errno; assert(pjdlog_initialized == PJDLOG_NEVER_INITIALIZED || pjdlog_initialized == PJDLOG_NOT_INITIALIZED); assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG); saved_errno = errno; if (pjdlog_initialized == PJDLOG_NEVER_INITIALIZED) { #ifdef __FreeBSD__ __use_xprintf = 1; register_printf_render_std("T"); register_printf_render('N', pjdlog_printf_render_humanized_number, pjdlog_printf_arginfo_humanized_number); register_printf_render('S', pjdlog_printf_render_sockaddr, pjdlog_printf_arginfo_sockaddr); #endif } if (mode == PJDLOG_MODE_SYSLOG) openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON); pjdlog_mode = mode; pjdlog_debug_level = 0; bzero(pjdlog_prefix, sizeof(pjdlog_prefix)); pjdlog_initialized = PJDLOG_INITIALIZED; errno = saved_errno; } void pjdlog_fini(void) { int saved_errno; assert(pjdlog_initialized == PJDLOG_INITIALIZED); saved_errno = errno; if (pjdlog_mode == PJDLOG_MODE_SYSLOG) closelog(); pjdlog_initialized = PJDLOG_NOT_INITIALIZED; errno = saved_errno; } /* * Configure where the logs should go. * By default they are send to stdout/stderr, but after going into background * (eg. by calling daemon(3)) application is responsible for changing mode to * PJDLOG_MODE_SYSLOG, so logs will be send to syslog. */ void pjdlog_mode_set(int mode) { int saved_errno; assert(pjdlog_initialized == PJDLOG_INITIALIZED); assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG); if (pjdlog_mode == mode) return; saved_errno = errno; if (mode == PJDLOG_MODE_SYSLOG) openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON); else /* if (mode == PJDLOG_MODE_STD) */ closelog(); pjdlog_mode = mode; errno = saved_errno; } /* * Return current mode. */ int pjdlog_mode_get(void) { assert(pjdlog_initialized == PJDLOG_INITIALIZED); return (pjdlog_mode); } /* * Set debug level. All the logs above the level specified here will be * ignored. */ void pjdlog_debug_set(int level) { assert(pjdlog_initialized == PJDLOG_INITIALIZED); assert(level >= 0); pjdlog_debug_level = level; } /* * Return current debug level. */ int pjdlog_debug_get(void) { assert(pjdlog_initialized == PJDLOG_INITIALIZED); return (pjdlog_debug_level); } /* * Set prefix that will be used before each log. * Setting prefix to NULL will remove it. */ void pjdlog_prefix_set(const char *fmt, ...) { va_list ap; assert(pjdlog_initialized == PJDLOG_INITIALIZED); va_start(ap, fmt); pjdlogv_prefix_set(fmt, ap); va_end(ap); } /* * Set prefix that will be used before each log. * Setting prefix to NULL will remove it. */ void pjdlogv_prefix_set(const char *fmt, va_list ap) { int saved_errno; assert(pjdlog_initialized == PJDLOG_INITIALIZED); assert(fmt != NULL); saved_errno = errno; vsnprintf(pjdlog_prefix, sizeof(pjdlog_prefix), fmt, ap); errno = saved_errno; } /* * Convert log level into string. */ static const char * pjdlog_level_string(int loglevel) { switch (loglevel) { case LOG_EMERG: return ("EMERG"); case LOG_ALERT: return ("ALERT"); case LOG_CRIT: return ("CRIT"); case LOG_ERR: return ("ERROR"); case LOG_WARNING: return ("WARNING"); case LOG_NOTICE: return ("NOTICE"); case LOG_INFO: return ("INFO"); case LOG_DEBUG: return ("DEBUG"); } assert(!"Invalid log level."); abort(); /* XXX: gcc */ } /* * Common log routine. */ void pjdlog_common(int loglevel, int debuglevel, int error, const char *fmt, ...) { va_list ap; assert(pjdlog_initialized == PJDLOG_INITIALIZED); va_start(ap, fmt); pjdlogv_common(loglevel, debuglevel, error, fmt, ap); va_end(ap); } /* * Common log routine, which can handle regular log level as well as debug * level. We decide here where to send the logs (stdout/stderr or syslog). */ void pjdlogv_common(int loglevel, int debuglevel, int error, const char *fmt, va_list ap) { int saved_errno; assert(pjdlog_initialized == PJDLOG_INITIALIZED); assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || loglevel == LOG_CRIT || loglevel == LOG_ERR || loglevel == LOG_WARNING || loglevel == LOG_NOTICE || loglevel == LOG_INFO || loglevel == LOG_DEBUG); assert(loglevel != LOG_DEBUG || debuglevel > 0); assert(error >= -1); /* Ignore debug above configured level. */ if (loglevel == LOG_DEBUG && debuglevel > pjdlog_debug_level) return; saved_errno = errno; switch (pjdlog_mode) { case PJDLOG_MODE_STD: { FILE *out; /* * We send errors and warning to stderr and the rest to stdout. */ switch (loglevel) { case LOG_EMERG: case LOG_ALERT: case LOG_CRIT: case LOG_ERR: case LOG_WARNING: out = stderr; break; case LOG_NOTICE: case LOG_INFO: case LOG_DEBUG: out = stdout; break; default: assert(!"Invalid loglevel."); abort(); /* XXX: gcc */ } fprintf(out, "(%d) ", getpid()); fprintf(out, "[%s]", pjdlog_level_string(loglevel)); /* Attach debuglevel if this is debug log. */ if (loglevel == LOG_DEBUG) fprintf(out, "[%d]", debuglevel); fprintf(out, " %s", pjdlog_prefix); vfprintf(out, fmt, ap); if (error != -1) fprintf(out, ": %s.", strerror(error)); fprintf(out, "\n"); fflush(out); break; } case PJDLOG_MODE_SYSLOG: { char log[1024]; int len; len = snprintf(log, sizeof(log), "%s", pjdlog_prefix); if ((size_t)len < sizeof(log)) len += vsnprintf(log + len, sizeof(log) - len, fmt, ap); if (error != -1 && (size_t)len < sizeof(log)) { (void)snprintf(log + len, sizeof(log) - len, ": %s.", strerror(error)); } syslog(loglevel, "%s", log); break; } default: assert(!"Invalid mode."); } errno = saved_errno; } /* * Regular logs. */ void pjdlogv(int loglevel, const char *fmt, va_list ap) { assert(pjdlog_initialized == PJDLOG_INITIALIZED); /* LOG_DEBUG is invalid here, pjdlogv?_debug() should be used. */ assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || loglevel == LOG_CRIT || loglevel == LOG_ERR || loglevel == LOG_WARNING || loglevel == LOG_NOTICE || loglevel == LOG_INFO); pjdlogv_common(loglevel, 0, -1, fmt, ap); } /* * Regular logs. */ void pjdlog(int loglevel, const char *fmt, ...) { va_list ap; assert(pjdlog_initialized == PJDLOG_INITIALIZED); va_start(ap, fmt); pjdlogv(loglevel, fmt, ap); va_end(ap); } /* * Debug logs. */ void pjdlogv_debug(int debuglevel, const char *fmt, va_list ap) { assert(pjdlog_initialized == PJDLOG_INITIALIZED); pjdlogv_common(LOG_DEBUG, debuglevel, -1, fmt, ap); } /* * Debug logs. */ void pjdlog_debug(int debuglevel, const char *fmt, ...) { va_list ap; assert(pjdlog_initialized == PJDLOG_INITIALIZED); va_start(ap, fmt); pjdlogv_debug(debuglevel, fmt, ap); va_end(ap); } /* * Error logs with errno logging. */ void pjdlogv_errno(int loglevel, const char *fmt, va_list ap) { assert(pjdlog_initialized == PJDLOG_INITIALIZED); pjdlogv_common(loglevel, 0, errno, fmt, ap); } /* * Error logs with errno logging. */ void pjdlog_errno(int loglevel, const char *fmt, ...) { va_list ap; assert(pjdlog_initialized == PJDLOG_INITIALIZED); va_start(ap, fmt); pjdlogv_errno(loglevel, fmt, ap); va_end(ap); } /* * Log error, errno and exit. */ void pjdlogv_exit(int exitcode, const char *fmt, va_list ap) { assert(pjdlog_initialized == PJDLOG_INITIALIZED); pjdlogv_errno(LOG_ERR, fmt, ap); exit(exitcode); /* NOTREACHED */ } /* * Log error, errno and exit. */ void pjdlog_exit(int exitcode, const char *fmt, ...) { va_list ap; assert(pjdlog_initialized == PJDLOG_INITIALIZED); va_start(ap, fmt); pjdlogv_exit(exitcode, fmt, ap); /* NOTREACHED */ va_end(ap); } /* * Log error and exit. */ void pjdlogv_exitx(int exitcode, const char *fmt, va_list ap) { assert(pjdlog_initialized == PJDLOG_INITIALIZED); pjdlogv(LOG_ERR, fmt, ap); exit(exitcode); /* NOTREACHED */ } /* * Log error and exit. */ void pjdlog_exitx(int exitcode, const char *fmt, ...) { va_list ap; assert(pjdlog_initialized == PJDLOG_INITIALIZED); va_start(ap, fmt); pjdlogv_exitx(exitcode, fmt, ap); /* NOTREACHED */ va_end(ap); } /* * Log failure message and exit. */ void pjdlog_abort(const char *func, const char *file, int line, const char *failedexpr, const char *fmt, ...) { va_list ap; assert(pjdlog_initialized == PJDLOG_INITIALIZED); /* * When there is no message we pass __func__ as 'fmt'. * It would be cleaner to pass NULL or "", but gcc generates a warning * for both of those. */ if (fmt != func) { va_start(ap, fmt); pjdlogv_critical(fmt, ap); va_end(ap); } if (failedexpr == NULL) { if (func == NULL) { pjdlog_critical("Aborted at file %s, line %d.", file, line); } else { pjdlog_critical("Aborted at function %s, file %s, line %d.", func, file, line); } } else { if (func == NULL) { pjdlog_critical("Assertion failed: (%s), file %s, line %d.", failedexpr, file, line); } else { pjdlog_critical("Assertion failed: (%s), function %s, file %s, line %d.", failedexpr, func, file, line); } } abort(); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/pjdlog.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/pjdlog.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/pjdlog.h (revision 292449) @@ -1,119 +1,117 @@ /*- * Copyright (c) 2009-2010 The FreeBSD Foundation * Copyright (c) 2011 Pawel Jakub Dawidek * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/pjdlog.h#1 $ */ #ifndef _PJDLOG_H_ #define _PJDLOG_H_ #include #include #include #include #include #define PJDLOG_MODE_STD 0 #define PJDLOG_MODE_SYSLOG 1 void pjdlog_init(int mode); void pjdlog_fini(void); void pjdlog_mode_set(int mode); int pjdlog_mode_get(void); void pjdlog_debug_set(int level); int pjdlog_debug_get(void); void pjdlog_prefix_set(const char *fmt, ...) __printflike(1, 2); void pjdlogv_prefix_set(const char *fmt, va_list ap) __printflike(1, 0); void pjdlog_common(int loglevel, int debuglevel, int error, const char *fmt, ...) __printflike(4, 5); void pjdlogv_common(int loglevel, int debuglevel, int error, const char *fmt, va_list ap) __printflike(4, 0); void pjdlog(int loglevel, const char *fmt, ...) __printflike(2, 3); void pjdlogv(int loglevel, const char *fmt, va_list ap) __printflike(2, 0); #define pjdlogv_emergency(fmt, ap) pjdlogv(LOG_EMERG, (fmt), (ap)) #define pjdlog_emergency(...) pjdlog(LOG_EMERG, __VA_ARGS__) #define pjdlogv_alert(fmt, ap) pjdlogv(LOG_ALERT, (fmt), (ap)) #define pjdlog_alert(...) pjdlog(LOG_ALERT, __VA_ARGS__) #define pjdlogv_critical(fmt, ap) pjdlogv(LOG_CRIT, (fmt), (ap)) #define pjdlog_critical(...) pjdlog(LOG_CRIT, __VA_ARGS__) #define pjdlogv_error(fmt, ap) pjdlogv(LOG_ERR, (fmt), (ap)) #define pjdlog_error(...) pjdlog(LOG_ERR, __VA_ARGS__) #define pjdlogv_warning(fmt, ap) pjdlogv(LOG_WARNING, (fmt), (ap)) #define pjdlog_warning(...) pjdlog(LOG_WARNING, __VA_ARGS__) #define pjdlogv_notice(fmt, ap) pjdlogv(LOG_NOTICE, (fmt), (ap)) #define pjdlog_notice(...) pjdlog(LOG_NOTICE, __VA_ARGS__) #define pjdlogv_info(fmt, ap) pjdlogv(LOG_INFO, (fmt), (ap)) #define pjdlog_info(...) pjdlog(LOG_INFO, __VA_ARGS__) void pjdlog_debug(int debuglevel, const char *fmt, ...) __printflike(2, 3); void pjdlogv_debug(int debuglevel, const char *fmt, va_list ap) __printflike(2, 0); void pjdlog_errno(int loglevel, const char *fmt, ...) __printflike(2, 3); void pjdlogv_errno(int loglevel, const char *fmt, va_list ap) __printflike(2, 0); void pjdlog_exit(int exitcode, const char *fmt, ...) __printflike(2, 3) __dead2; void pjdlogv_exit(int exitcode, const char *fmt, va_list ap) __printflike(2, 0) __dead2; void pjdlog_exitx(int exitcode, const char *fmt, ...) __printflike(2, 3) __dead2; void pjdlogv_exitx(int exitcode, const char *fmt, va_list ap) __printflike(2, 0) __dead2; void pjdlog_abort(const char *func, const char *file, int line, const char *failedexpr, const char *fmt, ...) __printflike(5, 6) __dead2; #define PJDLOG_VERIFY(expr) do { \ if (!(expr)) { \ pjdlog_abort(__func__, __FILE__, __LINE__, #expr, \ "%s", __func__); \ } \ } while (0) #define PJDLOG_RVERIFY(expr, ...) do { \ if (!(expr)) { \ pjdlog_abort(__func__, __FILE__, __LINE__, #expr, \ __VA_ARGS__); \ } \ } while (0) #define PJDLOG_ABORT(...) pjdlog_abort(__func__, __FILE__, \ __LINE__, NULL, __VA_ARGS__) #ifdef NDEBUG #define PJDLOG_ASSERT(expr) do { } while (0) #define PJDLOG_RASSERT(...) do { } while (0) #else #define PJDLOG_ASSERT(expr) PJDLOG_VERIFY(expr) #define PJDLOG_RASSERT(...) PJDLOG_RVERIFY(__VA_ARGS__) #endif #endif /* !_PJDLOG_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto.c (revision 292449) @@ -1,529 +1,527 @@ /*- * Copyright (c) 2009-2010 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/proto.c#1 $ */ #include #include #include #include #include #include #include #include "pjdlog.h" #include "proto.h" #include "proto_impl.h" #define PROTO_CONN_MAGIC 0x907041c struct proto_conn { int pc_magic; struct proto *pc_proto; void *pc_ctx; int pc_side; #define PROTO_SIDE_CLIENT 0 #define PROTO_SIDE_SERVER_LISTEN 1 #define PROTO_SIDE_SERVER_WORK 2 }; static TAILQ_HEAD(, proto) protos = TAILQ_HEAD_INITIALIZER(protos); void proto_register(struct proto *proto, bool isdefault) { static bool seen_default = false; if (!isdefault) TAILQ_INSERT_HEAD(&protos, proto, prt_next); else { PJDLOG_ASSERT(!seen_default); seen_default = true; TAILQ_INSERT_TAIL(&protos, proto, prt_next); } } static struct proto_conn * proto_alloc(struct proto *proto, int side) { struct proto_conn *conn; PJDLOG_ASSERT(proto != NULL); PJDLOG_ASSERT(side == PROTO_SIDE_CLIENT || side == PROTO_SIDE_SERVER_LISTEN || side == PROTO_SIDE_SERVER_WORK); conn = malloc(sizeof(*conn)); if (conn != NULL) { conn->pc_proto = proto; conn->pc_side = side; conn->pc_magic = PROTO_CONN_MAGIC; } return (conn); } static void proto_free(struct proto_conn *conn) { PJDLOG_ASSERT(conn != NULL); PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); PJDLOG_ASSERT(conn->pc_side == PROTO_SIDE_CLIENT || conn->pc_side == PROTO_SIDE_SERVER_LISTEN || conn->pc_side == PROTO_SIDE_SERVER_WORK); PJDLOG_ASSERT(conn->pc_proto != NULL); bzero(conn, sizeof(*conn)); free(conn); } static int proto_common_setup(const char *srcaddr, const char *dstaddr, int timeout, int side, struct proto_conn **connp) { struct proto *proto; struct proto_conn *conn; void *ctx; int ret; PJDLOG_ASSERT(side == PROTO_SIDE_CLIENT || side == PROTO_SIDE_SERVER_LISTEN); TAILQ_FOREACH(proto, &protos, prt_next) { if (side == PROTO_SIDE_CLIENT) { if (proto->prt_connect == NULL) { ret = -1; } else { ret = proto->prt_connect(srcaddr, dstaddr, timeout, &ctx); } } else /* if (side == PROTO_SIDE_SERVER_LISTEN) */ { if (proto->prt_server == NULL) ret = -1; else ret = proto->prt_server(dstaddr, &ctx); } /* * ret == 0 - success * ret == -1 - dstaddr is not for this protocol * ret > 0 - right protocol, but an error occured */ if (ret >= 0) break; } if (proto == NULL) { /* Unrecognized address. */ errno = EINVAL; return (-1); } if (ret > 0) { /* An error occured. */ errno = ret; return (-1); } conn = proto_alloc(proto, side); if (conn == NULL) { if (proto->prt_close != NULL) proto->prt_close(ctx); errno = ENOMEM; return (-1); } conn->pc_ctx = ctx; *connp = conn; return (0); } int proto_connect(const char *srcaddr, const char *dstaddr, int timeout, struct proto_conn **connp) { PJDLOG_ASSERT(srcaddr == NULL || srcaddr[0] != '\0'); PJDLOG_ASSERT(dstaddr != NULL); PJDLOG_ASSERT(timeout >= -1); return (proto_common_setup(srcaddr, dstaddr, timeout, PROTO_SIDE_CLIENT, connp)); } int proto_connect_wait(struct proto_conn *conn, int timeout) { int error; PJDLOG_ASSERT(conn != NULL); PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); PJDLOG_ASSERT(conn->pc_side == PROTO_SIDE_CLIENT); PJDLOG_ASSERT(conn->pc_proto != NULL); PJDLOG_ASSERT(conn->pc_proto->prt_connect_wait != NULL); PJDLOG_ASSERT(timeout >= 0); error = conn->pc_proto->prt_connect_wait(conn->pc_ctx, timeout); if (error != 0) { errno = error; return (-1); } return (0); } int proto_server(const char *addr, struct proto_conn **connp) { PJDLOG_ASSERT(addr != NULL); return (proto_common_setup(NULL, addr, -1, PROTO_SIDE_SERVER_LISTEN, connp)); } int proto_accept(struct proto_conn *conn, struct proto_conn **newconnp) { struct proto_conn *newconn; int error; PJDLOG_ASSERT(conn != NULL); PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); PJDLOG_ASSERT(conn->pc_side == PROTO_SIDE_SERVER_LISTEN); PJDLOG_ASSERT(conn->pc_proto != NULL); PJDLOG_ASSERT(conn->pc_proto->prt_accept != NULL); newconn = proto_alloc(conn->pc_proto, PROTO_SIDE_SERVER_WORK); if (newconn == NULL) return (-1); error = conn->pc_proto->prt_accept(conn->pc_ctx, &newconn->pc_ctx); if (error != 0) { proto_free(newconn); errno = error; return (-1); } *newconnp = newconn; return (0); } int proto_send(const struct proto_conn *conn, const void *data, size_t size) { int error; PJDLOG_ASSERT(conn != NULL); PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); PJDLOG_ASSERT(conn->pc_proto != NULL); PJDLOG_ASSERT(conn->pc_proto->prt_send != NULL); error = conn->pc_proto->prt_send(conn->pc_ctx, data, size, -1); if (error != 0) { errno = error; return (-1); } return (0); } int proto_recv(const struct proto_conn *conn, void *data, size_t size) { int error; PJDLOG_ASSERT(conn != NULL); PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); PJDLOG_ASSERT(conn->pc_proto != NULL); PJDLOG_ASSERT(conn->pc_proto->prt_recv != NULL); error = conn->pc_proto->prt_recv(conn->pc_ctx, data, size, NULL); if (error != 0) { errno = error; return (-1); } return (0); } int proto_connection_send(const struct proto_conn *conn, struct proto_conn *mconn) { const char *protoname; int error, fd; PJDLOG_ASSERT(conn != NULL); PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); PJDLOG_ASSERT(conn->pc_proto != NULL); PJDLOG_ASSERT(conn->pc_proto->prt_send != NULL); PJDLOG_ASSERT(mconn != NULL); PJDLOG_ASSERT(mconn->pc_magic == PROTO_CONN_MAGIC); PJDLOG_ASSERT(mconn->pc_proto != NULL); fd = proto_descriptor(mconn); PJDLOG_ASSERT(fd >= 0); protoname = mconn->pc_proto->prt_name; PJDLOG_ASSERT(protoname != NULL); error = conn->pc_proto->prt_send(conn->pc_ctx, (const unsigned char *)protoname, strlen(protoname) + 1, fd); proto_close(mconn); if (error != 0) { errno = error; return (-1); } return (0); } int proto_wrap(const char *protoname, bool client, int fd, struct proto_conn **newconnp) { struct proto *proto; struct proto_conn *newconn; int error; TAILQ_FOREACH(proto, &protos, prt_next) { if (strcmp(proto->prt_name, protoname) == 0) break; } if (proto == NULL) { errno = EINVAL; return (-1); } newconn = proto_alloc(proto, client ? PROTO_SIDE_CLIENT : PROTO_SIDE_SERVER_WORK); if (newconn == NULL) return (-1); PJDLOG_ASSERT(newconn->pc_proto->prt_wrap != NULL); error = newconn->pc_proto->prt_wrap(fd, client, &newconn->pc_ctx); if (error != 0) { proto_free(newconn); errno = error; return (-1); } *newconnp = newconn; return (0); } int proto_connection_recv(const struct proto_conn *conn, bool client, struct proto_conn **newconnp) { char protoname[128]; int error, fd; PJDLOG_ASSERT(conn != NULL); PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); PJDLOG_ASSERT(conn->pc_proto != NULL); PJDLOG_ASSERT(conn->pc_proto->prt_recv != NULL); PJDLOG_ASSERT(newconnp != NULL); bzero(protoname, sizeof(protoname)); error = conn->pc_proto->prt_recv(conn->pc_ctx, (unsigned char *)protoname, sizeof(protoname) - 1, &fd); if (error != 0) { errno = error; return (-1); } PJDLOG_ASSERT(fd >= 0); return (proto_wrap(protoname, client, fd, newconnp)); } int proto_descriptor(const struct proto_conn *conn) { PJDLOG_ASSERT(conn != NULL); PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); PJDLOG_ASSERT(conn->pc_proto != NULL); PJDLOG_ASSERT(conn->pc_proto->prt_descriptor != NULL); return (conn->pc_proto->prt_descriptor(conn->pc_ctx)); } bool proto_address_match(const struct proto_conn *conn, const char *addr) { PJDLOG_ASSERT(conn != NULL); PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); PJDLOG_ASSERT(conn->pc_proto != NULL); PJDLOG_ASSERT(conn->pc_proto->prt_address_match != NULL); return (conn->pc_proto->prt_address_match(conn->pc_ctx, addr)); } void proto_local_address(const struct proto_conn *conn, char *addr, size_t size) { PJDLOG_ASSERT(conn != NULL); PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); PJDLOG_ASSERT(conn->pc_proto != NULL); PJDLOG_ASSERT(conn->pc_proto->prt_local_address != NULL); conn->pc_proto->prt_local_address(conn->pc_ctx, addr, size); } void proto_remote_address(const struct proto_conn *conn, char *addr, size_t size) { PJDLOG_ASSERT(conn != NULL); PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); PJDLOG_ASSERT(conn->pc_proto != NULL); PJDLOG_ASSERT(conn->pc_proto->prt_remote_address != NULL); conn->pc_proto->prt_remote_address(conn->pc_ctx, addr, size); } int proto_timeout(const struct proto_conn *conn, int timeout) { struct timeval tv; int fd; PJDLOG_ASSERT(conn != NULL); PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); PJDLOG_ASSERT(conn->pc_proto != NULL); fd = proto_descriptor(conn); if (fd < 0) return (-1); tv.tv_sec = timeout; tv.tv_usec = 0; if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) return (-1); if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) return (-1); return (0); } void proto_close(struct proto_conn *conn) { PJDLOG_ASSERT(conn != NULL); PJDLOG_ASSERT(conn->pc_magic == PROTO_CONN_MAGIC); PJDLOG_ASSERT(conn->pc_proto != NULL); PJDLOG_ASSERT(conn->pc_proto->prt_close != NULL); conn->pc_proto->prt_close(conn->pc_ctx); proto_free(conn); } int proto_exec(int argc, char *argv[]) { struct proto *proto; int error; if (argc == 0) { errno = EINVAL; return (-1); } TAILQ_FOREACH(proto, &protos, prt_next) { if (strcmp(proto->prt_name, argv[0]) == 0) break; } if (proto == NULL) { errno = EINVAL; return (-1); } if (proto->prt_exec == NULL) { errno = EOPNOTSUPP; return (-1); } error = proto->prt_exec(argc, argv); if (error != 0) { errno = error; return (-1); } /* NOTREACHED */ return (0); } struct proto_nvpair { char *pnv_name; char *pnv_value; TAILQ_ENTRY(proto_nvpair) pnv_next; }; static TAILQ_HEAD(, proto_nvpair) proto_nvpairs = TAILQ_HEAD_INITIALIZER(proto_nvpairs); int proto_set(const char *name, const char *value) { struct proto_nvpair *pnv; TAILQ_FOREACH(pnv, &proto_nvpairs, pnv_next) { if (strcmp(pnv->pnv_name, name) == 0) break; } if (pnv != NULL) { TAILQ_REMOVE(&proto_nvpairs, pnv, pnv_next); free(pnv->pnv_value); } else { pnv = malloc(sizeof(*pnv)); if (pnv == NULL) return (-1); pnv->pnv_name = strdup(name); if (pnv->pnv_name == NULL) { free(pnv); return (-1); } } pnv->pnv_value = strdup(value); if (pnv->pnv_value == NULL) { free(pnv->pnv_name); free(pnv); return (-1); } TAILQ_INSERT_TAIL(&proto_nvpairs, pnv, pnv_next); return (0); } const char * proto_get(const char *name) { struct proto_nvpair *pnv; TAILQ_FOREACH(pnv, &proto_nvpairs, pnv_next) { if (strcmp(pnv->pnv_name, name) == 0) break; } if (pnv != NULL) return (pnv->pnv_value); return (NULL); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto.h (revision 292449) @@ -1,63 +1,61 @@ /*- * Copyright (c) 2009-2010 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/proto.h#1 $ */ #ifndef _PROTO_H_ #define _PROTO_H_ #include /* bool */ #include /* size_t */ struct proto_conn; int proto_connect(const char *srcaddr, const char *dstaddr, int timeout, struct proto_conn **connp); int proto_connect_wait(struct proto_conn *conn, int timeout); int proto_server(const char *addr, struct proto_conn **connp); int proto_accept(struct proto_conn *conn, struct proto_conn **newconnp); int proto_send(const struct proto_conn *conn, const void *data, size_t size); int proto_recv(const struct proto_conn *conn, void *data, size_t size); int proto_connection_send(const struct proto_conn *conn, struct proto_conn *mconn); int proto_connection_recv(const struct proto_conn *conn, bool client, struct proto_conn **newconnp); int proto_descriptor(const struct proto_conn *conn); bool proto_address_match(const struct proto_conn *conn, const char *addr); void proto_local_address(const struct proto_conn *conn, char *addr, size_t size); void proto_remote_address(const struct proto_conn *conn, char *addr, size_t size); int proto_timeout(const struct proto_conn *conn, int timeout); void proto_close(struct proto_conn *conn); int proto_exec(int argc, char *argv[]); int proto_set(const char *name, const char *value); const char *proto_get(const char *name); #endif /* !_PROTO_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_common.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_common.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_common.c (revision 292449) @@ -1,233 +1,231 @@ /*- * Copyright (c) 2009-2010 The FreeBSD Foundation * Copyright (c) 2011 Pawel Jakub Dawidek * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/proto_common.c#1 $ */ #include #include #include #include #include #include #include #include #include #include "pjdlog.h" #include "proto_impl.h" /* Maximum size of packet we want to use when sending data. */ #ifndef MAX_SEND_SIZE #define MAX_SEND_SIZE 32768 #endif static bool blocking_socket(int sock) { int flags; flags = fcntl(sock, F_GETFL); PJDLOG_ASSERT(flags >= 0); return ((flags & O_NONBLOCK) == 0); } static int proto_descriptor_send(int sock, int fd) { unsigned char ctrl[CMSG_SPACE(sizeof(fd))]; struct msghdr msg; struct cmsghdr *cmsg; PJDLOG_ASSERT(sock >= 0); PJDLOG_ASSERT(fd >= 0); bzero(&msg, sizeof(msg)); bzero(&ctrl, sizeof(ctrl)); msg.msg_iov = NULL; msg.msg_iovlen = 0; msg.msg_control = ctrl; msg.msg_controllen = sizeof(ctrl); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); bcopy(&fd, CMSG_DATA(cmsg), sizeof(fd)); if (sendmsg(sock, &msg, 0) == -1) return (errno); return (0); } int proto_common_send(int sock, const unsigned char *data, size_t size, int fd) { ssize_t done; size_t sendsize; int errcount = 0; PJDLOG_ASSERT(sock >= 0); if (data == NULL) { /* The caller is just trying to decide about direction. */ PJDLOG_ASSERT(size == 0); if (shutdown(sock, SHUT_RD) == -1) return (errno); return (0); } PJDLOG_ASSERT(data != NULL); PJDLOG_ASSERT(size > 0); do { sendsize = size < MAX_SEND_SIZE ? size : MAX_SEND_SIZE; done = send(sock, data, sendsize, MSG_NOSIGNAL); if (done == 0) { return (ENOTCONN); } else if (done < 0) { if (errno == EINTR) continue; if (errno == ENOBUFS) { /* * If there are no buffers we retry. * After each try we increase delay before the * next one and we give up after fifteen times. * This gives 11s of total wait time. */ if (errcount == 15) { pjdlog_warning("Getting ENOBUFS errors for 11s on send(), giving up."); } else { if (errcount == 0) pjdlog_warning("Got ENOBUFS error on send(), retrying for a bit."); errcount++; usleep(100000 * errcount); continue; } } /* * If this is blocking socket and we got EAGAIN, this * means the request timed out. Translate errno to * ETIMEDOUT, to give administrator a hint to * eventually increase timeout. */ if (errno == EAGAIN && blocking_socket(sock)) errno = ETIMEDOUT; return (errno); } data += done; size -= done; } while (size > 0); if (errcount > 0) { pjdlog_info("Data sent successfully after %d ENOBUFS error%s.", errcount, errcount == 1 ? "" : "s"); } if (fd == -1) return (0); return (proto_descriptor_send(sock, fd)); } static int proto_descriptor_recv(int sock, int *fdp) { unsigned char ctrl[CMSG_SPACE(sizeof(*fdp))]; struct msghdr msg; struct cmsghdr *cmsg; PJDLOG_ASSERT(sock >= 0); PJDLOG_ASSERT(fdp != NULL); bzero(&msg, sizeof(msg)); bzero(&ctrl, sizeof(ctrl)); msg.msg_iov = NULL; msg.msg_iovlen = 0; msg.msg_control = ctrl; msg.msg_controllen = sizeof(ctrl); if (recvmsg(sock, &msg, 0) == -1) return (errno); cmsg = CMSG_FIRSTHDR(&msg); if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) { return (EINVAL); } bcopy(CMSG_DATA(cmsg), fdp, sizeof(*fdp)); return (0); } int proto_common_recv(int sock, unsigned char *data, size_t size, int *fdp) { ssize_t done; PJDLOG_ASSERT(sock >= 0); if (data == NULL) { /* The caller is just trying to decide about direction. */ PJDLOG_ASSERT(size == 0); if (shutdown(sock, SHUT_WR) == -1) return (errno); return (0); } PJDLOG_ASSERT(data != NULL); PJDLOG_ASSERT(size > 0); do { done = recv(sock, data, size, MSG_WAITALL); } while (done == -1 && errno == EINTR); if (done == 0) { return (ENOTCONN); } else if (done < 0) { /* * If this is blocking socket and we got EAGAIN, this * means the request timed out. Translate errno to * ETIMEDOUT, to give administrator a hint to * eventually increase timeout. */ if (errno == EAGAIN && blocking_socket(sock)) errno = ETIMEDOUT; return (errno); } if (fdp == NULL) return (0); return (proto_descriptor_recv(sock, fdp)); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_impl.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_impl.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_impl.h (revision 292449) @@ -1,84 +1,82 @@ /*- * Copyright (c) 2009-2010 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/proto_impl.h#1 $ */ #ifndef _PROTO_IMPL_H_ #define _PROTO_IMPL_H_ #include #include /* bool */ #include /* size_t */ #define __constructor __attribute__((constructor)) struct proto_conn; typedef int prt_connect_t(const char *, const char *, int, void **); typedef int prt_connect_wait_t(void *, int); typedef int prt_server_t(const char *, void **); typedef int prt_accept_t(void *, void **); typedef int prt_wrap_t(int, bool, void **); typedef int prt_send_t(void *, const unsigned char *, size_t, int); typedef int prt_recv_t(void *, unsigned char *, size_t, int *); typedef int prt_descriptor_t(const void *); typedef bool prt_address_match_t(const void *, const char *); typedef void prt_local_address_t(const void *, char *, size_t); typedef void prt_remote_address_t(const void *, char *, size_t); typedef void prt_close_t(void *); typedef int prt_exec_t(int, char *[]); struct proto { const char *prt_name; prt_connect_t *prt_connect; prt_connect_wait_t *prt_connect_wait; prt_server_t *prt_server; prt_accept_t *prt_accept; prt_wrap_t *prt_wrap; prt_send_t *prt_send; prt_recv_t *prt_recv; prt_descriptor_t *prt_descriptor; prt_address_match_t *prt_address_match; prt_local_address_t *prt_local_address; prt_remote_address_t *prt_remote_address; prt_close_t *prt_close; prt_exec_t *prt_exec; TAILQ_ENTRY(proto) prt_next; }; void proto_register(struct proto *proto, bool isdefault); int proto_wrap(const char *protoname, bool client, int fd, struct proto_conn **newconnp); int proto_common_send(int sock, const unsigned char *data, size_t size, int fd); int proto_common_recv(int sock, unsigned char *data, size_t size, int *fdp); #endif /* !_PROTO_IMPL_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_socketpair.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_socketpair.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_socketpair.c (revision 292449) @@ -1,266 +1,264 @@ /*- * Copyright (c) 2009-2010 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/proto_socketpair.c#1 $ */ #include #include #include #include #include #include #include #include #include "pjdlog.h" #include "proto_impl.h" #define SP_CTX_MAGIC 0x50c3741 struct sp_ctx { int sp_magic; int sp_fd[2]; int sp_side; #define SP_SIDE_UNDEF 0 #define SP_SIDE_CLIENT 1 #define SP_SIDE_SERVER 2 }; static void sp_close(void *ctx); static int sp_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp) { struct sp_ctx *spctx; int error; PJDLOG_ASSERT(dstaddr != NULL); PJDLOG_ASSERT(timeout >= -1); if (strcmp(dstaddr, "socketpair://") != 0) return (-1); PJDLOG_ASSERT(srcaddr == NULL); spctx = malloc(sizeof(*spctx)); if (spctx == NULL) return (errno); if (socketpair(PF_UNIX, SOCK_STREAM, 0, spctx->sp_fd) == -1) { error = errno; free(spctx); return (error); } spctx->sp_side = SP_SIDE_UNDEF; spctx->sp_magic = SP_CTX_MAGIC; *ctxp = spctx; return (0); } static int sp_wrap(int fd, bool client, void **ctxp) { struct sp_ctx *spctx; PJDLOG_ASSERT(fd >= 0); spctx = malloc(sizeof(*spctx)); if (spctx == NULL) return (errno); if (client) { spctx->sp_side = SP_SIDE_CLIENT; spctx->sp_fd[0] = fd; spctx->sp_fd[1] = -1; } else { spctx->sp_side = SP_SIDE_SERVER; spctx->sp_fd[0] = -1; spctx->sp_fd[1] = fd; } spctx->sp_magic = SP_CTX_MAGIC; *ctxp = spctx; return (0); } static int sp_send(void *ctx, const unsigned char *data, size_t size, int fd) { struct sp_ctx *spctx = ctx; int sock; PJDLOG_ASSERT(spctx != NULL); PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); switch (spctx->sp_side) { case SP_SIDE_UNDEF: /* * If the first operation done by the caller is proto_send(), * we assume this is the client. */ /* FALLTHROUGH */ spctx->sp_side = SP_SIDE_CLIENT; /* Close other end. */ close(spctx->sp_fd[1]); spctx->sp_fd[1] = -1; case SP_SIDE_CLIENT: PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); sock = spctx->sp_fd[0]; break; case SP_SIDE_SERVER: PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); sock = spctx->sp_fd[1]; break; default: PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); } /* Someone is just trying to decide about side. */ if (data == NULL) return (0); return (proto_common_send(sock, data, size, fd)); } static int sp_recv(void *ctx, unsigned char *data, size_t size, int *fdp) { struct sp_ctx *spctx = ctx; int sock; PJDLOG_ASSERT(spctx != NULL); PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); switch (spctx->sp_side) { case SP_SIDE_UNDEF: /* * If the first operation done by the caller is proto_recv(), * we assume this is the server. */ /* FALLTHROUGH */ spctx->sp_side = SP_SIDE_SERVER; /* Close other end. */ close(spctx->sp_fd[0]); spctx->sp_fd[0] = -1; case SP_SIDE_SERVER: PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); sock = spctx->sp_fd[1]; break; case SP_SIDE_CLIENT: PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); sock = spctx->sp_fd[0]; break; default: PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); } /* Someone is just trying to decide about side. */ if (data == NULL) return (0); return (proto_common_recv(sock, data, size, fdp)); } static int sp_descriptor(const void *ctx) { const struct sp_ctx *spctx = ctx; PJDLOG_ASSERT(spctx != NULL); PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); PJDLOG_ASSERT(spctx->sp_side == SP_SIDE_CLIENT || spctx->sp_side == SP_SIDE_SERVER); switch (spctx->sp_side) { case SP_SIDE_CLIENT: PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); return (spctx->sp_fd[0]); case SP_SIDE_SERVER: PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); return (spctx->sp_fd[1]); } PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); } static void sp_close(void *ctx) { struct sp_ctx *spctx = ctx; PJDLOG_ASSERT(spctx != NULL); PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); switch (spctx->sp_side) { case SP_SIDE_UNDEF: PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); close(spctx->sp_fd[0]); spctx->sp_fd[0] = -1; PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); close(spctx->sp_fd[1]); spctx->sp_fd[1] = -1; break; case SP_SIDE_CLIENT: PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); close(spctx->sp_fd[0]); spctx->sp_fd[0] = -1; PJDLOG_ASSERT(spctx->sp_fd[1] == -1); break; case SP_SIDE_SERVER: PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); close(spctx->sp_fd[1]); spctx->sp_fd[1] = -1; PJDLOG_ASSERT(spctx->sp_fd[0] == -1); break; default: PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); } spctx->sp_magic = 0; free(spctx); } static struct proto sp_proto = { .prt_name = "socketpair", .prt_connect = sp_connect, .prt_wrap = sp_wrap, .prt_send = sp_send, .prt_recv = sp_recv, .prt_descriptor = sp_descriptor, .prt_close = sp_close }; static __constructor void sp_ctor(void) { proto_register(&sp_proto, false); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_tcp.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_tcp.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_tcp.c (revision 292449) @@ -1,723 +1,721 @@ /*- * Copyright (c) 2009-2010 The FreeBSD Foundation * Copyright (c) 2011 Pawel Jakub Dawidek * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/proto_tcp.c#2 $ */ #include #include /* MAXHOSTNAMELEN */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef HAVE_STRLCPY #include #endif #include "pjdlog.h" #include "proto_impl.h" #include "subr.h" #define TCP_CTX_MAGIC 0x7c41c struct tcp_ctx { int tc_magic; struct sockaddr_storage tc_sa; int tc_fd; int tc_side; #define TCP_SIDE_CLIENT 0 #define TCP_SIDE_SERVER_LISTEN 1 #define TCP_SIDE_SERVER_WORK 2 bool tc_wait_called; }; static int tcp_connect_wait(void *ctx, int timeout); static void tcp_close(void *ctx); /* * Function converts the given string to unsigned number. */ static int numfromstr(const char *str, intmax_t minnum, intmax_t maxnum, intmax_t *nump) { intmax_t digit, num; if (str[0] == '\0') goto invalid; /* Empty string. */ num = 0; for (; *str != '\0'; str++) { if (*str < '0' || *str > '9') goto invalid; /* Non-digit character. */ digit = *str - '0'; if (num > num * 10 + digit) goto invalid; /* Overflow. */ num = num * 10 + digit; if (num > maxnum) goto invalid; /* Too big. */ } if (num < minnum) goto invalid; /* Too small. */ *nump = num; return (0); invalid: errno = EINVAL; return (-1); } static int tcp_addr(const char *addr, int defport, struct sockaddr_storage *sap) { char iporhost[MAXHOSTNAMELEN], portstr[6]; struct addrinfo hints; struct addrinfo *res; const char *pp; intmax_t port; size_t size; int error; if (addr == NULL) return (-1); bzero(&hints, sizeof(hints)); hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; if (strncasecmp(addr, "tcp4://", 7) == 0) { addr += 7; hints.ai_family = PF_INET; } else if (strncasecmp(addr, "tcp6://", 7) == 0) { addr += 7; hints.ai_family = PF_INET6; } else if (strncasecmp(addr, "tcp://", 6) == 0) { addr += 6; } else { /* * Because TCP is the default assume IP or host is given without * prefix. */ } /* * Extract optional port. * There are three cases to consider. * 1. hostname with port, eg. freefall.freebsd.org:8457 * 2. IPv4 address with port, eg. 192.168.0.101:8457 * 3. IPv6 address with port, eg. [fe80::1]:8457 * We discover IPv6 address by checking for two colons and if port is * given, the address has to start with [. */ pp = NULL; if (strchr(addr, ':') != strrchr(addr, ':')) { if (addr[0] == '[') pp = strrchr(addr, ':'); } else { pp = strrchr(addr, ':'); } if (pp == NULL) { /* Port not given, use the default. */ port = defport; } else { if (numfromstr(pp + 1, 1, 65535, &port) < 0) return (errno); } (void)snprintf(portstr, sizeof(portstr), "%jd", (intmax_t)port); /* Extract host name or IP address. */ if (pp == NULL) { size = sizeof(iporhost); if (strlcpy(iporhost, addr, size) >= size) return (ENAMETOOLONG); } else if (addr[0] == '[' && pp[-1] == ']') { size = (size_t)(pp - addr - 2 + 1); if (size > sizeof(iporhost)) return (ENAMETOOLONG); (void)strlcpy(iporhost, addr + 1, size); } else { size = (size_t)(pp - addr + 1); if (size > sizeof(iporhost)) return (ENAMETOOLONG); (void)strlcpy(iporhost, addr, size); } error = getaddrinfo(iporhost, portstr, &hints, &res); if (error != 0) { pjdlog_debug(1, "getaddrinfo(%s, %s) failed: %s.", iporhost, portstr, gai_strerror(error)); return (EINVAL); } if (res == NULL) return (ENOENT); memcpy(sap, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); return (0); } static int tcp_setup_new(const char *addr, int side, struct tcp_ctx **tctxp) { struct tcp_ctx *tctx; int error, nodelay; PJDLOG_ASSERT(addr != NULL); PJDLOG_ASSERT(side == TCP_SIDE_CLIENT || side == TCP_SIDE_SERVER_LISTEN); PJDLOG_ASSERT(tctxp != NULL); tctx = malloc(sizeof(*tctx)); if (tctx == NULL) return (errno); /* Parse given address. */ error = tcp_addr(addr, atoi(proto_get("tcp:port")), &tctx->tc_sa); if (error != 0) { free(tctx); return (error); } PJDLOG_ASSERT(tctx->tc_sa.ss_family != AF_UNSPEC); tctx->tc_fd = socket(tctx->tc_sa.ss_family, SOCK_STREAM, 0); if (tctx->tc_fd == -1) { error = errno; free(tctx); return (error); } PJDLOG_ASSERT(tctx->tc_sa.ss_family != AF_UNSPEC); /* Socket settings. */ nodelay = 1; if (setsockopt(tctx->tc_fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay)) == -1) { pjdlog_errno(LOG_WARNING, "Unable to set TCP_NOELAY"); } tctx->tc_wait_called = (side == TCP_SIDE_CLIENT ? false : true); tctx->tc_side = side; tctx->tc_magic = TCP_CTX_MAGIC; *tctxp = tctx; return (0); } static socklen_t sockaddr_len(const struct sockaddr_storage *ss) { #ifdef HAVE_SOCKADDR_STORAGE_SS_LEN return (ss->ss_len); #else switch (ss->ss_family) { case AF_INET: return (sizeof(struct sockaddr_in)); case AF_INET6: return (sizeof(struct sockaddr_in6)); default: PJDLOG_ABORT("Unexpected family %hhu.", ss->ss_family); } #endif } static int tcp_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp) { struct tcp_ctx *tctx; struct sockaddr_storage sa; int error, flags, ret; PJDLOG_ASSERT(srcaddr == NULL || srcaddr[0] != '\0'); PJDLOG_ASSERT(dstaddr != NULL); PJDLOG_ASSERT(timeout >= -1); error = tcp_setup_new(dstaddr, TCP_SIDE_CLIENT, &tctx); if (error != 0) return (error); if (srcaddr != NULL) { error = tcp_addr(srcaddr, 0, &sa); if (error != 0) goto fail; if (bind(tctx->tc_fd, (struct sockaddr *)&sa, sockaddr_len(&sa)) == -1) { error = errno; goto fail; } } flags = fcntl(tctx->tc_fd, F_GETFL); if (flags == -1) { error = errno; pjdlog_common(LOG_DEBUG, 1, errno, "fcntl(F_GETFL) failed"); goto fail; } /* * We make socket non-blocking so we can handle connection timeout * manually. */ flags |= O_NONBLOCK; if (fcntl(tctx->tc_fd, F_SETFL, flags) == -1) { error = errno; pjdlog_common(LOG_DEBUG, 1, errno, "fcntl(F_SETFL, O_NONBLOCK) failed"); goto fail; } ret = connect(tctx->tc_fd, (struct sockaddr *)&tctx->tc_sa, sockaddr_len(&tctx->tc_sa)); if (ret == -1 && errno != EINPROGRESS) { error = errno; pjdlog_common(LOG_DEBUG, 1, errno, "connect() failed"); goto fail; } if (timeout >= 0) { if (ret == -1) { /* Connection still in progress. Wait for it. */ error = tcp_connect_wait(tctx, timeout); if (error != 0) goto fail; } else { /* Connection already complete. */ flags &= ~O_NONBLOCK; if (fcntl(tctx->tc_fd, F_SETFL, flags) == -1) { error = errno; pjdlog_common(LOG_DEBUG, 1, errno, "fcntl(F_SETFL, ~O_NONBLOCK) failed"); goto fail; } } } *ctxp = tctx; return (0); fail: tcp_close(tctx); return (error); } static int tcp_connect_wait(void *ctx, int timeout) { struct tcp_ctx *tctx = ctx; struct timeval tv; fd_set fdset; socklen_t esize; int error, flags, ret; PJDLOG_ASSERT(tctx != NULL); PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); PJDLOG_ASSERT(tctx->tc_side == TCP_SIDE_CLIENT); PJDLOG_ASSERT(!tctx->tc_wait_called); PJDLOG_ASSERT(tctx->tc_fd >= 0); PJDLOG_ASSERT(timeout >= 0); tv.tv_sec = timeout; tv.tv_usec = 0; again: FD_ZERO(&fdset); FD_SET(tctx->tc_fd, &fdset); ret = select(tctx->tc_fd + 1, NULL, &fdset, NULL, &tv); if (ret == 0) { error = ETIMEDOUT; goto done; } else if (ret == -1) { if (errno == EINTR) goto again; error = errno; pjdlog_common(LOG_DEBUG, 1, errno, "select() failed"); goto done; } PJDLOG_ASSERT(ret > 0); PJDLOG_ASSERT(FD_ISSET(tctx->tc_fd, &fdset)); esize = sizeof(error); if (getsockopt(tctx->tc_fd, SOL_SOCKET, SO_ERROR, &error, &esize) == -1) { error = errno; pjdlog_common(LOG_DEBUG, 1, errno, "getsockopt(SO_ERROR) failed"); goto done; } if (error != 0) { pjdlog_common(LOG_DEBUG, 1, error, "getsockopt(SO_ERROR) returned error"); goto done; } error = 0; tctx->tc_wait_called = true; done: flags = fcntl(tctx->tc_fd, F_GETFL); if (flags == -1) { if (error == 0) error = errno; pjdlog_common(LOG_DEBUG, 1, errno, "fcntl(F_GETFL) failed"); return (error); } flags &= ~O_NONBLOCK; if (fcntl(tctx->tc_fd, F_SETFL, flags) == -1) { if (error == 0) error = errno; pjdlog_common(LOG_DEBUG, 1, errno, "fcntl(F_SETFL, ~O_NONBLOCK) failed"); } return (error); } static int tcp_server(const char *addr, void **ctxp) { struct tcp_ctx *tctx; int error, val; error = tcp_setup_new(addr, TCP_SIDE_SERVER_LISTEN, &tctx); if (error != 0) return (error); val = 1; /* Ignore failure. */ (void)setsockopt(tctx->tc_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); PJDLOG_ASSERT(tctx->tc_sa.ss_family != AF_UNSPEC); if (bind(tctx->tc_fd, (struct sockaddr *)&tctx->tc_sa, sockaddr_len(&tctx->tc_sa)) == -1) { error = errno; tcp_close(tctx); return (error); } if (listen(tctx->tc_fd, 8) == -1) { error = errno; tcp_close(tctx); return (error); } *ctxp = tctx; return (0); } static int tcp_accept(void *ctx, void **newctxp) { struct tcp_ctx *tctx = ctx; struct tcp_ctx *newtctx; socklen_t fromlen; int ret; PJDLOG_ASSERT(tctx != NULL); PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); PJDLOG_ASSERT(tctx->tc_side == TCP_SIDE_SERVER_LISTEN); PJDLOG_ASSERT(tctx->tc_fd >= 0); PJDLOG_ASSERT(tctx->tc_sa.ss_family != AF_UNSPEC); newtctx = malloc(sizeof(*newtctx)); if (newtctx == NULL) return (errno); fromlen = sockaddr_len(&tctx->tc_sa); newtctx->tc_fd = accept(tctx->tc_fd, (struct sockaddr *)&tctx->tc_sa, &fromlen); if (newtctx->tc_fd < 0) { ret = errno; free(newtctx); return (ret); } newtctx->tc_wait_called = true; newtctx->tc_side = TCP_SIDE_SERVER_WORK; newtctx->tc_magic = TCP_CTX_MAGIC; *newctxp = newtctx; return (0); } static int tcp_wrap(int fd, bool client, void **ctxp) { struct tcp_ctx *tctx; PJDLOG_ASSERT(fd >= 0); PJDLOG_ASSERT(ctxp != NULL); tctx = malloc(sizeof(*tctx)); if (tctx == NULL) return (errno); tctx->tc_fd = fd; tctx->tc_sa.ss_family = AF_UNSPEC; tctx->tc_wait_called = (client ? false : true); tctx->tc_side = (client ? TCP_SIDE_CLIENT : TCP_SIDE_SERVER_WORK); tctx->tc_magic = TCP_CTX_MAGIC; *ctxp = tctx; return (0); } static int tcp_send(void *ctx, const unsigned char *data, size_t size, int fd) { struct tcp_ctx *tctx = ctx; PJDLOG_ASSERT(tctx != NULL); PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); PJDLOG_ASSERT(tctx->tc_side == TCP_SIDE_CLIENT || tctx->tc_side == TCP_SIDE_SERVER_WORK); PJDLOG_ASSERT(tctx->tc_wait_called); PJDLOG_ASSERT(tctx->tc_fd >= 0); PJDLOG_ASSERT(fd == -1); return (proto_common_send(tctx->tc_fd, data, size, -1)); } static int tcp_recv(void *ctx, unsigned char *data, size_t size, int *fdp) { struct tcp_ctx *tctx = ctx; PJDLOG_ASSERT(tctx != NULL); PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); PJDLOG_ASSERT(tctx->tc_side == TCP_SIDE_CLIENT || tctx->tc_side == TCP_SIDE_SERVER_WORK); PJDLOG_ASSERT(tctx->tc_wait_called); PJDLOG_ASSERT(tctx->tc_fd >= 0); PJDLOG_ASSERT(fdp == NULL); return (proto_common_recv(tctx->tc_fd, data, size, NULL)); } static int tcp_descriptor(const void *ctx) { const struct tcp_ctx *tctx = ctx; PJDLOG_ASSERT(tctx != NULL); PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); return (tctx->tc_fd); } static bool tcp_address_match(const void *ctx, const char *addr) { const struct tcp_ctx *tctx = ctx; struct sockaddr_storage sa1, sa2; socklen_t salen; PJDLOG_ASSERT(tctx != NULL); PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); if (tcp_addr(addr, atoi(proto_get("tcp:port")), &sa1) != 0) return (false); salen = sizeof(sa2); if (getpeername(tctx->tc_fd, (struct sockaddr *)&sa2, &salen) < 0) return (false); if (sa1.ss_family != sa2.ss_family) return (false); #ifdef HAVE_SOCKADDR_STORAGE_SS_LEN if (sa1.ss_len != sa2.ss_len) return (false); #endif switch (sa1.ss_family) { case AF_INET: { struct sockaddr_in *sin1, *sin2; sin1 = (struct sockaddr_in *)&sa1; sin2 = (struct sockaddr_in *)&sa2; return (memcmp(&sin1->sin_addr, &sin2->sin_addr, sizeof(sin1->sin_addr)) == 0); } case AF_INET6: { struct sockaddr_in6 *sin1, *sin2; sin1 = (struct sockaddr_in6 *)&sa1; sin2 = (struct sockaddr_in6 *)&sa2; return (memcmp(&sin1->sin6_addr, &sin2->sin6_addr, sizeof(sin1->sin6_addr)) == 0); } default: return (false); } } #ifndef __FreeBSD__ static void sockaddr_to_string(const void *sa, char *buf, size_t size) { const struct sockaddr_storage *ss; ss = (const struct sockaddr_storage * const *)sa; switch (ss->ss_family) { case AF_INET: { char addr[INET_ADDRSTRLEN]; const struct sockaddr_in *sin; unsigned int port; sin = (const struct sockaddr_in *)ss; port = ntohs(sin->sin_port); if (inet_ntop(ss->ss_family, &sin->sin_addr, addr, sizeof(addr)) == NULL) { PJDLOG_ABORT("inet_ntop(AF_INET) failed: %s.", strerror(errno)); } snprintf(buf, size, "%s:%u", addr, port); break; } case AF_INET6: { char addr[INET6_ADDRSTRLEN]; const struct sockaddr_in6 *sin; unsigned int port; sin = (const struct sockaddr_in6 *)ss; port = ntohs(sin->sin6_port); if (inet_ntop(ss->ss_family, &sin->sin6_addr, addr, sizeof(addr)) == NULL) { PJDLOG_ABORT("inet_ntop(AF_INET6) failed: %s.", strerror(errno)); } snprintf(buf, size, "[%s]:%u", addr, port); break; } default: snprintf(buf, size, "[unsupported family %hhu]", ss->ss_family); break; } } #endif /* !__FreeBSD__ */ static void tcp_local_address(const void *ctx, char *addr, size_t size) { const struct tcp_ctx *tctx = ctx; struct sockaddr_storage sa; socklen_t salen; PJDLOG_ASSERT(tctx != NULL); PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); salen = sizeof(sa); if (getsockname(tctx->tc_fd, (struct sockaddr *)&sa, &salen) < 0) { PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size); return; } #ifdef __FreeBSD__ PJDLOG_VERIFY(snprintf(addr, size, "tcp://%S", &sa) < (ssize_t)size); #else strlcpy(addr, "tcp://", size); if (size > 6) sockaddr_to_string(&sa, addr + 6, size - 6); #endif } static void tcp_remote_address(const void *ctx, char *addr, size_t size) { const struct tcp_ctx *tctx = ctx; struct sockaddr_storage sa; socklen_t salen; PJDLOG_ASSERT(tctx != NULL); PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); salen = sizeof(sa); if (getpeername(tctx->tc_fd, (struct sockaddr *)&sa, &salen) < 0) { PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size); return; } #ifdef __FreeBSD__ PJDLOG_VERIFY(snprintf(addr, size, "tcp://%S", &sa) < (ssize_t)size); #else strlcpy(addr, "tcp://", size); if (size > 6) sockaddr_to_string(&sa, addr + 6, size - 6); #endif } static void tcp_close(void *ctx) { struct tcp_ctx *tctx = ctx; PJDLOG_ASSERT(tctx != NULL); PJDLOG_ASSERT(tctx->tc_magic == TCP_CTX_MAGIC); if (tctx->tc_fd >= 0) close(tctx->tc_fd); tctx->tc_magic = 0; free(tctx); } static struct proto tcp_proto = { .prt_name = "tcp", .prt_connect = tcp_connect, .prt_connect_wait = tcp_connect_wait, .prt_server = tcp_server, .prt_accept = tcp_accept, .prt_wrap = tcp_wrap, .prt_send = tcp_send, .prt_recv = tcp_recv, .prt_descriptor = tcp_descriptor, .prt_address_match = tcp_address_match, .prt_local_address = tcp_local_address, .prt_remote_address = tcp_remote_address, .prt_close = tcp_close }; static __constructor void tcp_ctor(void) { proto_register(&tcp_proto, true); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_tls.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_tls.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_tls.c (revision 292449) @@ -1,1076 +1,1074 @@ /*- * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/proto_tls.c#2 $ */ #include #include /* MAXHOSTNAMELEN */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef HAVE_CLOSEFROM #include #endif #ifndef HAVE_STRLCPY #include #endif #include "pjdlog.h" #include "proto_impl.h" #include "sandbox.h" #include "subr.h" #define TLS_CTX_MAGIC 0x715c7 struct tls_ctx { int tls_magic; struct proto_conn *tls_sock; struct proto_conn *tls_tcp; char tls_laddr[256]; char tls_raddr[256]; int tls_side; #define TLS_SIDE_CLIENT 0 #define TLS_SIDE_SERVER_LISTEN 1 #define TLS_SIDE_SERVER_WORK 2 bool tls_wait_called; }; #define TLS_DEFAULT_TIMEOUT 30 static int tls_connect_wait(void *ctx, int timeout); static void tls_close(void *ctx); static void block(int fd) { int flags; flags = fcntl(fd, F_GETFL); if (flags == -1) pjdlog_exit(EX_TEMPFAIL, "fcntl(F_GETFL) failed"); flags &= ~O_NONBLOCK; if (fcntl(fd, F_SETFL, flags) == -1) pjdlog_exit(EX_TEMPFAIL, "fcntl(F_SETFL) failed"); } static void nonblock(int fd) { int flags; flags = fcntl(fd, F_GETFL); if (flags == -1) pjdlog_exit(EX_TEMPFAIL, "fcntl(F_GETFL) failed"); flags |= O_NONBLOCK; if (fcntl(fd, F_SETFL, flags) == -1) pjdlog_exit(EX_TEMPFAIL, "fcntl(F_SETFL) failed"); } static int wait_for_fd(int fd, int timeout) { struct timeval tv; fd_set fdset; int error, ret; error = 0; for (;;) { FD_ZERO(&fdset); FD_SET(fd, &fdset); tv.tv_sec = timeout; tv.tv_usec = 0; ret = select(fd + 1, NULL, &fdset, NULL, timeout == -1 ? NULL : &tv); if (ret == 0) { error = ETIMEDOUT; break; } else if (ret == -1) { if (errno == EINTR) continue; error = errno; break; } PJDLOG_ASSERT(ret > 0); PJDLOG_ASSERT(FD_ISSET(fd, &fdset)); break; } return (error); } static void ssl_log_errors(void) { unsigned long error; while ((error = ERR_get_error()) != 0) pjdlog_error("SSL error: %s", ERR_error_string(error, NULL)); } static int ssl_check_error(SSL *ssl, int ret) { int error; error = SSL_get_error(ssl, ret); switch (error) { case SSL_ERROR_NONE: return (0); case SSL_ERROR_WANT_READ: pjdlog_debug(2, "SSL_ERROR_WANT_READ"); return (-1); case SSL_ERROR_WANT_WRITE: pjdlog_debug(2, "SSL_ERROR_WANT_WRITE"); return (-1); case SSL_ERROR_ZERO_RETURN: pjdlog_exitx(EX_OK, "Connection closed."); case SSL_ERROR_SYSCALL: ssl_log_errors(); pjdlog_exitx(EX_TEMPFAIL, "SSL I/O error."); case SSL_ERROR_SSL: ssl_log_errors(); pjdlog_exitx(EX_TEMPFAIL, "SSL protocol error."); default: ssl_log_errors(); pjdlog_exitx(EX_TEMPFAIL, "Unknown SSL error (%d).", error); } } static void tcp_recv_ssl_send(int recvfd, SSL *sendssl) { static unsigned char buf[65536]; ssize_t tcpdone; int sendfd, ssldone; sendfd = SSL_get_fd(sendssl); PJDLOG_ASSERT(sendfd >= 0); pjdlog_debug(2, "%s: start %d -> %d", __func__, recvfd, sendfd); for (;;) { tcpdone = recv(recvfd, buf, sizeof(buf), 0); pjdlog_debug(2, "%s: recv() returned %zd", __func__, tcpdone); if (tcpdone == 0) { pjdlog_debug(1, "Connection terminated."); exit(0); } else if (tcpdone == -1) { if (errno == EINTR) continue; else if (errno == EAGAIN) break; pjdlog_exit(EX_TEMPFAIL, "recv() failed"); } for (;;) { ssldone = SSL_write(sendssl, buf, (int)tcpdone); pjdlog_debug(2, "%s: send() returned %d", __func__, ssldone); if (ssl_check_error(sendssl, ssldone) == -1) { (void)wait_for_fd(sendfd, -1); continue; } PJDLOG_ASSERT(ssldone == tcpdone); break; } } pjdlog_debug(2, "%s: done %d -> %d", __func__, recvfd, sendfd); } static void ssl_recv_tcp_send(SSL *recvssl, int sendfd) { static unsigned char buf[65536]; unsigned char *ptr; ssize_t tcpdone; size_t todo; int recvfd, ssldone; recvfd = SSL_get_fd(recvssl); PJDLOG_ASSERT(recvfd >= 0); pjdlog_debug(2, "%s: start %d -> %d", __func__, recvfd, sendfd); for (;;) { ssldone = SSL_read(recvssl, buf, sizeof(buf)); pjdlog_debug(2, "%s: SSL_read() returned %d", __func__, ssldone); if (ssl_check_error(recvssl, ssldone) == -1) break; todo = (size_t)ssldone; ptr = buf; do { tcpdone = send(sendfd, ptr, todo, MSG_NOSIGNAL); pjdlog_debug(2, "%s: send() returned %zd", __func__, tcpdone); if (tcpdone == 0) { pjdlog_debug(1, "Connection terminated."); exit(0); } else if (tcpdone == -1) { if (errno == EINTR || errno == ENOBUFS) continue; if (errno == EAGAIN) { (void)wait_for_fd(sendfd, -1); continue; } pjdlog_exit(EX_TEMPFAIL, "send() failed"); } todo -= tcpdone; ptr += tcpdone; } while (todo > 0); } pjdlog_debug(2, "%s: done %d -> %d", __func__, recvfd, sendfd); } static void tls_loop(int sockfd, SSL *tcpssl) { fd_set fds; int maxfd, tcpfd; tcpfd = SSL_get_fd(tcpssl); PJDLOG_ASSERT(tcpfd >= 0); for (;;) { FD_ZERO(&fds); FD_SET(sockfd, &fds); FD_SET(tcpfd, &fds); maxfd = MAX(sockfd, tcpfd); PJDLOG_ASSERT(maxfd + 1 <= (int)FD_SETSIZE); if (select(maxfd + 1, &fds, NULL, NULL, NULL) == -1) { if (errno == EINTR) continue; pjdlog_exit(EX_TEMPFAIL, "select() failed"); } if (FD_ISSET(sockfd, &fds)) tcp_recv_ssl_send(sockfd, tcpssl); if (FD_ISSET(tcpfd, &fds)) ssl_recv_tcp_send(tcpssl, sockfd); } } static void tls_certificate_verify(SSL *ssl, const char *fingerprint) { unsigned char md[EVP_MAX_MD_SIZE]; char mdstr[sizeof("SHA256=") - 1 + EVP_MAX_MD_SIZE * 3]; char *mdstrp; unsigned int i, mdsize; X509 *cert; if (fingerprint[0] == '\0') { pjdlog_debug(1, "No fingerprint verification requested."); return; } cert = SSL_get_peer_certificate(ssl); if (cert == NULL) pjdlog_exitx(EX_TEMPFAIL, "No peer certificate received."); if (X509_digest(cert, EVP_sha256(), md, &mdsize) != 1) pjdlog_exitx(EX_TEMPFAIL, "X509_digest() failed."); PJDLOG_ASSERT(mdsize <= EVP_MAX_MD_SIZE); X509_free(cert); (void)strlcpy(mdstr, "SHA256=", sizeof(mdstr)); mdstrp = mdstr + strlen(mdstr); for (i = 0; i < mdsize; i++) { PJDLOG_VERIFY(mdstrp + 3 <= mdstr + sizeof(mdstr)); (void)sprintf(mdstrp, "%02hhX:", md[i]); mdstrp += 3; } /* Clear last colon. */ mdstrp[-1] = '\0'; if (strcasecmp(mdstr, fingerprint) != 0) { pjdlog_exitx(EX_NOPERM, "Finger print doesn't match. Received \"%s\", expected \"%s\"", mdstr, fingerprint); } } static void tls_exec_client(const char *user, int startfd, const char *srcaddr, const char *dstaddr, const char *fingerprint, const char *defport, int timeout, int debuglevel) { struct proto_conn *tcp; char *saddr, *daddr; SSL_CTX *sslctx; SSL *ssl; long ret; int sockfd, tcpfd; uint8_t connected; pjdlog_debug_set(debuglevel); pjdlog_prefix_set("[TLS sandbox] (client) "); #ifdef HAVE_SETPROCTITLE setproctitle("[TLS sandbox] (client) "); #endif proto_set("tcp:port", defport); sockfd = startfd; /* Change tls:// to tcp://. */ if (srcaddr == NULL) { saddr = NULL; } else { saddr = strdup(srcaddr); if (saddr == NULL) pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate memory."); bcopy("tcp://", saddr, 6); } daddr = strdup(dstaddr); if (daddr == NULL) pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate memory."); bcopy("tcp://", daddr, 6); /* Establish TCP connection. */ if (proto_connect(saddr, daddr, timeout, &tcp) == -1) exit(EX_TEMPFAIL); SSL_load_error_strings(); SSL_library_init(); /* * TODO: On FreeBSD we could move this below sandbox() once libc and * libcrypto use sysctl kern.arandom to obtain random data * instead of /dev/urandom and friends. */ sslctx = SSL_CTX_new(TLSv1_client_method()); if (sslctx == NULL) pjdlog_exitx(EX_TEMPFAIL, "SSL_CTX_new() failed."); if (sandbox(user, true, "proto_tls client: %s", dstaddr) != 0) pjdlog_exitx(EX_CONFIG, "Unable to sandbox TLS client."); pjdlog_debug(1, "Privileges successfully dropped."); SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); /* Load CA certs. */ /* TODO */ //SSL_CTX_load_verify_locations(sslctx, cacerts_file, NULL); ssl = SSL_new(sslctx); if (ssl == NULL) pjdlog_exitx(EX_TEMPFAIL, "SSL_new() failed."); tcpfd = proto_descriptor(tcp); block(tcpfd); if (SSL_set_fd(ssl, tcpfd) != 1) pjdlog_exitx(EX_TEMPFAIL, "SSL_set_fd() failed."); ret = SSL_connect(ssl); ssl_check_error(ssl, (int)ret); nonblock(sockfd); nonblock(tcpfd); tls_certificate_verify(ssl, fingerprint); /* * The following byte is send to make proto_connect_wait() to work. */ connected = 1; for (;;) { switch (send(sockfd, &connected, sizeof(connected), 0)) { case -1: if (errno == EINTR || errno == ENOBUFS) continue; if (errno == EAGAIN) { (void)wait_for_fd(sockfd, -1); continue; } pjdlog_exit(EX_TEMPFAIL, "send() failed"); case 0: pjdlog_debug(1, "Connection terminated."); exit(0); case 1: break; } break; } tls_loop(sockfd, ssl); } static void tls_call_exec_client(struct proto_conn *sock, const char *srcaddr, const char *dstaddr, int timeout) { char *timeoutstr, *startfdstr, *debugstr; int startfd; /* Declare that we are receiver. */ proto_recv(sock, NULL, 0); if (pjdlog_mode_get() == PJDLOG_MODE_STD) startfd = 3; else /* if (pjdlog_mode_get() == PJDLOG_MODE_SYSLOG) */ startfd = 0; if (proto_descriptor(sock) != startfd) { /* Move socketpair descriptor to descriptor number startfd. */ if (dup2(proto_descriptor(sock), startfd) == -1) pjdlog_exit(EX_OSERR, "dup2() failed"); proto_close(sock); } else { /* * The FD_CLOEXEC is cleared by dup2(2), so when we not * call it, we have to clear it by hand in case it is set. */ if (fcntl(startfd, F_SETFD, 0) == -1) pjdlog_exit(EX_OSERR, "fcntl() failed"); } closefrom(startfd + 1); if (asprintf(&startfdstr, "%d", startfd) == -1) pjdlog_exit(EX_TEMPFAIL, "asprintf() failed"); if (timeout == -1) timeout = TLS_DEFAULT_TIMEOUT; if (asprintf(&timeoutstr, "%d", timeout) == -1) pjdlog_exit(EX_TEMPFAIL, "asprintf() failed"); if (asprintf(&debugstr, "%d", pjdlog_debug_get()) == -1) pjdlog_exit(EX_TEMPFAIL, "asprintf() failed"); execl(proto_get("execpath"), proto_get("execpath"), "proto", "tls", proto_get("user"), "client", startfdstr, srcaddr == NULL ? "" : srcaddr, dstaddr, proto_get("tls:fingerprint"), proto_get("tcp:port"), timeoutstr, debugstr, NULL); pjdlog_exit(EX_SOFTWARE, "execl() failed"); } static int tls_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp) { struct tls_ctx *tlsctx; struct proto_conn *sock; pid_t pid; int error; PJDLOG_ASSERT(srcaddr == NULL || srcaddr[0] != '\0'); PJDLOG_ASSERT(dstaddr != NULL); PJDLOG_ASSERT(timeout >= -1); PJDLOG_ASSERT(ctxp != NULL); if (strncmp(dstaddr, "tls://", 6) != 0) return (-1); if (srcaddr != NULL && strncmp(srcaddr, "tls://", 6) != 0) return (-1); if (proto_connect(NULL, "socketpair://", -1, &sock) == -1) return (errno); #if 0 /* * We use rfork() with the following flags to disable SIGCHLD * delivery upon the sandbox process exit. */ pid = rfork(RFFDG | RFPROC | RFTSIGZMB | RFTSIGFLAGS(0)); #else /* * We don't use rfork() to be able to log information about sandbox * process exiting. */ pid = fork(); #endif switch (pid) { case -1: /* Failure. */ error = errno; proto_close(sock); return (error); case 0: /* Child. */ pjdlog_prefix_set("[TLS sandbox] (client) "); #ifdef HAVE_SETPROCTITLE setproctitle("[TLS sandbox] (client) "); #endif tls_call_exec_client(sock, srcaddr, dstaddr, timeout); /* NOTREACHED */ default: /* Parent. */ tlsctx = calloc(1, sizeof(*tlsctx)); if (tlsctx == NULL) { error = errno; proto_close(sock); (void)kill(pid, SIGKILL); return (error); } proto_send(sock, NULL, 0); tlsctx->tls_sock = sock; tlsctx->tls_tcp = NULL; tlsctx->tls_side = TLS_SIDE_CLIENT; tlsctx->tls_wait_called = false; tlsctx->tls_magic = TLS_CTX_MAGIC; if (timeout >= 0) { error = tls_connect_wait(tlsctx, timeout); if (error != 0) { (void)kill(pid, SIGKILL); tls_close(tlsctx); return (error); } } *ctxp = tlsctx; return (0); } } static int tls_connect_wait(void *ctx, int timeout) { struct tls_ctx *tlsctx = ctx; int error, sockfd; uint8_t connected; PJDLOG_ASSERT(tlsctx != NULL); PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_CLIENT); PJDLOG_ASSERT(tlsctx->tls_sock != NULL); PJDLOG_ASSERT(!tlsctx->tls_wait_called); PJDLOG_ASSERT(timeout >= 0); sockfd = proto_descriptor(tlsctx->tls_sock); error = wait_for_fd(sockfd, timeout); if (error != 0) return (error); for (;;) { switch (recv(sockfd, &connected, sizeof(connected), MSG_WAITALL)) { case -1: if (errno == EINTR || errno == ENOBUFS) continue; error = errno; break; case 0: pjdlog_debug(1, "Connection terminated."); error = ENOTCONN; break; case 1: tlsctx->tls_wait_called = true; break; } break; } return (error); } static int tls_server(const char *lstaddr, void **ctxp) { struct proto_conn *tcp; struct tls_ctx *tlsctx; char *laddr; int error; if (strncmp(lstaddr, "tls://", 6) != 0) return (-1); tlsctx = malloc(sizeof(*tlsctx)); if (tlsctx == NULL) { pjdlog_warning("Unable to allocate memory."); return (ENOMEM); } laddr = strdup(lstaddr); if (laddr == NULL) { free(tlsctx); pjdlog_warning("Unable to allocate memory."); return (ENOMEM); } bcopy("tcp://", laddr, 6); if (proto_server(laddr, &tcp) == -1) { error = errno; free(tlsctx); free(laddr); return (error); } free(laddr); tlsctx->tls_sock = NULL; tlsctx->tls_tcp = tcp; tlsctx->tls_side = TLS_SIDE_SERVER_LISTEN; tlsctx->tls_wait_called = true; tlsctx->tls_magic = TLS_CTX_MAGIC; *ctxp = tlsctx; return (0); } static void tls_exec_server(const char *user, int startfd, const char *privkey, const char *cert, int debuglevel) { SSL_CTX *sslctx; SSL *ssl; int sockfd, tcpfd, ret; pjdlog_debug_set(debuglevel); pjdlog_prefix_set("[TLS sandbox] (server) "); #ifdef HAVE_SETPROCTITLE setproctitle("[TLS sandbox] (server) "); #endif sockfd = startfd; tcpfd = startfd + 1; SSL_load_error_strings(); SSL_library_init(); sslctx = SSL_CTX_new(TLSv1_server_method()); if (sslctx == NULL) pjdlog_exitx(EX_TEMPFAIL, "SSL_CTX_new() failed."); SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); ssl = SSL_new(sslctx); if (ssl == NULL) pjdlog_exitx(EX_TEMPFAIL, "SSL_new() failed."); if (SSL_use_RSAPrivateKey_file(ssl, privkey, SSL_FILETYPE_PEM) != 1) { ssl_log_errors(); pjdlog_exitx(EX_CONFIG, "SSL_use_RSAPrivateKey_file(%s) failed.", privkey); } if (SSL_use_certificate_file(ssl, cert, SSL_FILETYPE_PEM) != 1) { ssl_log_errors(); pjdlog_exitx(EX_CONFIG, "SSL_use_certificate_file(%s) failed.", cert); } if (sandbox(user, true, "proto_tls server") != 0) pjdlog_exitx(EX_CONFIG, "Unable to sandbox TLS server."); pjdlog_debug(1, "Privileges successfully dropped."); nonblock(sockfd); nonblock(tcpfd); if (SSL_set_fd(ssl, tcpfd) != 1) pjdlog_exitx(EX_TEMPFAIL, "SSL_set_fd() failed."); ret = SSL_accept(ssl); ssl_check_error(ssl, ret); tls_loop(sockfd, ssl); } static void tls_call_exec_server(struct proto_conn *sock, struct proto_conn *tcp) { int startfd, sockfd, tcpfd, safefd; char *startfdstr, *debugstr; if (pjdlog_mode_get() == PJDLOG_MODE_STD) startfd = 3; else /* if (pjdlog_mode_get() == PJDLOG_MODE_SYSLOG) */ startfd = 0; /* Declare that we are receiver. */ proto_send(sock, NULL, 0); sockfd = proto_descriptor(sock); tcpfd = proto_descriptor(tcp); safefd = MAX(sockfd, tcpfd); safefd = MAX(safefd, startfd); safefd++; /* Move sockfd and tcpfd to safe numbers first. */ if (dup2(sockfd, safefd) == -1) pjdlog_exit(EX_OSERR, "dup2() failed"); proto_close(sock); sockfd = safefd; if (dup2(tcpfd, safefd + 1) == -1) pjdlog_exit(EX_OSERR, "dup2() failed"); proto_close(tcp); tcpfd = safefd + 1; /* Move socketpair descriptor to descriptor number startfd. */ if (dup2(sockfd, startfd) == -1) pjdlog_exit(EX_OSERR, "dup2() failed"); (void)close(sockfd); /* Move tcp descriptor to descriptor number startfd + 1. */ if (dup2(tcpfd, startfd + 1) == -1) pjdlog_exit(EX_OSERR, "dup2() failed"); (void)close(tcpfd); closefrom(startfd + 2); /* * Even if FD_CLOEXEC was set on descriptors before dup2(), it should * have been cleared on dup2(), but better be safe than sorry. */ if (fcntl(startfd, F_SETFD, 0) == -1) pjdlog_exit(EX_OSERR, "fcntl() failed"); if (fcntl(startfd + 1, F_SETFD, 0) == -1) pjdlog_exit(EX_OSERR, "fcntl() failed"); if (asprintf(&startfdstr, "%d", startfd) == -1) pjdlog_exit(EX_TEMPFAIL, "asprintf() failed"); if (asprintf(&debugstr, "%d", pjdlog_debug_get()) == -1) pjdlog_exit(EX_TEMPFAIL, "asprintf() failed"); execl(proto_get("execpath"), proto_get("execpath"), "proto", "tls", proto_get("user"), "server", startfdstr, proto_get("tls:keyfile"), proto_get("tls:certfile"), debugstr, NULL); pjdlog_exit(EX_SOFTWARE, "execl() failed"); } static int tls_accept(void *ctx, void **newctxp) { struct tls_ctx *tlsctx = ctx; struct tls_ctx *newtlsctx; struct proto_conn *sock, *tcp; pid_t pid; int error; PJDLOG_ASSERT(tlsctx != NULL); PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_SERVER_LISTEN); if (proto_connect(NULL, "socketpair://", -1, &sock) == -1) return (errno); /* Accept TCP connection. */ if (proto_accept(tlsctx->tls_tcp, &tcp) == -1) { error = errno; proto_close(sock); return (error); } pid = fork(); switch (pid) { case -1: /* Failure. */ error = errno; proto_close(sock); return (error); case 0: /* Child. */ pjdlog_prefix_set("[TLS sandbox] (server) "); #ifdef HAVE_SETPROCTITLE setproctitle("[TLS sandbox] (server) "); #endif /* Close listen socket. */ proto_close(tlsctx->tls_tcp); tls_call_exec_server(sock, tcp); /* NOTREACHED */ PJDLOG_ABORT("Unreachable."); default: /* Parent. */ newtlsctx = calloc(1, sizeof(*tlsctx)); if (newtlsctx == NULL) { error = errno; proto_close(sock); proto_close(tcp); (void)kill(pid, SIGKILL); return (error); } proto_local_address(tcp, newtlsctx->tls_laddr, sizeof(newtlsctx->tls_laddr)); PJDLOG_ASSERT(strncmp(newtlsctx->tls_laddr, "tcp://", 6) == 0); bcopy("tls://", newtlsctx->tls_laddr, 6); *strrchr(newtlsctx->tls_laddr, ':') = '\0'; proto_remote_address(tcp, newtlsctx->tls_raddr, sizeof(newtlsctx->tls_raddr)); PJDLOG_ASSERT(strncmp(newtlsctx->tls_raddr, "tcp://", 6) == 0); bcopy("tls://", newtlsctx->tls_raddr, 6); *strrchr(newtlsctx->tls_raddr, ':') = '\0'; proto_close(tcp); proto_recv(sock, NULL, 0); newtlsctx->tls_sock = sock; newtlsctx->tls_tcp = NULL; newtlsctx->tls_wait_called = true; newtlsctx->tls_side = TLS_SIDE_SERVER_WORK; newtlsctx->tls_magic = TLS_CTX_MAGIC; *newctxp = newtlsctx; return (0); } } static int tls_wrap(int fd, bool client, void **ctxp) { struct tls_ctx *tlsctx; struct proto_conn *sock; int error; tlsctx = calloc(1, sizeof(*tlsctx)); if (tlsctx == NULL) return (errno); if (proto_wrap("socketpair", client, fd, &sock) == -1) { error = errno; free(tlsctx); return (error); } tlsctx->tls_sock = sock; tlsctx->tls_tcp = NULL; tlsctx->tls_wait_called = (client ? false : true); tlsctx->tls_side = (client ? TLS_SIDE_CLIENT : TLS_SIDE_SERVER_WORK); tlsctx->tls_magic = TLS_CTX_MAGIC; *ctxp = tlsctx; return (0); } static int tls_send(void *ctx, const unsigned char *data, size_t size, int fd) { struct tls_ctx *tlsctx = ctx; PJDLOG_ASSERT(tlsctx != NULL); PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_CLIENT || tlsctx->tls_side == TLS_SIDE_SERVER_WORK); PJDLOG_ASSERT(tlsctx->tls_sock != NULL); PJDLOG_ASSERT(tlsctx->tls_wait_called); PJDLOG_ASSERT(fd == -1); if (proto_send(tlsctx->tls_sock, data, size) == -1) return (errno); return (0); } static int tls_recv(void *ctx, unsigned char *data, size_t size, int *fdp) { struct tls_ctx *tlsctx = ctx; PJDLOG_ASSERT(tlsctx != NULL); PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_CLIENT || tlsctx->tls_side == TLS_SIDE_SERVER_WORK); PJDLOG_ASSERT(tlsctx->tls_sock != NULL); PJDLOG_ASSERT(tlsctx->tls_wait_called); PJDLOG_ASSERT(fdp == NULL); if (proto_recv(tlsctx->tls_sock, data, size) == -1) return (errno); return (0); } static int tls_descriptor(const void *ctx) { const struct tls_ctx *tlsctx = ctx; PJDLOG_ASSERT(tlsctx != NULL); PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); switch (tlsctx->tls_side) { case TLS_SIDE_CLIENT: case TLS_SIDE_SERVER_WORK: PJDLOG_ASSERT(tlsctx->tls_sock != NULL); return (proto_descriptor(tlsctx->tls_sock)); case TLS_SIDE_SERVER_LISTEN: PJDLOG_ASSERT(tlsctx->tls_tcp != NULL); return (proto_descriptor(tlsctx->tls_tcp)); default: PJDLOG_ABORT("Invalid side (%d).", tlsctx->tls_side); } } static bool tcp_address_match(const void *ctx, const char *addr) { const struct tls_ctx *tlsctx = ctx; PJDLOG_ASSERT(tlsctx != NULL); PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); return (strcmp(tlsctx->tls_raddr, addr) == 0); } static void tls_local_address(const void *ctx, char *addr, size_t size) { const struct tls_ctx *tlsctx = ctx; PJDLOG_ASSERT(tlsctx != NULL); PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); PJDLOG_ASSERT(tlsctx->tls_wait_called); switch (tlsctx->tls_side) { case TLS_SIDE_CLIENT: PJDLOG_ASSERT(tlsctx->tls_sock != NULL); PJDLOG_VERIFY(strlcpy(addr, "tls://N/A", size) < size); break; case TLS_SIDE_SERVER_WORK: PJDLOG_ASSERT(tlsctx->tls_sock != NULL); PJDLOG_VERIFY(strlcpy(addr, tlsctx->tls_laddr, size) < size); break; case TLS_SIDE_SERVER_LISTEN: PJDLOG_ASSERT(tlsctx->tls_tcp != NULL); proto_local_address(tlsctx->tls_tcp, addr, size); PJDLOG_ASSERT(strncmp(addr, "tcp://", 6) == 0); /* Replace tcp:// prefix with tls:// */ bcopy("tls://", addr, 6); break; default: PJDLOG_ABORT("Invalid side (%d).", tlsctx->tls_side); } } static void tls_remote_address(const void *ctx, char *addr, size_t size) { const struct tls_ctx *tlsctx = ctx; PJDLOG_ASSERT(tlsctx != NULL); PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); PJDLOG_ASSERT(tlsctx->tls_wait_called); switch (tlsctx->tls_side) { case TLS_SIDE_CLIENT: PJDLOG_ASSERT(tlsctx->tls_sock != NULL); PJDLOG_VERIFY(strlcpy(addr, "tls://N/A", size) < size); break; case TLS_SIDE_SERVER_WORK: PJDLOG_ASSERT(tlsctx->tls_sock != NULL); PJDLOG_VERIFY(strlcpy(addr, tlsctx->tls_raddr, size) < size); break; case TLS_SIDE_SERVER_LISTEN: PJDLOG_ASSERT(tlsctx->tls_tcp != NULL); proto_remote_address(tlsctx->tls_tcp, addr, size); PJDLOG_ASSERT(strncmp(addr, "tcp://", 6) == 0); /* Replace tcp:// prefix with tls:// */ bcopy("tls://", addr, 6); break; default: PJDLOG_ABORT("Invalid side (%d).", tlsctx->tls_side); } } static void tls_close(void *ctx) { struct tls_ctx *tlsctx = ctx; PJDLOG_ASSERT(tlsctx != NULL); PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); if (tlsctx->tls_sock != NULL) { proto_close(tlsctx->tls_sock); tlsctx->tls_sock = NULL; } if (tlsctx->tls_tcp != NULL) { proto_close(tlsctx->tls_tcp); tlsctx->tls_tcp = NULL; } tlsctx->tls_side = 0; tlsctx->tls_magic = 0; free(tlsctx); } static int tls_exec(int argc, char *argv[]) { PJDLOG_ASSERT(argc > 3); PJDLOG_ASSERT(strcmp(argv[0], "tls") == 0); pjdlog_init(atoi(argv[3]) == 0 ? PJDLOG_MODE_SYSLOG : PJDLOG_MODE_STD); if (strcmp(argv[2], "client") == 0) { if (argc != 10) return (EINVAL); tls_exec_client(argv[1], atoi(argv[3]), argv[4][0] == '\0' ? NULL : argv[4], argv[5], argv[6], argv[7], atoi(argv[8]), atoi(argv[9])); } else if (strcmp(argv[2], "server") == 0) { if (argc != 7) return (EINVAL); tls_exec_server(argv[1], atoi(argv[3]), argv[4], argv[5], atoi(argv[6])); } return (EINVAL); } static struct proto tls_proto = { .prt_name = "tls", .prt_connect = tls_connect, .prt_connect_wait = tls_connect_wait, .prt_server = tls_server, .prt_accept = tls_accept, .prt_wrap = tls_wrap, .prt_send = tls_send, .prt_recv = tls_recv, .prt_descriptor = tls_descriptor, .prt_address_match = tcp_address_match, .prt_local_address = tls_local_address, .prt_remote_address = tls_remote_address, .prt_close = tls_close, .prt_exec = tls_exec }; static __constructor void tls_ctor(void) { proto_register(&tls_proto, false); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_uds.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_uds.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/proto_uds.c (revision 292449) @@ -1,362 +1,360 @@ /*- * Copyright (c) 2009-2010 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/proto_uds.c#2 $ */ /* UDS - UNIX Domain Socket */ #include #include #include #include #include #include #include #include #include #include #ifndef HAVE_STRLCPY #include #endif #include "pjdlog.h" #include "proto_impl.h" #define UDS_CTX_MAGIC 0xd541c struct uds_ctx { int uc_magic; struct sockaddr_un uc_sun; int uc_fd; int uc_side; #define UDS_SIDE_CLIENT 0 #define UDS_SIDE_SERVER_LISTEN 1 #define UDS_SIDE_SERVER_WORK 2 pid_t uc_owner; }; static void uds_close(void *ctx); static int uds_addr(const char *addr, struct sockaddr_un *sunp) { if (addr == NULL) return (-1); if (strncasecmp(addr, "uds://", 6) == 0) addr += 6; else if (strncasecmp(addr, "unix://", 7) == 0) addr += 7; else if (addr[0] == '/' && /* If it starts from /... */ strstr(addr, "://") == NULL)/* ...and there is no prefix... */ ; /* ...we assume its us. */ else return (-1); sunp->sun_family = AF_UNIX; if (strlcpy(sunp->sun_path, addr, sizeof(sunp->sun_path)) >= sizeof(sunp->sun_path)) { return (ENAMETOOLONG); } #ifdef HAVE_SOCKADDR_STORAGE_SS_LEN sunp->sun_len = SUN_LEN(sunp); #endif return (0); } static int uds_common_setup(const char *addr, int side, struct uds_ctx **uctxp) { struct uds_ctx *uctx; int error; uctx = malloc(sizeof(*uctx)); if (uctx == NULL) return (errno); /* Parse given address. */ error = uds_addr(addr, &uctx->uc_sun); if (error != 0) { free(uctx); return (error); } uctx->uc_fd = socket(AF_UNIX, SOCK_STREAM, 0); if (uctx->uc_fd == -1) { error = errno; free(uctx); return (error); } uctx->uc_side = side; uctx->uc_owner = 0; uctx->uc_magic = UDS_CTX_MAGIC; *uctxp = uctx; return (0); } static int uds_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp) { struct uds_ctx *uctx; int error; PJDLOG_ASSERT(dstaddr != NULL); PJDLOG_ASSERT(timeout >= -1); error = uds_common_setup(dstaddr, UDS_SIDE_CLIENT, &uctx); if (error != 0) return (error); PJDLOG_ASSERT(srcaddr == NULL); if (connect(uctx->uc_fd, (struct sockaddr *)&uctx->uc_sun, sizeof(uctx->uc_sun)) == -1) { error = errno; uds_close(uctx); return (error); } *ctxp = uctx; return (0); } static int uds_connect_wait(void *ctx, int timeout) { struct uds_ctx *uctx = ctx; PJDLOG_ASSERT(uctx != NULL); PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC); PJDLOG_ASSERT(uctx->uc_side == UDS_SIDE_CLIENT); PJDLOG_ASSERT(uctx->uc_fd >= 0); PJDLOG_ASSERT(timeout >= 0); return (0); } static int uds_server(const char *addr, void **ctxp) { struct uds_ctx *uctx; int error; error = uds_common_setup(addr, UDS_SIDE_SERVER_LISTEN, &uctx); if (error != 0) return (error); (void)unlink(uctx->uc_sun.sun_path); if (bind(uctx->uc_fd, (struct sockaddr *)&uctx->uc_sun, sizeof(uctx->uc_sun)) == -1) { error = errno; uds_close(uctx); return (error); } uctx->uc_owner = getpid(); if (listen(uctx->uc_fd, 8) == -1) { error = errno; uds_close(uctx); return (error); } *ctxp = uctx; return (0); } static int uds_accept(void *ctx, void **newctxp) { struct uds_ctx *uctx = ctx; struct uds_ctx *newuctx; socklen_t fromlen; int error; PJDLOG_ASSERT(uctx != NULL); PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC); PJDLOG_ASSERT(uctx->uc_side == UDS_SIDE_SERVER_LISTEN); PJDLOG_ASSERT(uctx->uc_fd >= 0); newuctx = malloc(sizeof(*newuctx)); if (newuctx == NULL) return (errno); fromlen = sizeof(newuctx->uc_sun); newuctx->uc_fd = accept(uctx->uc_fd, (struct sockaddr *)&newuctx->uc_sun, &fromlen); if (newuctx->uc_fd < 0) { error = errno; free(newuctx); return (error); } newuctx->uc_side = UDS_SIDE_SERVER_WORK; newuctx->uc_magic = UDS_CTX_MAGIC; *newctxp = newuctx; return (0); } static int uds_send(void *ctx, const unsigned char *data, size_t size, int fd) { struct uds_ctx *uctx = ctx; PJDLOG_ASSERT(uctx != NULL); PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC); PJDLOG_ASSERT(uctx->uc_fd >= 0); return (proto_common_send(uctx->uc_fd, data, size, fd)); } static int uds_recv(void *ctx, unsigned char *data, size_t size, int *fdp) { struct uds_ctx *uctx = ctx; PJDLOG_ASSERT(uctx != NULL); PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC); PJDLOG_ASSERT(uctx->uc_fd >= 0); return (proto_common_recv(uctx->uc_fd, data, size, fdp)); } static int uds_descriptor(const void *ctx) { const struct uds_ctx *uctx = ctx; PJDLOG_ASSERT(uctx != NULL); PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC); return (uctx->uc_fd); } static void uds_local_address(const void *ctx, char *addr, size_t size) { const struct uds_ctx *uctx = ctx; struct sockaddr_un sun; socklen_t sunlen; PJDLOG_ASSERT(uctx != NULL); PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC); PJDLOG_ASSERT(addr != NULL); sunlen = sizeof(sun); if (getsockname(uctx->uc_fd, (struct sockaddr *)&sun, &sunlen) < 0) { PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size); return; } PJDLOG_ASSERT(sun.sun_family == AF_UNIX); if (sun.sun_path[0] == '\0') { PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size); return; } PJDLOG_VERIFY(snprintf(addr, size, "uds://%s", sun.sun_path) < (ssize_t)size); } static void uds_remote_address(const void *ctx, char *addr, size_t size) { const struct uds_ctx *uctx = ctx; struct sockaddr_un sun; socklen_t sunlen; PJDLOG_ASSERT(uctx != NULL); PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC); PJDLOG_ASSERT(addr != NULL); sunlen = sizeof(sun); if (getpeername(uctx->uc_fd, (struct sockaddr *)&sun, &sunlen) < 0) { PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size); return; } PJDLOG_ASSERT(sun.sun_family == AF_UNIX); if (sun.sun_path[0] == '\0') { PJDLOG_VERIFY(strlcpy(addr, "N/A", size) < size); return; } snprintf(addr, size, "uds://%s", sun.sun_path); } static void uds_close(void *ctx) { struct uds_ctx *uctx = ctx; PJDLOG_ASSERT(uctx != NULL); PJDLOG_ASSERT(uctx->uc_magic == UDS_CTX_MAGIC); if (uctx->uc_fd >= 0) close(uctx->uc_fd); /* * Unlink the socket only if we are the owner and this is descriptor * we listen on. */ if (uctx->uc_side == UDS_SIDE_SERVER_LISTEN && uctx->uc_owner == getpid()) { PJDLOG_ASSERT(uctx->uc_sun.sun_path[0] != '\0'); if (unlink(uctx->uc_sun.sun_path) == -1) { pjdlog_errno(LOG_WARNING, "Unable to unlink socket file %s", uctx->uc_sun.sun_path); } } uctx->uc_owner = 0; uctx->uc_magic = 0; free(uctx); } static struct proto uds_proto = { .prt_name = "uds", .prt_connect = uds_connect, .prt_connect_wait = uds_connect_wait, .prt_server = uds_server, .prt_accept = uds_accept, .prt_send = uds_send, .prt_recv = uds_recv, .prt_descriptor = uds_descriptor, .prt_local_address = uds_local_address, .prt_remote_address = uds_remote_address, .prt_close = uds_close }; static __constructor void uds_ctor(void) { proto_register(&uds_proto, false); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/receiver.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/receiver.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/receiver.c (revision 292449) @@ -1,714 +1,712 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/receiver.c#3 $ */ #include #include #if defined(HAVE_SYS_ENDIAN_H) && defined(HAVE_BSWAP) #include #else /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */ #ifdef HAVE_MACHINE_ENDIAN_H #include #else /* !HAVE_MACHINE_ENDIAN_H */ #ifdef HAVE_ENDIAN_H #include #else /* !HAVE_ENDIAN_H */ #error "No supported endian.h" #endif /* !HAVE_ENDIAN_H */ #endif /* !HAVE_MACHINE_ENDIAN_H */ #include #endif /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */ #include #include #include #include #include #include #ifdef HAVE_LIBUTIL_H #include #endif #include #include #include #include #include #include #include #include #ifndef HAVE_STRLCPY #include #endif #ifndef HAVE_FSTATAT #include "fstatat.h" #endif #ifndef HAVE_OPENAT #include "openat.h" #endif #ifndef HAVE_RENAMEAT #include "renameat.h" #endif #include "auditdistd.h" #include "pjdlog.h" #include "proto.h" #include "sandbox.h" #include "subr.h" #include "synch.h" #include "trail.h" static struct adist_config *adcfg; static struct adist_host *adhost; static TAILQ_HEAD(, adreq) adist_free_list; static pthread_mutex_t adist_free_list_lock; static pthread_cond_t adist_free_list_cond; static TAILQ_HEAD(, adreq) adist_disk_list; static pthread_mutex_t adist_disk_list_lock; static pthread_cond_t adist_disk_list_cond; static TAILQ_HEAD(, adreq) adist_send_list; static pthread_mutex_t adist_send_list_lock; static pthread_cond_t adist_send_list_cond; static void adreq_clear(struct adreq *adreq) { adreq->adr_error = -1; adreq->adr_byteorder = ADIST_BYTEORDER_UNDEFINED; adreq->adr_cmd = ADIST_CMD_UNDEFINED; adreq->adr_seq = 0; adreq->adr_datasize = 0; } static void init_environment(void) { struct adreq *adreq; unsigned int ii; TAILQ_INIT(&adist_free_list); mtx_init(&adist_free_list_lock); cv_init(&adist_free_list_cond); TAILQ_INIT(&adist_disk_list); mtx_init(&adist_disk_list_lock); cv_init(&adist_disk_list_cond); TAILQ_INIT(&adist_send_list); mtx_init(&adist_send_list_lock); cv_init(&adist_send_list_cond); for (ii = 0; ii < ADIST_QUEUE_SIZE; ii++) { adreq = malloc(sizeof(*adreq) + ADIST_BUF_SIZE); if (adreq == NULL) { pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate %zu bytes of memory for adreq object.", sizeof(*adreq) + ADIST_BUF_SIZE); } adreq_clear(adreq); TAILQ_INSERT_TAIL(&adist_free_list, adreq, adr_next); } } static void adreq_decode_and_validate_header(struct adreq *adreq) { /* Byte-swap only is the sender is using different byte order. */ if (adreq->adr_byteorder != ADIST_BYTEORDER) { adreq->adr_byteorder = ADIST_BYTEORDER; adreq->adr_seq = bswap64(adreq->adr_seq); adreq->adr_datasize = bswap32(adreq->adr_datasize); } /* Validate packet header. */ if (adreq->adr_datasize > ADIST_BUF_SIZE) { pjdlog_exitx(EX_PROTOCOL, "Invalid datasize received (%ju).", (uintmax_t)adreq->adr_datasize); } switch (adreq->adr_cmd) { case ADIST_CMD_OPEN: case ADIST_CMD_APPEND: case ADIST_CMD_CLOSE: if (adreq->adr_datasize == 0) { pjdlog_exitx(EX_PROTOCOL, "Invalid datasize received (%ju).", (uintmax_t)adreq->adr_datasize); } break; case ADIST_CMD_KEEPALIVE: case ADIST_CMD_ERROR: if (adreq->adr_datasize > 0) { pjdlog_exitx(EX_PROTOCOL, "Invalid datasize received (%ju).", (uintmax_t)adreq->adr_datasize); } break; default: pjdlog_exitx(EX_PROTOCOL, "Invalid command received (%hhu).", adreq->adr_cmd); } } static void adreq_validate_data(const struct adreq *adreq) { /* Validate packet data. */ switch (adreq->adr_cmd) { case ADIST_CMD_OPEN: case ADIST_CMD_CLOSE: /* * File name must end up with '\0' and there must be no '\0' * in the middle. */ if (adreq->adr_data[adreq->adr_datasize - 1] != '\0' || strchr(adreq->adr_data, '\0') != (const char *)adreq->adr_data + adreq->adr_datasize - 1) { pjdlog_exitx(EX_PROTOCOL, "Invalid file name received."); } break; } } /* * Thread receives requests from the sender. */ static void * recv_thread(void *arg __unused) { struct adreq *adreq; for (;;) { pjdlog_debug(3, "recv: Taking free request."); QUEUE_TAKE(adreq, &adist_free_list, 0); pjdlog_debug(3, "recv: (%p) Got request.", adreq); if (proto_recv(adhost->adh_remote, &adreq->adr_packet, sizeof(adreq->adr_packet)) == -1) { pjdlog_exit(EX_TEMPFAIL, "Unable to receive request header"); } adreq_decode_and_validate_header(adreq); switch (adreq->adr_cmd) { case ADIST_CMD_KEEPALIVE: adreq->adr_error = 0; adreq_log(LOG_DEBUG, 2, -1, adreq, "recv: (%p) Got request header: ", adreq); pjdlog_debug(3, "recv: (%p) Moving request to the send queue.", adreq); QUEUE_INSERT(adreq, &adist_send_list); continue; case ADIST_CMD_ERROR: pjdlog_error("An error occured on the sender while reading \"%s/%s\".", adhost->adh_directory, adhost->adh_trail_name); adreq_log(LOG_DEBUG, 2, ADIST_ERROR_READ, adreq, "recv: (%p) Got request header: ", adreq); pjdlog_debug(3, "recv: (%p) Moving request to the send queue.", adreq); QUEUE_INSERT(adreq, &adist_disk_list); continue; case ADIST_CMD_OPEN: case ADIST_CMD_APPEND: case ADIST_CMD_CLOSE: if (proto_recv(adhost->adh_remote, adreq->adr_data, adreq->adr_datasize) == -1) { pjdlog_exit(EX_TEMPFAIL, "Unable to receive request data"); } adreq_validate_data(adreq); adreq_log(LOG_DEBUG, 2, -1, adreq, "recv: (%p) Got request header: ", adreq); pjdlog_debug(3, "recv: (%p) Moving request to the disk queue.", adreq); QUEUE_INSERT(adreq, &adist_disk_list); break; default: PJDLOG_ABORT("Invalid condition."); } } /* NOTREACHED */ return (NULL); } /* * Function that opens trail file requested by the sender. * If the file already exist, it has to be the most recent file and it can * only be open for append. * If the file doesn't already exist, it has to be "older" than all existing * files. */ static int receiver_open(const char *filename) { int fd; /* * Previous file should be closed by now. Sending OPEN request without * sending CLOSE for the previous file is a sender bug. */ if (adhost->adh_trail_fd != -1) { pjdlog_error("Sender requested opening file \"%s\" without first closing \"%s\".", filename, adhost->adh_trail_name); return (ADIST_ERROR_WRONG_ORDER); } if (!trail_validate_name(filename, NULL)) { pjdlog_error("Sender wants to open file \"%s\", which has invalid name.", filename); return (ADIST_ERROR_INVALID_NAME); } switch (trail_name_compare(filename, adhost->adh_trail_name)) { case TRAIL_RENAMED: if (!trail_is_not_terminated(adhost->adh_trail_name)) { pjdlog_error("Terminated trail \"%s/%s\" was unterminated on the sender as \"%s/%s\"?", adhost->adh_directory, adhost->adh_trail_name, adhost->adh_directory, filename); return (ADIST_ERROR_INVALID_NAME); } if (renameat(adhost->adh_trail_dirfd, adhost->adh_trail_name, adhost->adh_trail_dirfd, filename) == -1) { pjdlog_errno(LOG_ERR, "Unable to rename file \"%s/%s\" to \"%s/%s\"", adhost->adh_directory, adhost->adh_trail_name, adhost->adh_directory, filename); PJDLOG_ASSERT(errno > 0); return (ADIST_ERROR_RENAME); } pjdlog_debug(1, "Renamed file \"%s/%s\" to \"%s/%s\".", adhost->adh_directory, adhost->adh_trail_name, adhost->adh_directory, filename); /* FALLTHROUGH */ case TRAIL_IDENTICAL: /* Opening existing file. */ fd = openat(adhost->adh_trail_dirfd, filename, O_WRONLY | O_APPEND | O_NOFOLLOW); if (fd == -1) { pjdlog_errno(LOG_ERR, "Unable to open file \"%s/%s\" for append", adhost->adh_directory, filename); PJDLOG_ASSERT(errno > 0); return (ADIST_ERROR_OPEN); } pjdlog_debug(1, "Opened file \"%s/%s\".", adhost->adh_directory, filename); break; case TRAIL_NEWER: /* Opening new file. */ fd = openat(adhost->adh_trail_dirfd, filename, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); if (fd == -1) { pjdlog_errno(LOG_ERR, "Unable to create file \"%s/%s\"", adhost->adh_directory, filename); PJDLOG_ASSERT(errno > 0); return (ADIST_ERROR_CREATE); } pjdlog_debug(1, "Created file \"%s/%s\".", adhost->adh_directory, filename); break; case TRAIL_OLDER: /* Trying to open old file. */ pjdlog_error("Sender wants to open an old file \"%s\".", filename); return (ADIST_ERROR_OPEN_OLD); default: PJDLOG_ABORT("Unknown return value from trail_name_compare()."); } PJDLOG_VERIFY(strlcpy(adhost->adh_trail_name, filename, sizeof(adhost->adh_trail_name)) < sizeof(adhost->adh_trail_name)); adhost->adh_trail_fd = fd; return (0); } /* * Function appends data to the trail file that is currently open. */ static int receiver_append(const unsigned char *data, size_t size) { ssize_t done; size_t osize; /* We should have opened trail file. */ if (adhost->adh_trail_fd == -1) { pjdlog_error("Sender requested append without first opening file."); return (ADIST_ERROR_WRONG_ORDER); } osize = size; while (size > 0) { done = write(adhost->adh_trail_fd, data, size); if (done == -1) { if (errno == EINTR) continue; pjdlog_errno(LOG_ERR, "Write to \"%s/%s\" failed", adhost->adh_directory, adhost->adh_trail_name); PJDLOG_ASSERT(errno > 0); return (ADIST_ERROR_WRITE); } pjdlog_debug(3, "Wrote %zd bytes into \"%s/%s\".", done, adhost->adh_directory, adhost->adh_trail_name); size -= done; } pjdlog_debug(2, "Appended %zu bytes to file \"%s/%s\".", osize, adhost->adh_directory, adhost->adh_trail_name); return (0); } static int receiver_close(const char *filename) { /* We should have opened trail file. */ if (adhost->adh_trail_fd == -1) { pjdlog_error("Sender requested closing file without first opening it."); return (ADIST_ERROR_WRONG_ORDER); } /* Validate if we can do the rename. */ if (!trail_validate_name(adhost->adh_trail_name, filename)) { pjdlog_error("Sender wants to close file \"%s\" using name \"%s\".", adhost->adh_trail_name, filename); return (ADIST_ERROR_INVALID_NAME); } PJDLOG_VERIFY(close(adhost->adh_trail_fd) == 0); adhost->adh_trail_fd = -1; pjdlog_debug(1, "Closed file \"%s/%s\".", adhost->adh_directory, adhost->adh_trail_name); if (strcmp(adhost->adh_trail_name, filename) == 0) { /* File name didn't change, we are done here. */ return (0); } if (renameat(adhost->adh_trail_dirfd, adhost->adh_trail_name, adhost->adh_trail_dirfd, filename) == -1) { pjdlog_errno(LOG_ERR, "Unable to rename \"%s\" to \"%s\"", adhost->adh_trail_name, filename); PJDLOG_ASSERT(errno > 0); return (ADIST_ERROR_RENAME); } pjdlog_debug(1, "Renamed file \"%s/%s\" to \"%s/%s\".", adhost->adh_directory, adhost->adh_trail_name, adhost->adh_directory, filename); PJDLOG_VERIFY(strlcpy(adhost->adh_trail_name, filename, sizeof(adhost->adh_trail_name)) < sizeof(adhost->adh_trail_name)); return (0); } static int receiver_error(void) { /* We should have opened trail file. */ if (adhost->adh_trail_fd == -1) { pjdlog_error("Sender send read error, but file is not open."); return (ADIST_ERROR_WRONG_ORDER); } PJDLOG_VERIFY(close(adhost->adh_trail_fd) == 0); adhost->adh_trail_fd = -1; pjdlog_debug(1, "Closed file \"%s/%s\".", adhost->adh_directory, adhost->adh_trail_name); return (0); } static void * disk_thread(void *arg __unused) { struct adreq *adreq; for (;;) { pjdlog_debug(3, "disk: Taking request."); QUEUE_TAKE(adreq, &adist_disk_list, 0); adreq_log(LOG_DEBUG, 3, -1, adreq, "disk: (%p) Got request: ", adreq); /* Handle the actual request. */ switch (adreq->adr_cmd) { case ADIST_CMD_OPEN: adreq->adr_error = receiver_open(adreq->adr_data); break; case ADIST_CMD_APPEND: adreq->adr_error = receiver_append(adreq->adr_data, adreq->adr_datasize); break; case ADIST_CMD_CLOSE: adreq->adr_error = receiver_close(adreq->adr_data); break; case ADIST_CMD_ERROR: adreq->adr_error = receiver_error(); break; default: PJDLOG_ABORT("Unexpected command (cmd=%hhu).", adreq->adr_cmd); } if (adreq->adr_error != 0) { adreq_log(LOG_ERR, 0, adreq->adr_error, adreq, "Request failed: "); } pjdlog_debug(3, "disk: (%p) Moving request to the send queue.", adreq); QUEUE_INSERT(adreq, &adist_send_list); } /* NOTREACHED */ return (NULL); } /* * Thread sends requests back to primary node. */ static void * send_thread(void *arg __unused) { struct adreq *adreq; struct adrep adrep; for (;;) { pjdlog_debug(3, "send: Taking request."); QUEUE_TAKE(adreq, &adist_send_list, 0); adreq_log(LOG_DEBUG, 3, -1, adreq, "send: (%p) Got request: ", adreq); adrep.adrp_byteorder = ADIST_BYTEORDER; adrep.adrp_seq = adreq->adr_seq; adrep.adrp_error = adreq->adr_error; if (proto_send(adhost->adh_remote, &adrep, sizeof(adrep)) == -1) { pjdlog_exit(EX_TEMPFAIL, "Unable to send reply"); } pjdlog_debug(3, "send: (%p) Moving request to the free queue.", adreq); adreq_clear(adreq); QUEUE_INSERT(adreq, &adist_free_list); } /* NOTREACHED */ return (NULL); } static void receiver_directory_create(void) { struct passwd *pw; /* * According to getpwnam(3) we have to clear errno before calling the * function to be able to distinguish between an error and missing * entry (with is not treated as error by getpwnam(3)). */ errno = 0; pw = getpwnam(ADIST_USER); if (pw == NULL) { if (errno != 0) { pjdlog_exit(EX_NOUSER, "Unable to find info about '%s' user", ADIST_USER); } else { pjdlog_exitx(EX_NOUSER, "User '%s' doesn't exist.", ADIST_USER); } } if (mkdir(adhost->adh_directory, 0700) == -1) { pjdlog_exit(EX_OSFILE, "Unable to create directory \"%s\"", adhost->adh_directory); } if (chown(adhost->adh_directory, pw->pw_uid, pw->pw_gid) == -1) { pjdlog_errno(LOG_ERR, "Unable to change owner of the directory \"%s\"", adhost->adh_directory); (void)rmdir(adhost->adh_directory); exit(EX_OSFILE); } } static void receiver_directory_open(void) { #ifdef HAVE_FDOPENDIR adhost->adh_trail_dirfd = open(adhost->adh_directory, O_RDONLY | O_DIRECTORY); if (adhost->adh_trail_dirfd == -1) { if (errno == ENOENT) { receiver_directory_create(); adhost->adh_trail_dirfd = open(adhost->adh_directory, O_RDONLY | O_DIRECTORY); } if (adhost->adh_trail_dirfd == -1) { pjdlog_exit(EX_CONFIG, "Unable to open directory \"%s\"", adhost->adh_directory); } } adhost->adh_trail_dirfp = fdopendir(adhost->adh_trail_dirfd); if (adhost->adh_trail_dirfp == NULL) { pjdlog_exit(EX_CONFIG, "Unable to fdopen directory \"%s\"", adhost->adh_directory); } #else struct stat sb; if (stat(adhost->adh_directory, &sb) == -1) { if (errno == ENOENT) { receiver_directory_create(); } else { pjdlog_exit(EX_CONFIG, "Unable to stat directory \"%s\"", adhost->adh_directory); } } adhost->adh_trail_dirfp = opendir(adhost->adh_directory); if (adhost->adh_trail_dirfp == NULL) { pjdlog_exit(EX_CONFIG, "Unable to open directory \"%s\"", adhost->adh_directory); } adhost->adh_trail_dirfd = dirfd(adhost->adh_trail_dirfp); #endif } static void receiver_connect(void) { uint64_t trail_size; struct stat sb; PJDLOG_ASSERT(adhost->adh_trail_dirfp != NULL); trail_last(adhost->adh_trail_dirfp, adhost->adh_trail_name, sizeof(adhost->adh_trail_name)); if (adhost->adh_trail_name[0] == '\0') { trail_size = 0; } else { if (fstatat(adhost->adh_trail_dirfd, adhost->adh_trail_name, &sb, AT_SYMLINK_NOFOLLOW) == -1) { pjdlog_exit(EX_CONFIG, "Unable to stat \"%s/%s\"", adhost->adh_directory, adhost->adh_trail_name); } if (!S_ISREG(sb.st_mode)) { pjdlog_exitx(EX_CONFIG, "File \"%s/%s\" is not a regular file.", adhost->adh_directory, adhost->adh_trail_name); } trail_size = sb.st_size; } trail_size = htole64(trail_size); if (proto_send(adhost->adh_remote, &trail_size, sizeof(trail_size)) == -1) { pjdlog_exit(EX_TEMPFAIL, "Unable to send size of the most recent trail file"); } if (proto_send(adhost->adh_remote, adhost->adh_trail_name, sizeof(adhost->adh_trail_name)) == -1) { pjdlog_exit(EX_TEMPFAIL, "Unable to send name of the most recent trail file"); } } void adist_receiver(struct adist_config *config, struct adist_host *adh) { sigset_t mask; pthread_t td; pid_t pid; int error, mode, debuglevel; pid = fork(); if (pid == -1) { pjdlog_errno(LOG_ERR, "Unable to fork"); proto_close(adh->adh_remote); adh->adh_remote = NULL; return; } if (pid > 0) { /* This is parent. */ proto_close(adh->adh_remote); adh->adh_remote = NULL; adh->adh_worker_pid = pid; return; } adcfg = config; adhost = adh; mode = pjdlog_mode_get(); debuglevel = pjdlog_debug_get(); descriptors_cleanup(adhost); // descriptors_assert(adhost, mode); pjdlog_init(mode); pjdlog_debug_set(debuglevel); pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, role2str(adhost->adh_role)); #ifdef HAVE_SETPROCTITLE setproctitle("%s (%s)", adhost->adh_name, role2str(adhost->adh_role)); #endif PJDLOG_VERIFY(sigemptyset(&mask) == 0); PJDLOG_VERIFY(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); /* Error in setting timeout is not critical, but why should it fail? */ if (proto_timeout(adhost->adh_remote, adcfg->adc_timeout) == -1) pjdlog_errno(LOG_WARNING, "Unable to set connection timeout"); init_environment(); adhost->adh_trail_fd = -1; receiver_directory_open(); if (sandbox(ADIST_USER, true, "auditdistd: %s (%s)", role2str(adhost->adh_role), adhost->adh_name) != 0) { exit(EX_CONFIG); } pjdlog_info("Privileges successfully dropped."); receiver_connect(); error = pthread_create(&td, NULL, recv_thread, adhost); PJDLOG_ASSERT(error == 0); error = pthread_create(&td, NULL, disk_thread, adhost); PJDLOG_ASSERT(error == 0); (void)send_thread(adhost); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/renameat.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/renameat.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/renameat.h (revision 292449) @@ -1,68 +1,66 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/renameat.h#1 $ */ #ifndef _RENAMEAT_H_ #define _RENAMEAT_H_ #include #include static int renameat(int fromfd, const char *from, int tofd, const char *to) { int cfd, error, ret; if (fromfd != tofd) { errno = EINVAL; return (-1); } cfd = open(".", O_RDONLY | O_DIRECTORY); if (cfd == -1) return (-1); if (fchdir(fromfd) == -1) { error = errno; (void)close(cfd); errno = error; return (-1); } ret = rename(from, to); error = errno; (void)fchdir(cfd); (void)close(cfd); errno = error; return (ret); } #endif /* !_RENAMEAT_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/sandbox.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/sandbox.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/sandbox.c (revision 292449) @@ -1,234 +1,232 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/sandbox.c#3 $ */ #include #include #ifdef HAVE_JAIL #include #endif #ifdef HAVE_CAP_ENTER #include #endif #include #include #include #include #include #include #include #include #include "pjdlog.h" #include "sandbox.h" static int groups_compare(const void *grp0, const void *grp1) { gid_t gr0 = *(const gid_t *)grp0; gid_t gr1 = *(const gid_t *)grp1; return (gr0 <= gr1 ? (gr0 < gr1 ? -1 : 0) : 1); } int sandbox(const char *user, bool capsicum, const char *fmt, ...) { #ifdef HAVE_JAIL struct jail jailst; char *jailhost; va_list ap; #endif struct passwd *pw; uid_t ruid, euid; gid_t rgid, egid; #ifdef HAVE_GETRESUID uid_t suid; #endif #ifdef HAVE_GETRESGID gid_t sgid; #endif gid_t *groups, *ggroups; bool jailed; int ngroups, ret; PJDLOG_ASSERT(user != NULL); PJDLOG_ASSERT(fmt != NULL); ret = -1; groups = NULL; ggroups = NULL; /* * According to getpwnam(3) we have to clear errno before calling the * function to be able to distinguish between an error and missing * entry (with is not treated as error by getpwnam(3)). */ errno = 0; pw = getpwnam(user); if (pw == NULL) { if (errno != 0) { pjdlog_errno(LOG_ERR, "Unable to find info about '%s' user", user); goto out; } else { pjdlog_error("'%s' user doesn't exist.", user); errno = ENOENT; goto out; } } ngroups = sysconf(_SC_NGROUPS_MAX); if (ngroups == -1) { pjdlog_errno(LOG_WARNING, "Unable to obtain maximum number of groups"); ngroups = NGROUPS_MAX; } ngroups++; /* For base gid. */ groups = malloc(sizeof(groups[0]) * ngroups); if (groups == NULL) { pjdlog_error("Unable to allocate memory for %d groups.", ngroups); goto out; } if (getgrouplist(user, pw->pw_gid, groups, &ngroups) == -1) { pjdlog_error("Unable to obtain groups of user %s.", user); goto out; } #ifdef HAVE_JAIL va_start(ap, fmt); (void)vasprintf(&jailhost, fmt, ap); va_end(ap); if (jailhost == NULL) { pjdlog_error("Unable to allocate memory for jail host name."); goto out; } bzero(&jailst, sizeof(jailst)); jailst.version = JAIL_API_VERSION; jailst.path = pw->pw_dir; jailst.hostname = jailhost; if (jail(&jailst) >= 0) { jailed = true; } else { jailed = false; pjdlog_errno(LOG_WARNING, "Unable to jail to directory %s", pw->pw_dir); } free(jailhost); #else /* !HAVE_JAIL */ jailed = false; #endif /* !HAVE_JAIL */ if (!jailed) { if (chroot(pw->pw_dir) == -1) { pjdlog_errno(LOG_ERR, "Unable to change root directory to %s", pw->pw_dir); goto out; } } PJDLOG_VERIFY(chdir("/") == 0); if (setgroups(ngroups, groups) == -1) { pjdlog_errno(LOG_ERR, "Unable to set groups"); goto out; } if (setgid(pw->pw_gid) == -1) { pjdlog_errno(LOG_ERR, "Unable to set gid to %u", (unsigned int)pw->pw_gid); goto out; } if (setuid(pw->pw_uid) == -1) { pjdlog_errno(LOG_ERR, "Unable to set uid to %u", (unsigned int)pw->pw_uid); goto out; } #ifdef HAVE_CAP_ENTER if (capsicum) { capsicum = (cap_enter() == 0); if (!capsicum) { pjdlog_common(LOG_DEBUG, 1, errno, "Unable to sandbox using capsicum"); } } #else /* !HAVE_CAP_ENTER */ capsicum = false; #endif /* !HAVE_CAP_ENTER */ /* * Better be sure that everything succeeded. */ #ifdef HAVE_GETRESUID PJDLOG_VERIFY(getresuid(&ruid, &euid, &suid) == 0); PJDLOG_VERIFY(suid == pw->pw_uid); #else ruid = getuid(); euid = geteuid(); #endif PJDLOG_VERIFY(ruid == pw->pw_uid); PJDLOG_VERIFY(euid == pw->pw_uid); #ifdef HAVE_GETRESGID PJDLOG_VERIFY(getresgid(&rgid, &egid, &sgid) == 0); PJDLOG_VERIFY(sgid == pw->pw_gid); #else rgid = getgid(); egid = getegid(); #endif PJDLOG_VERIFY(rgid == pw->pw_gid); PJDLOG_VERIFY(egid == pw->pw_gid); PJDLOG_VERIFY(getgroups(0, NULL) == ngroups); ggroups = malloc(sizeof(ggroups[0]) * ngroups); if (ggroups == NULL) { pjdlog_error("Unable to allocate memory for %d groups.", ngroups); goto out; } PJDLOG_VERIFY(getgroups(ngroups, ggroups) == ngroups); qsort(groups, (size_t)ngroups, sizeof(groups[0]), groups_compare); qsort(ggroups, (size_t)ngroups, sizeof(ggroups[0]), groups_compare); PJDLOG_VERIFY(bcmp(groups, ggroups, sizeof(groups[0]) * ngroups) == 0); pjdlog_debug(1, "Privileges successfully dropped using %s%s+setgid+setuid.", capsicum ? "capsicum+" : "", jailed ? "jail" : "chroot"); ret = 0; out: if (groups != NULL) free(groups); if (ggroups != NULL) free(ggroups); return (ret); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/sandbox.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/sandbox.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/sandbox.h (revision 292449) @@ -1,39 +1,37 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/sandbox.h#1 $ */ #ifndef _SANDBOX_H_ #define _SANDBOX_H_ #include int sandbox(const char *user, bool capsicum, const char *fmt, ...); #endif /* !_SANDBOX_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/sender.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/sender.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/sender.c (revision 292449) @@ -1,847 +1,845 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/sender.c#3 $ */ #include #include #if defined(HAVE_SYS_ENDIAN_H) && defined(HAVE_BSWAP) #include #else /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */ #ifdef HAVE_MACHINE_ENDIAN_H #include #else /* !HAVE_MACHINE_ENDIAN_H */ #ifdef HAVE_ENDIAN_H #include #else /* !HAVE_ENDIAN_H */ #error "No supported endian.h" #endif /* !HAVE_ENDIAN_H */ #endif /* !HAVE_MACHINE_ENDIAN_H */ #include #endif /* !HAVE_SYS_ENDIAN_H || !HAVE_BSWAP */ #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LIBUTIL_H #include #endif #include #include #include #include #ifndef HAVE_SIGTIMEDWAIT #include "sigtimedwait.h" #endif #include "auditdistd.h" #include "pjdlog.h" #include "proto.h" #include "sandbox.h" #include "subr.h" #include "synch.h" #include "trail.h" static struct adist_config *adcfg; static struct adist_host *adhost; static pthread_rwlock_t adist_remote_lock; static pthread_mutex_t adist_remote_mtx; static pthread_cond_t adist_remote_cond; static struct trail *adist_trail; static TAILQ_HEAD(, adreq) adist_free_list; static pthread_mutex_t adist_free_list_lock; static pthread_cond_t adist_free_list_cond; static TAILQ_HEAD(, adreq) adist_send_list; static pthread_mutex_t adist_send_list_lock; static pthread_cond_t adist_send_list_cond; static TAILQ_HEAD(, adreq) adist_recv_list; static pthread_mutex_t adist_recv_list_lock; static pthread_cond_t adist_recv_list_cond; static void init_environment(void) { struct adreq *adreq; unsigned int ii; rw_init(&adist_remote_lock); mtx_init(&adist_remote_mtx); cv_init(&adist_remote_cond); TAILQ_INIT(&adist_free_list); mtx_init(&adist_free_list_lock); cv_init(&adist_free_list_cond); TAILQ_INIT(&adist_send_list); mtx_init(&adist_send_list_lock); cv_init(&adist_send_list_cond); TAILQ_INIT(&adist_recv_list); mtx_init(&adist_recv_list_lock); cv_init(&adist_recv_list_cond); for (ii = 0; ii < ADIST_QUEUE_SIZE; ii++) { adreq = malloc(sizeof(*adreq) + ADIST_BUF_SIZE); if (adreq == NULL) { pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate %zu bytes of memory for adreq object.", sizeof(*adreq) + ADIST_BUF_SIZE); } adreq->adr_byteorder = ADIST_BYTEORDER; adreq->adr_cmd = ADIST_CMD_UNDEFINED; adreq->adr_seq = 0; adreq->adr_datasize = 0; TAILQ_INSERT_TAIL(&adist_free_list, adreq, adr_next); } } static int sender_connect(void) { unsigned char rnd[32], hash[32], resp[32]; struct proto_conn *conn; char welcome[8]; int16_t val; val = 1; if (proto_send(adhost->adh_conn, &val, sizeof(val)) < 0) { pjdlog_exit(EX_TEMPFAIL, "Unable to send connection request to parent"); } if (proto_recv(adhost->adh_conn, &val, sizeof(val)) < 0) { pjdlog_exit(EX_TEMPFAIL, "Unable to receive reply to connection request from parent"); } if (val != 0) { errno = val; pjdlog_errno(LOG_WARNING, "Unable to connect to %s", adhost->adh_remoteaddr); return (-1); } if (proto_connection_recv(adhost->adh_conn, true, &conn) < 0) { pjdlog_exit(EX_TEMPFAIL, "Unable to receive connection from parent"); } if (proto_connect_wait(conn, adcfg->adc_timeout) < 0) { pjdlog_errno(LOG_WARNING, "Unable to connect to %s", adhost->adh_remoteaddr); proto_close(conn); return (-1); } pjdlog_debug(1, "Connected to %s.", adhost->adh_remoteaddr); /* Error in setting timeout is not critical, but why should it fail? */ if (proto_timeout(conn, adcfg->adc_timeout) < 0) pjdlog_errno(LOG_WARNING, "Unable to set connection timeout"); else pjdlog_debug(1, "Timeout set to %d.", adcfg->adc_timeout); /* Exchange welcome message, which includes version number. */ (void)snprintf(welcome, sizeof(welcome), "ADIST%02d", ADIST_VERSION); if (proto_send(conn, welcome, sizeof(welcome)) < 0) { pjdlog_errno(LOG_WARNING, "Unable to send welcome message to %s", adhost->adh_remoteaddr); proto_close(conn); return (-1); } pjdlog_debug(1, "Welcome message sent (%s).", welcome); bzero(welcome, sizeof(welcome)); if (proto_recv(conn, welcome, sizeof(welcome)) < 0) { pjdlog_errno(LOG_WARNING, "Unable to receive welcome message from %s", adhost->adh_remoteaddr); proto_close(conn); return (-1); } if (strncmp(welcome, "ADIST", 5) != 0 || !isdigit(welcome[5]) || !isdigit(welcome[6]) || welcome[7] != '\0') { pjdlog_warning("Invalid welcome message from %s.", adhost->adh_remoteaddr); proto_close(conn); return (-1); } pjdlog_debug(1, "Welcome message received (%s).", welcome); /* * Receiver can only reply with version number lower or equal to * the one we sent. */ adhost->adh_version = atoi(welcome + 5); if (adhost->adh_version > ADIST_VERSION) { pjdlog_warning("Invalid version number from %s (%d received, up to %d supported).", adhost->adh_remoteaddr, adhost->adh_version, ADIST_VERSION); proto_close(conn); return (-1); } pjdlog_debug(1, "Version %d negotiated with %s.", adhost->adh_version, adhost->adh_remoteaddr); if (proto_send(conn, adcfg->adc_name, sizeof(adcfg->adc_name)) == -1) { pjdlog_errno(LOG_WARNING, "Unable to send name to %s", adhost->adh_remoteaddr); proto_close(conn); return (-1); } pjdlog_debug(1, "Name (%s) sent.", adcfg->adc_name); if (proto_recv(conn, rnd, sizeof(rnd)) == -1) { pjdlog_errno(LOG_WARNING, "Unable to receive challenge from %s", adhost->adh_remoteaddr); proto_close(conn); return (-1); } pjdlog_debug(1, "Challenge received."); if (HMAC(EVP_sha256(), adhost->adh_password, (int)strlen(adhost->adh_password), rnd, (int)sizeof(rnd), hash, NULL) == NULL) { pjdlog_warning("Unable to generate response."); proto_close(conn); return (-1); } pjdlog_debug(1, "Response generated."); if (proto_send(conn, hash, sizeof(hash)) == -1) { pjdlog_errno(LOG_WARNING, "Unable to send response to %s", adhost->adh_remoteaddr); proto_close(conn); return (-1); } pjdlog_debug(1, "Response sent."); if (adist_random(rnd, sizeof(rnd)) == -1) { pjdlog_warning("Unable to generate challenge."); proto_close(conn); return (-1); } pjdlog_debug(1, "Challenge generated."); if (proto_send(conn, rnd, sizeof(rnd)) == -1) { pjdlog_errno(LOG_WARNING, "Unable to send challenge to %s", adhost->adh_remoteaddr); proto_close(conn); return (-1); } pjdlog_debug(1, "Challenge sent."); if (proto_recv(conn, resp, sizeof(resp)) == -1) { pjdlog_errno(LOG_WARNING, "Unable to receive response from %s", adhost->adh_remoteaddr); proto_close(conn); return (-1); } pjdlog_debug(1, "Response received."); if (HMAC(EVP_sha256(), adhost->adh_password, (int)strlen(adhost->adh_password), rnd, (int)sizeof(rnd), hash, NULL) == NULL) { pjdlog_warning("Unable to generate hash."); proto_close(conn); return (-1); } pjdlog_debug(1, "Hash generated."); if (memcmp(resp, hash, sizeof(hash)) != 0) { pjdlog_warning("Invalid response from %s (wrong password?).", adhost->adh_remoteaddr); proto_close(conn); return (-1); } pjdlog_info("Receiver authenticated."); if (proto_recv(conn, &adhost->adh_trail_offset, sizeof(adhost->adh_trail_offset)) == -1) { pjdlog_errno(LOG_WARNING, "Unable to receive size of the most recent trail file from %s", adhost->adh_remoteaddr); proto_close(conn); return (-1); } adhost->adh_trail_offset = le64toh(adhost->adh_trail_offset); if (proto_recv(conn, &adhost->adh_trail_name, sizeof(adhost->adh_trail_name)) == -1) { pjdlog_errno(LOG_WARNING, "Unable to receive name of the most recent trail file from %s", adhost->adh_remoteaddr); proto_close(conn); return (-1); } pjdlog_debug(1, "Trail name (%s) and offset (%ju) received.", adhost->adh_trail_name, (uintmax_t)adhost->adh_trail_offset); rw_wlock(&adist_remote_lock); mtx_lock(&adist_remote_mtx); PJDLOG_ASSERT(adhost->adh_remote == NULL); PJDLOG_ASSERT(conn != NULL); adhost->adh_remote = conn; mtx_unlock(&adist_remote_mtx); rw_unlock(&adist_remote_lock); cv_signal(&adist_remote_cond); return (0); } static void sender_disconnect(void) { rw_wlock(&adist_remote_lock); /* * Check for a race between dropping rlock and acquiring wlock - * another thread can close connection in-between. */ if (adhost->adh_remote == NULL) { rw_unlock(&adist_remote_lock); return; } pjdlog_debug(2, "Closing connection to %s.", adhost->adh_remoteaddr); proto_close(adhost->adh_remote); mtx_lock(&adist_remote_mtx); adhost->adh_remote = NULL; adhost->adh_reset = true; adhost->adh_trail_name[0] = '\0'; adhost->adh_trail_offset = 0; mtx_unlock(&adist_remote_mtx); rw_unlock(&adist_remote_lock); pjdlog_warning("Disconnected from %s.", adhost->adh_remoteaddr); /* Move all in-flight requests back onto free list. */ mtx_lock(&adist_free_list_lock); mtx_lock(&adist_send_list_lock); TAILQ_CONCAT(&adist_free_list, &adist_send_list, adr_next); mtx_unlock(&adist_send_list_lock); mtx_lock(&adist_recv_list_lock); TAILQ_CONCAT(&adist_free_list, &adist_recv_list, adr_next); mtx_unlock(&adist_recv_list_lock); mtx_unlock(&adist_free_list_lock); } static void adreq_fill(struct adreq *adreq, uint8_t cmd, const unsigned char *data, size_t size) { static uint64_t seq = 1; PJDLOG_ASSERT(size <= ADIST_BUF_SIZE); switch (cmd) { case ADIST_CMD_OPEN: case ADIST_CMD_CLOSE: PJDLOG_ASSERT(data != NULL && size == 0); size = strlen(data) + 1; break; case ADIST_CMD_APPEND: PJDLOG_ASSERT(data != NULL && size > 0); break; case ADIST_CMD_KEEPALIVE: case ADIST_CMD_ERROR: PJDLOG_ASSERT(data == NULL && size == 0); break; default: PJDLOG_ABORT("Invalid command (%hhu).", cmd); } adreq->adr_cmd = cmd; adreq->adr_seq = seq++; adreq->adr_datasize = size; /* Don't copy if data is already in out buffer. */ if (data != NULL && data != adreq->adr_data) bcopy(data, adreq->adr_data, size); } static bool read_thread_wait(void) { bool newfile = false; mtx_lock(&adist_remote_mtx); if (adhost->adh_reset) { reset: adhost->adh_reset = false; if (trail_filefd(adist_trail) != -1) trail_close(adist_trail); trail_reset(adist_trail); while (adhost->adh_remote == NULL) cv_wait(&adist_remote_cond, &adist_remote_mtx); trail_start(adist_trail, adhost->adh_trail_name, adhost->adh_trail_offset); newfile = true; } mtx_unlock(&adist_remote_mtx); while (trail_filefd(adist_trail) == -1) { newfile = true; wait_for_dir(); /* * We may have been disconnected and reconnected in the * meantime, check if reset is set. */ mtx_lock(&adist_remote_mtx); if (adhost->adh_reset) goto reset; mtx_unlock(&adist_remote_mtx); if (trail_filefd(adist_trail) == -1) trail_next(adist_trail); } if (newfile) { pjdlog_debug(1, "Trail file \"%s/%s\" opened.", adhost->adh_directory, trail_filename(adist_trail)); (void)wait_for_file_init(trail_filefd(adist_trail)); } return (newfile); } static void * read_thread(void *arg __unused) { struct adreq *adreq; ssize_t done; bool newfile; pjdlog_debug(1, "%s started.", __func__); for (;;) { newfile = read_thread_wait(); QUEUE_TAKE(adreq, &adist_free_list, 0); if (newfile) { adreq_fill(adreq, ADIST_CMD_OPEN, trail_filename(adist_trail), 0); newfile = false; goto move; } done = read(trail_filefd(adist_trail), adreq->adr_data, ADIST_BUF_SIZE); if (done == -1) { off_t offset; int error; error = errno; offset = lseek(trail_filefd(adist_trail), 0, SEEK_CUR); errno = error; pjdlog_errno(LOG_ERR, "Error while reading \"%s/%s\" at offset %jd", adhost->adh_directory, trail_filename(adist_trail), offset); trail_close(adist_trail); adreq_fill(adreq, ADIST_CMD_ERROR, NULL, 0); goto move; } else if (done == 0) { /* End of file. */ pjdlog_debug(3, "End of \"%s/%s\".", adhost->adh_directory, trail_filename(adist_trail)); if (!trail_switch(adist_trail)) { /* More audit records can arrive. */ mtx_lock(&adist_free_list_lock); TAILQ_INSERT_TAIL(&adist_free_list, adreq, adr_next); mtx_unlock(&adist_free_list_lock); wait_for_file(); continue; } adreq_fill(adreq, ADIST_CMD_CLOSE, trail_filename(adist_trail), 0); trail_close(adist_trail); goto move; } adreq_fill(adreq, ADIST_CMD_APPEND, adreq->adr_data, done); move: pjdlog_debug(3, "read thread: Moving request %p to the send queue (%hhu).", adreq, adreq->adr_cmd); QUEUE_INSERT(adreq, &adist_send_list); } /* NOTREACHED */ return (NULL); } static void keepalive_send(void) { struct adreq *adreq; rw_rlock(&adist_remote_lock); if (adhost->adh_remote == NULL) { rw_unlock(&adist_remote_lock); return; } rw_unlock(&adist_remote_lock); mtx_lock(&adist_free_list_lock); adreq = TAILQ_FIRST(&adist_free_list); if (adreq != NULL) TAILQ_REMOVE(&adist_free_list, adreq, adr_next); mtx_unlock(&adist_free_list_lock); if (adreq == NULL) return; adreq_fill(adreq, ADIST_CMD_KEEPALIVE, NULL, 0); QUEUE_INSERT(adreq, &adist_send_list); pjdlog_debug(3, "keepalive_send: Request sent."); } /* * Thread sends request to secondary node. */ static void * send_thread(void *arg __unused) { time_t lastcheck, now; struct adreq *adreq; pjdlog_debug(1, "%s started.", __func__); lastcheck = time(NULL); for (;;) { pjdlog_debug(3, "send thread: Taking request."); for (;;) { QUEUE_TAKE(adreq, &adist_send_list, ADIST_KEEPALIVE); if (adreq != NULL) break; now = time(NULL); if (lastcheck + ADIST_KEEPALIVE <= now) { keepalive_send(); lastcheck = now; } } PJDLOG_ASSERT(adreq != NULL); pjdlog_debug(3, "send thread: (%p) Got request %hhu.", adreq, adreq->adr_cmd); /* * Protect connection from disappearing. */ rw_rlock(&adist_remote_lock); /* * Move the request to the recv queue first to avoid race * where the recv thread receives the reply before we move * the request to the recv queue. */ QUEUE_INSERT(adreq, &adist_recv_list); if (adhost->adh_remote == NULL || proto_send(adhost->adh_remote, &adreq->adr_packet, ADPKT_SIZE(adreq)) == -1) { rw_unlock(&adist_remote_lock); pjdlog_debug(1, "send thread: (%p) Unable to send request.", adreq); if (adhost->adh_remote != NULL) sender_disconnect(); continue; } else { pjdlog_debug(3, "Request %p sent successfully.", adreq); adreq_log(LOG_DEBUG, 2, -1, adreq, "send: (%p) Request sent: ", adreq); rw_unlock(&adist_remote_lock); } } /* NOTREACHED */ return (NULL); } static void adrep_decode_header(struct adrep *adrep) { /* Byte-swap only is the receiver is using different byte order. */ if (adrep->adrp_byteorder != ADIST_BYTEORDER) { adrep->adrp_byteorder = ADIST_BYTEORDER; adrep->adrp_seq = bswap64(adrep->adrp_seq); adrep->adrp_error = bswap16(adrep->adrp_error); } } /* * Thread receives answer from secondary node and passes it to ggate_send * thread. */ static void * recv_thread(void *arg __unused) { struct adrep adrep; struct adreq *adreq; pjdlog_debug(1, "%s started.", __func__); for (;;) { /* Wait until there is anything to receive. */ QUEUE_WAIT(&adist_recv_list); pjdlog_debug(3, "recv thread: Got something."); rw_rlock(&adist_remote_lock); if (adhost->adh_remote == NULL) { /* * Connection is dead. * XXX: We shouldn't be here. */ rw_unlock(&adist_remote_lock); continue; } if (proto_recv(adhost->adh_remote, &adrep, sizeof(adrep)) == -1) { rw_unlock(&adist_remote_lock); pjdlog_errno(LOG_ERR, "Unable to receive reply"); sender_disconnect(); continue; } rw_unlock(&adist_remote_lock); adrep_decode_header(&adrep); /* * Find the request that was just confirmed. */ mtx_lock(&adist_recv_list_lock); TAILQ_FOREACH(adreq, &adist_recv_list, adr_next) { if (adreq->adr_seq == adrep.adrp_seq) { TAILQ_REMOVE(&adist_recv_list, adreq, adr_next); break; } } if (adreq == NULL) { /* * If we disconnected in the meantime, just continue. * On disconnect sender_disconnect() clears the queue, * we can use that. */ if (TAILQ_EMPTY(&adist_recv_list)) { mtx_unlock(&adist_recv_list_lock); continue; } mtx_unlock(&adist_recv_list_lock); pjdlog_error("Found no request matching received 'seq' field (%ju).", (uintmax_t)adrep.adrp_seq); sender_disconnect(); continue; } mtx_unlock(&adist_recv_list_lock); adreq_log(LOG_DEBUG, 2, -1, adreq, "recv thread: (%p) Request confirmed: ", adreq); pjdlog_debug(3, "recv thread: (%p) Got request %hhu.", adreq, adreq->adr_cmd); if (adrep.adrp_error != 0) { pjdlog_error("Receiver returned error (%s), disconnecting.", adist_errstr((int)adrep.adrp_error)); sender_disconnect(); continue; } if (adreq->adr_cmd == ADIST_CMD_CLOSE) trail_unlink(adist_trail, adreq->adr_data); pjdlog_debug(3, "Request received successfully."); QUEUE_INSERT(adreq, &adist_free_list); } /* NOTREACHED */ return (NULL); } static void guard_check_connection(void) { PJDLOG_ASSERT(adhost->adh_role == ADIST_ROLE_SENDER); rw_rlock(&adist_remote_lock); if (adhost->adh_remote != NULL) { rw_unlock(&adist_remote_lock); pjdlog_debug(3, "remote_guard: Connection to %s is ok.", adhost->adh_remoteaddr); return; } /* * Upgrade the lock. It doesn't have to be atomic as no other thread * can change connection status from disconnected to connected. */ rw_unlock(&adist_remote_lock); pjdlog_debug(1, "remote_guard: Reconnecting to %s.", adhost->adh_remoteaddr); if (sender_connect() == 0) { pjdlog_info("Successfully reconnected to %s.", adhost->adh_remoteaddr); } else { pjdlog_debug(1, "remote_guard: Reconnect to %s failed.", adhost->adh_remoteaddr); } } /* * Thread guards remote connections and reconnects when needed, handles * signals, etc. */ static void * guard_thread(void *arg __unused) { struct timespec timeout; time_t lastcheck, now; sigset_t mask; int signo; lastcheck = time(NULL); PJDLOG_VERIFY(sigemptyset(&mask) == 0); PJDLOG_VERIFY(sigaddset(&mask, SIGINT) == 0); PJDLOG_VERIFY(sigaddset(&mask, SIGTERM) == 0); timeout.tv_sec = ADIST_KEEPALIVE; timeout.tv_nsec = 0; signo = -1; for (;;) { switch (signo) { case SIGINT: case SIGTERM: sigexit_received = true; pjdlog_exitx(EX_OK, "Termination signal received, exiting."); break; default: break; } pjdlog_debug(3, "remote_guard: Checking connections."); now = time(NULL); if (lastcheck + ADIST_KEEPALIVE <= now) { guard_check_connection(); lastcheck = now; } signo = sigtimedwait(&mask, NULL, &timeout); } /* NOTREACHED */ return (NULL); } void adist_sender(struct adist_config *config, struct adist_host *adh) { pthread_t td; pid_t pid; int error, mode, debuglevel; /* * Create communication channel for sending connection requests from * child to parent. */ if (proto_connect(NULL, "socketpair://", -1, &adh->adh_conn) == -1) { pjdlog_errno(LOG_ERR, "Unable to create connection sockets between child and parent"); return; } pid = fork(); if (pid == -1) { pjdlog_errno(LOG_ERR, "Unable to fork"); proto_close(adh->adh_conn); adh->adh_conn = NULL; return; } if (pid > 0) { /* This is parent. */ adh->adh_worker_pid = pid; /* Declare that we are receiver. */ proto_recv(adh->adh_conn, NULL, 0); return; } adcfg = config; adhost = adh; mode = pjdlog_mode_get(); debuglevel = pjdlog_debug_get(); /* Declare that we are sender. */ proto_send(adhost->adh_conn, NULL, 0); descriptors_cleanup(adhost); #ifdef TODO descriptors_assert(adhost, mode); #endif pjdlog_init(mode); pjdlog_debug_set(debuglevel); pjdlog_prefix_set("[%s] (%s) ", adhost->adh_name, role2str(adhost->adh_role)); #ifdef HAVE_SETPROCTITLE setproctitle("[%s] (%s) ", adhost->adh_name, role2str(adhost->adh_role)); #endif /* * The sender process should be able to remove entries from its * trail directory, but it should not be able to write to the * trail files, only read from them. */ adist_trail = trail_new(adhost->adh_directory, false); if (adist_trail == NULL) exit(EX_OSFILE); if (sandbox(ADIST_USER, true, "auditdistd: %s (%s)", role2str(adhost->adh_role), adhost->adh_name) != 0) { exit(EX_CONFIG); } pjdlog_info("Privileges successfully dropped."); /* * We can ignore wait_for_dir_init() failures. It will fall back to * using sleep(3). */ (void)wait_for_dir_init(trail_dirfd(adist_trail)); init_environment(); if (sender_connect() == 0) { pjdlog_info("Successfully connected to %s.", adhost->adh_remoteaddr); } adhost->adh_reset = true; /* * Create the guard thread first, so we can handle signals from the * very begining. */ error = pthread_create(&td, NULL, guard_thread, NULL); PJDLOG_ASSERT(error == 0); error = pthread_create(&td, NULL, send_thread, NULL); PJDLOG_ASSERT(error == 0); error = pthread_create(&td, NULL, recv_thread, NULL); PJDLOG_ASSERT(error == 0); (void)read_thread(NULL); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/sigtimedwait.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/sigtimedwait.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/sigtimedwait.h (revision 292449) @@ -1,92 +1,90 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/sigtimedwait.h#2 $ */ #ifndef _SIGTIMEDWAIT_H_ #define _SIGTIMEDWAIT_H_ #include #include #include #include #include #include #include #include #include "pjdlog.h" static int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout) { struct itimerval it; sigset_t mask; int error, signo; PJDLOG_ASSERT(info == NULL); PJDLOG_VERIFY(sigemptyset(&mask) == 0); PJDLOG_VERIFY(sigaddset(&mask, SIGALRM) == 0); PJDLOG_VERIFY(sigprocmask(SIG_BLOCK, &mask, NULL) == 0); timerclear(&it.it_interval); it.it_value.tv_sec = timeout->tv_sec; it.it_value.tv_usec = timeout->tv_nsec / 1000; if (it.it_value.tv_sec == 0 && it.it_value.tv_usec == 0) it.it_value.tv_usec = 1; PJDLOG_VERIFY(setitimer(ITIMER_REAL, &it, NULL) == 0); bcopy(set, &mask, sizeof(mask)); PJDLOG_VERIFY(sigaddset(&mask, SIGALRM) == 0); PJDLOG_VERIFY(sigwait(&mask, &signo) == 0); error = errno; timerclear(&it.it_interval); timerclear(&it.it_value); PJDLOG_VERIFY(setitimer(ITIMER_REAL, &it, NULL) == 0); PJDLOG_VERIFY(sigemptyset(&mask) == 0); PJDLOG_VERIFY(sigaddset(&mask, SIGALRM) == 0); PJDLOG_VERIFY(sigprocmask(SIG_UNBLOCK, &mask, NULL) == 0); if (signo == SIGALRM) { errno = EAGAIN; signo = -1; } else { errno = error; } return (signo); } #endif /* !_SIGTIMEDWAIT_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/strndup.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/strndup.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/strndup.h (revision 292449) @@ -1,55 +1,53 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/strndup.h#1 $ */ #ifndef _STRNDUP_H_ #define _STRNDUP_H_ #include #include static char * strndup(const char *str, size_t len) { size_t outlen; char *outstr; outlen = strlen(str); if (outlen > len) outlen = len; outstr = malloc(outlen + 1); if (outstr != NULL) { memcpy(outstr, str, outlen); outstr[outlen] = '\0'; } return (outstr); } #endif /* !_STRNDUP_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/subr.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/subr.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/subr.c (revision 292449) @@ -1,306 +1,304 @@ /*- * Copyright (c) 2011-2012 Pawel Jakub Dawidek * 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 AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/subr.c#3 $ */ #include #ifdef HAVE_KQUEUE #include #include #include #endif #include #include #include #include #include #ifndef HAVE_ARC4RANDOM #include #endif #ifndef HAVE_STRLCAT #include #endif #include "auditdistd.h" #include "pjdlog.h" #include "subr.h" int vsnprlcat(char *str, size_t size, const char *fmt, va_list ap) { size_t len; len = strlen(str); return (vsnprintf(str + len, size - len, fmt, ap)); } int snprlcat(char *str, size_t size, const char *fmt, ...) { va_list ap; int result; va_start(ap, fmt); result = vsnprlcat(str, size, fmt, ap); va_end(ap); return (result); } const char * role2str(int role) { switch (role) { case ADIST_ROLE_SENDER: return ("sender"); case ADIST_ROLE_RECEIVER: return ("receiver"); } return ("unknown"); } const char * adist_errstr(int error) { switch (error) { case ADIST_ERROR_WRONG_ORDER: return ("wrong operations order"); case ADIST_ERROR_INVALID_NAME: return ("invalid trail file name"); case ADIST_ERROR_OPEN_OLD: return ("attempt to open an old trail file"); case ADIST_ERROR_CREATE: return ("creation of new trail file failed"); case ADIST_ERROR_OPEN: return ("open of existing trail file failed"); case ADIST_ERROR_READ: return ("read failed"); case ADIST_ERROR_WRITE: return ("write failed"); case ADIST_ERROR_RENAME: return ("rename of a trail file failed"); default: return ("unknown error"); } } void adreq_log(int loglevel, int debuglevel, int error, struct adreq *adreq, const char *fmt, ...) { char msg[1024]; va_list ap; va_start(ap, fmt); (void)vsnprintf(msg, sizeof(msg), fmt, ap); va_end(ap); (void)snprlcat(msg, sizeof(msg), "(seq=%ju) ", (uintmax_t)adreq->adr_seq); switch (adreq->adr_cmd) { case ADIST_CMD_OPEN: (void)snprlcat(msg, sizeof(msg), "OPEN(%s)", adreq->adr_data); break; case ADIST_CMD_APPEND: (void)snprlcat(msg, sizeof(msg), "APPEND(%ju)", (uintmax_t)adreq->adr_datasize); break; case ADIST_CMD_CLOSE: (void)snprlcat(msg, sizeof(msg), "CLOSE(%s)", adreq->adr_data); break; case ADIST_CMD_KEEPALIVE: (void)snprlcat(msg, sizeof(msg), "KEEPALIVE"); break; case ADIST_CMD_ERROR: (void)snprlcat(msg, sizeof(msg), "ERROR"); break; default: (void)snprlcat(msg, sizeof(msg), "UNKNOWN(%hhu)", adreq->adr_cmd); break; } if (error != -1) (void)snprlcat(msg, sizeof(msg), ": %s", adist_errstr(error)); (void)strlcat(msg, ".", sizeof(msg)); pjdlog_common(loglevel, debuglevel, -1, "%s", msg); } int adist_random(unsigned char *buf, size_t size) { #ifdef HAVE_ARC4RANDOM_BUF arc4random_buf(buf, size); return (0); #elif defined(HAVE_ARC4RANDOM) uint32_t val; PJDLOG_ASSERT(size > 0); PJDLOG_ASSERT((size % sizeof(val)) == 0); do { val = arc4random(); bcopy(&val, buf, sizeof(val)); buf += sizeof(val); size -= sizeof(val); } while (size > 0); return (0); #else if (RAND_bytes(buf, (int)size) == 0) return (-1); return (0); #endif } static int wait_for_dir_kq = -1; static int wait_for_file_kq = -1; int wait_for_dir_init(int fd) { #ifdef HAVE_KQUEUE struct kevent ev; int error, kq; PJDLOG_ASSERT(wait_for_dir_kq == -1); #endif PJDLOG_ASSERT(fd != -1); #ifdef HAVE_KQUEUE kq = kqueue(); if (kq == -1) { pjdlog_errno(LOG_WARNING, "kqueue() failed"); return (-1); } EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, NOTE_WRITE, 0, 0); if (kevent(kq, &ev, 1, NULL, 0, NULL) == -1) { error = errno; pjdlog_errno(LOG_WARNING, "kevent() failed"); (void)close(kq); errno = error; return (-1); } wait_for_dir_kq = kq; #endif return (0); } int wait_for_file_init(int fd) { #ifdef HAVE_KQUEUE struct kevent ev[2]; int error, kq; #endif PJDLOG_ASSERT(fd != -1); #ifdef HAVE_KQUEUE if (wait_for_file_kq != -1) { close(wait_for_file_kq); wait_for_file_kq = -1; } kq = kqueue(); if (kq == -1) { pjdlog_errno(LOG_WARNING, "kqueue() failed"); return (-1); } EV_SET(&ev[0], fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, NOTE_RENAME, 0, 0); EV_SET(&ev[1], fd, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0); if (kevent(kq, ev, 2, NULL, 0, NULL) == -1) { error = errno; pjdlog_errno(LOG_WARNING, "kevent() failed"); (void)close(kq); errno = error; return (-1); } wait_for_file_kq = kq; #endif return (0); } /* * Wait for new file to appear in directory. */ void wait_for_dir(void) { #ifdef HAVE_KQUEUE struct kevent ev; #endif if (wait_for_dir_kq == -1) { sleep(1); return; } #ifdef HAVE_KQUEUE PJDLOG_ASSERT(wait_for_dir_kq != -1); if (kevent(wait_for_dir_kq, NULL, 0, &ev, 1, NULL) == -1) { pjdlog_errno(LOG_WARNING, "kevent() failed"); sleep(1); } #endif } /* * Wait for file growth or rename. */ void wait_for_file(void) { #ifdef HAVE_KQUEUE struct kevent ev[2]; #endif if (wait_for_file_kq == -1) { sleep(1); return; } #ifdef HAVE_KQUEUE PJDLOG_ASSERT(wait_for_file_kq != -1); if (kevent(wait_for_file_kq, NULL, 0, ev, 2, NULL) == -1) { pjdlog_errno(LOG_WARNING, "kevent() failed"); sleep(1); } #endif } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/subr.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/subr.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/subr.h (revision 292449) @@ -1,60 +1,58 @@ /*- * Copyright (c) 2011 Pawel Jakub Dawidek * 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 AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/subr.h#1 $ */ #ifndef _AUDITDISTD_SUBR_H_ #define _AUDITDISTD_SUBR_H_ #include #include "auditdistd.h" #define KEEP_ERRNO(work) do { \ int _rerrno; \ \ _rerrno = errno; \ work; \ errno = _rerrno; \ } while (0) int vsnprlcat(char *str, size_t size, const char *fmt, va_list ap); int snprlcat(char *str, size_t size, const char *fmt, ...); const char *role2str(int role); const char *adist_errstr(int error); void adreq_log(int loglevel, int debuglevel, int error, struct adreq *adreq, const char *fmt, ...); int adist_random(unsigned char *buf, size_t size); int wait_for_dir_init(int fd); int wait_for_file_init(int fd); void wait_for_dir(void); void wait_for_file(void); #endif /* !_AUDITDISTD_SUBR_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/synch.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/synch.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/synch.h (revision 292449) @@ -1,206 +1,204 @@ /*- * Copyright (c) 2009-2010 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/synch.h#3 $ */ #ifndef _SYNCH_H_ #define _SYNCH_H_ #include #include #ifdef HAVE_PTHREAD_NP_H #include #endif #include #include #include "pjdlog.h" #ifndef PJDLOG_ASSERT #include #define PJDLOG_ASSERT(...) assert(__VA_ARGS__) #endif static __inline void mtx_init(pthread_mutex_t *lock) { int error; error = pthread_mutex_init(lock, NULL); PJDLOG_ASSERT(error == 0); } static __inline void mtx_destroy(pthread_mutex_t *lock) { int error; error = pthread_mutex_destroy(lock); PJDLOG_ASSERT(error == 0); } static __inline void mtx_lock(pthread_mutex_t *lock) { int error; error = pthread_mutex_lock(lock); PJDLOG_ASSERT(error == 0); } static __inline bool mtx_trylock(pthread_mutex_t *lock) { int error; error = pthread_mutex_trylock(lock); PJDLOG_ASSERT(error == 0 || error == EBUSY); return (error == 0); } static __inline void mtx_unlock(pthread_mutex_t *lock) { int error; error = pthread_mutex_unlock(lock); PJDLOG_ASSERT(error == 0); } static __inline bool mtx_owned(pthread_mutex_t *lock) { return (pthread_mutex_isowned_np(lock) != 0); } static __inline void rw_init(pthread_rwlock_t *lock) { int error; error = pthread_rwlock_init(lock, NULL); PJDLOG_ASSERT(error == 0); } static __inline void rw_destroy(pthread_rwlock_t *lock) { int error; error = pthread_rwlock_destroy(lock); PJDLOG_ASSERT(error == 0); } static __inline void rw_rlock(pthread_rwlock_t *lock) { int error; error = pthread_rwlock_rdlock(lock); PJDLOG_ASSERT(error == 0); } static __inline void rw_wlock(pthread_rwlock_t *lock) { int error; error = pthread_rwlock_wrlock(lock); PJDLOG_ASSERT(error == 0); } static __inline void rw_unlock(pthread_rwlock_t *lock) { int error; error = pthread_rwlock_unlock(lock); PJDLOG_ASSERT(error == 0); } static __inline void cv_init(pthread_cond_t *cv) { pthread_condattr_t attr; int error; error = pthread_condattr_init(&attr); PJDLOG_ASSERT(error == 0); #ifdef HAVE_PTHREAD_CONDATTR_SETCLOCK error = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); PJDLOG_ASSERT(error == 0); #endif error = pthread_cond_init(cv, &attr); PJDLOG_ASSERT(error == 0); error = pthread_condattr_destroy(&attr); PJDLOG_ASSERT(error == 0); } static __inline void cv_wait(pthread_cond_t *cv, pthread_mutex_t *lock) { int error; error = pthread_cond_wait(cv, lock); PJDLOG_ASSERT(error == 0); } static __inline bool cv_timedwait(pthread_cond_t *cv, pthread_mutex_t *lock, int timeout) { struct timespec ts; int error; if (timeout == 0) { cv_wait(cv, lock); return (false); } #ifdef HAVE_PTHREAD_CONDATTR_SETCLOCK error = clock_gettime(CLOCK_MONOTONIC, &ts); PJDLOG_ASSERT(error == 0); ts.tv_sec += timeout; error = pthread_cond_timedwait(cv, lock, &ts); #elif HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP ts.tv_sec = timeout; ts.tv_nsec = 0; error = pthread_cond_timedwait_relative_np(cv, lock, &ts); #else #error Neither pthread_condattr_setclock nor pthread_cond_timedwait_relative_np is available. #endif PJDLOG_ASSERT(error == 0 || error == ETIMEDOUT); return (error == ETIMEDOUT); } static __inline void cv_signal(pthread_cond_t *cv) { int error; error = pthread_cond_signal(cv); PJDLOG_ASSERT(error == 0); } static __inline void cv_broadcast(pthread_cond_t *cv) { int error; error = pthread_cond_broadcast(cv); PJDLOG_ASSERT(error == 0); } #endif /* !_SYNCH_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/token.l =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/token.l (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/token.l (revision 292449) @@ -1,84 +1,82 @@ %{ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/token.l#2 $ */ #include #include #include #ifndef HAVE_STRNDUP #include "strndup.h" #endif #include "auditdistd.h" #include "parse.h" #define SECTION_GLOBAL 0 #define SECTION_SENDER 1 #define SECTION_RECEIVER 2 int cursection; int depth; int lineno; #define DP do { } while (0) #define YY_DECL int yylex(void) %} %option noinput %option nounput %option noyywrap %% certfile { DP; return CERTFILE; } directory { DP; return DIRECTORY; } fingerprint { DP; return FINGERPRINT; } host { DP; return HOST; } keyfile { DP; return KEYFILE; } listen { DP; return LISTEN; } name { DP; return NAME; } password { DP; return PASSWORD; } pidfile { DP; return PIDFILE; } receiver { DP; return RECEIVER; } remote { DP; return REMOTE; } sender { DP; return SENDER; } source { DP; return SOURCE; } timeout { DP; return TIMEOUT; } [0-9]+ { DP; yylval.num = atoi(yytext); return NUM; } \"[a-zA-Z0-9_/ !@#\$%\^\&\*\(\)\+\=\|\;\?\,\.\[\]\-\:]*\" { DP; yylval.str = strndup(yytext + 1, strlen(yytext) - 2); return STR; } \{ { DP; depth++; return OB; } \} { DP; depth--; return CB; } #.*$ /* ignore comments */; \n { lineno++; } [ \t]+ /* ignore whitespace */; %% Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/trail.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/trail.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/trail.c (revision 292449) @@ -1,611 +1,609 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/trail.c#3 $ */ #include #include #include #include #include #include #include #include #include #include #include #include #ifndef HAVE_STRLCPY #include #endif #ifndef HAVE_FACCESSAT #include "faccessat.h" #endif #ifndef HAVE_FSTATAT #include "fstatat.h" #endif #ifndef HAVE_OPENAT #include "openat.h" #endif #ifndef HAVE_UNLINKAT #include "unlinkat.h" #endif #include "pjdlog.h" #include "trail.h" #define TRAIL_MAGIC 0x79a11 struct trail { int tr_magic; /* Path usually to /var/audit/dist/ directory. */ char tr_dirname[PATH_MAX]; /* Descriptor to td_dirname directory. */ DIR *tr_dirfp; /* Path to audit trail file. */ char tr_filename[PATH_MAX]; /* Descriptor to audit trail file. */ int tr_filefd; }; #define HALF_LEN 14 bool trail_is_not_terminated(const char *filename) { return (strcmp(filename + HALF_LEN, ".not_terminated") == 0); } bool trail_is_crash_recovery(const char *filename) { return (strcmp(filename + HALF_LEN, ".crash_recovery") == 0); } struct trail * trail_new(const char *dirname, bool create) { struct trail *trail; trail = calloc(1, sizeof(*trail)); if (strlcpy(trail->tr_dirname, dirname, sizeof(trail->tr_dirname)) >= sizeof(trail->tr_dirname)) { free(trail); pjdlog_error("Directory name too long (\"%s\").", dirname); errno = ENAMETOOLONG; return (NULL); } trail->tr_dirfp = opendir(dirname); if (trail->tr_dirfp == NULL) { if (create && errno == ENOENT) { if (mkdir(dirname, 0700) == -1) { pjdlog_errno(LOG_ERR, "Unable to create directory \"%s\"", dirname); free(trail); return (NULL); } /* TODO: Set directory ownership. */ } else { pjdlog_errno(LOG_ERR, "Unable to open directory \"%s\"", dirname); free(trail); return (NULL); } trail->tr_dirfp = opendir(dirname); if (trail->tr_dirfp == NULL) { pjdlog_errno(LOG_ERR, "Unable to open directory \"%s\"", dirname); free(trail); return (NULL); } } trail->tr_filefd = -1; trail->tr_magic = TRAIL_MAGIC; return (trail); } void trail_free(struct trail *trail) { PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); if (trail->tr_filefd != -1) trail_close(trail); closedir(trail->tr_dirfp); bzero(trail, sizeof(*trail)); trail->tr_magic = 0; trail->tr_filefd = -1; free(trail); } static uint8_t trail_type(DIR *dirfp, const char *filename) { struct stat sb; int dfd; PJDLOG_ASSERT(dirfp != NULL); dfd = dirfd(dirfp); PJDLOG_ASSERT(dfd >= 0); if (fstatat(dfd, filename, &sb, AT_SYMLINK_NOFOLLOW) == -1) { pjdlog_errno(LOG_ERR, "Unable to stat \"%s\"", filename); return (DT_UNKNOWN); } return (IFTODT(sb.st_mode)); } /* * Find trail file by first part of the name in case it was renamed. * First part of the trail file name never changes, but trail file * can be renamed when hosts are disconnected from .not_terminated * to .[0-9]{14} or to .crash_recovery. */ static bool trail_find(struct trail *trail) { struct dirent *dp; PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); PJDLOG_ASSERT(trail_is_not_terminated(trail->tr_filename)); rewinddir(trail->tr_dirfp); while ((dp = readdir(trail->tr_dirfp)) != NULL) { if (strncmp(dp->d_name, trail->tr_filename, HALF_LEN + 1) == 0) break; } if (dp == NULL) return (false); PJDLOG_VERIFY(strlcpy(trail->tr_filename, dp->d_name, sizeof(trail->tr_filename)) < sizeof(trail->tr_filename)); return (true); } /* * Open the given trail file and move pointer at the given offset, as this is * where receiver finished the last time. * If the file doesn't exist or the given offset is equal to the file size, * move to the next trail file. */ void trail_start(struct trail *trail, const char *filename, off_t offset) { struct stat sb; int dfd, fd; PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); PJDLOG_VERIFY(strlcpy(trail->tr_filename, filename, sizeof(trail->tr_filename)) < sizeof(trail->tr_filename)); trail->tr_filefd = -1; if (trail->tr_filename[0] == '\0') { PJDLOG_ASSERT(offset == 0); trail_next(trail); return; } dfd = dirfd(trail->tr_dirfp); PJDLOG_ASSERT(dfd >= 0); again: fd = openat(dfd, trail->tr_filename, O_RDONLY); if (fd == -1) { if (errno == ENOENT && trail_is_not_terminated(trail->tr_filename) && trail_find(trail)) { /* File was renamed. Retry with new name. */ pjdlog_debug(1, "Trail file was renamed since last connection to \"%s/%s\".", trail->tr_dirname, trail->tr_filename); goto again; } else if (errno == ENOENT) { /* File disappeared. */ pjdlog_debug(1, "File \"%s/%s\" doesn't exist.", trail->tr_dirname, trail->tr_filename); } else { pjdlog_errno(LOG_ERR, "Unable to open file \"%s/%s\", skipping", trail->tr_dirname, trail->tr_filename); } trail_next(trail); return; } if (fstat(fd, &sb) == -1) { pjdlog_errno(LOG_ERR, "Unable to stat file \"%s/%s\", skipping", trail->tr_dirname, trail->tr_filename); close(fd); trail_next(trail); return; } if (!S_ISREG(sb.st_mode)) { pjdlog_warning("File \"%s/%s\" is not a regular file, skipping.", trail->tr_dirname, trail->tr_filename); close(fd); trail_next(trail); return; } /* * We continue sending requested file if: * 1. It is not fully sent yet, or * 2. It is fully sent, but is not terminated, so new data can be * appended still, or * 3. It is fully sent but file name has changed. * * Note that we are fine if our .not_terminated or .crash_recovery file * is smaller than the one on the receiver side, as it is possible that * more data was send to the receiver than was safely stored on disk. * We accept .not_terminated only because auditdistd can start before * auditd manage to rename it to .crash_recovery. */ if (offset < sb.st_size || (offset >= sb.st_size && trail_is_not_terminated(trail->tr_filename)) || (offset >= sb.st_size && trail_is_not_terminated(filename) && trail_is_crash_recovery(trail->tr_filename))) { /* File was not fully send. Let's finish it. */ if (lseek(fd, offset, SEEK_SET) == -1) { pjdlog_errno(LOG_ERR, "Unable to move to offset %jd within file \"%s/%s\", skipping", (intmax_t)offset, trail->tr_dirname, trail->tr_filename); close(fd); trail_next(trail); return; } if (!trail_is_crash_recovery(trail->tr_filename)) { pjdlog_debug(1, "Restarting file \"%s/%s\" at offset %jd.", trail->tr_dirname, trail->tr_filename, (intmax_t)offset); } trail->tr_filefd = fd; return; } close(fd); if (offset > sb.st_size) { pjdlog_warning("File \"%s/%s\" shrinked, removing it.", trail->tr_dirname, trail->tr_filename); } else { pjdlog_debug(1, "File \"%s/%s\" is already sent, removing it.", trail->tr_dirname, trail->tr_filename); } /* Entire file is already sent or it shirnked, we can remove it. */ if (unlinkat(dfd, trail->tr_filename, 0) == -1) { pjdlog_errno(LOG_WARNING, "Unable to remove file \"%s/%s\"", trail->tr_dirname, trail->tr_filename); } trail_next(trail); } /* * Set next file in the trail->tr_dirname directory and open it for reading. */ void trail_next(struct trail *trail) { char curfile[PATH_MAX]; struct dirent *dp; int dfd; PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); PJDLOG_ASSERT(trail->tr_filefd == -1); again: curfile[0] = '\0'; rewinddir(trail->tr_dirfp); while ((dp = readdir(trail->tr_dirfp)) != NULL) { if (dp->d_name[0] < '0' || dp->d_name[0] > '9') continue; if (dp->d_type == DT_UNKNOWN) dp->d_type = trail_type(trail->tr_dirfp, dp->d_name); /* We are only interested in regular files, skip the rest. */ if (dp->d_type != DT_REG) { pjdlog_debug(1, "File \"%s/%s\" is not a regular file, skipping.", trail->tr_dirname, dp->d_name); continue; } /* Skip all files "greater" than curfile. */ if (curfile[0] != '\0' && strcmp(dp->d_name, curfile) > 0) continue; /* Skip all files "smaller" than the current trail_filename. */ if (trail->tr_filename[0] != '\0' && strcmp(dp->d_name, trail->tr_filename) <= 0) { continue; } PJDLOG_VERIFY(strlcpy(curfile, dp->d_name, sizeof(curfile)) < sizeof(curfile)); } if (curfile[0] == '\0') { /* * There are no new trail files, so we return. * We don't clear trail_filename string, to know where to * start when new file appears. */ PJDLOG_ASSERT(trail->tr_filefd == -1); pjdlog_debug(1, "No new trail files."); return; } PJDLOG_VERIFY(strlcpy(trail->tr_filename, curfile, sizeof(trail->tr_filename)) < sizeof(trail->tr_filename)); dfd = dirfd(trail->tr_dirfp); PJDLOG_ASSERT(dfd >= 0); trail->tr_filefd = openat(dfd, trail->tr_filename, O_RDONLY); if (trail->tr_filefd == -1) { pjdlog_errno(LOG_ERR, "Unable to open file \"%s/%s\", skipping", trail->tr_dirname, trail->tr_filename); goto again; } pjdlog_debug(1, "Found next trail file: \"%s/%s\".", trail->tr_dirname, trail->tr_filename); } /* * Close current trial file. */ void trail_close(struct trail *trail) { PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); PJDLOG_ASSERT(trail->tr_filefd >= 0); PJDLOG_ASSERT(trail->tr_filename[0] != '\0'); PJDLOG_VERIFY(close(trail->tr_filefd) == 0); trail->tr_filefd = -1; } /* * Reset trail state. Used when connection is disconnected and we will * need to start over after reconnect. Trail needs to be already closed. */ void trail_reset(struct trail *trail) { PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); PJDLOG_ASSERT(trail->tr_filefd == -1); trail->tr_filename[0] = '\0'; } /* * Unlink current trial file. */ void trail_unlink(struct trail *trail, const char *filename) { int dfd; PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); PJDLOG_ASSERT(filename != NULL); PJDLOG_ASSERT(filename[0] != '\0'); dfd = dirfd(trail->tr_dirfp); PJDLOG_ASSERT(dfd >= 0); if (unlinkat(dfd, filename, 0) == -1) { pjdlog_errno(LOG_ERR, "Unable to remove \"%s/%s\"", trail->tr_dirname, filename); } else { pjdlog_debug(1, "Trail file \"%s/%s\" removed.", trail->tr_dirname, filename); } } /* * Return true if we should switch to next trail file. * We don't switch if our file name ends with ".not_terminated" and it * exists (ie. wasn't renamed). */ bool trail_switch(struct trail *trail) { char filename[PATH_MAX]; int fd; PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); PJDLOG_ASSERT(trail->tr_filefd >= 0); if (!trail_is_not_terminated(trail->tr_filename)) return (true); fd = dirfd(trail->tr_dirfp); PJDLOG_ASSERT(fd >= 0); if (faccessat(fd, trail->tr_filename, F_OK, 0) == 0) return (false); if (errno != ENOENT) { pjdlog_errno(LOG_ERR, "Unable to access file \"%s/%s\"", trail->tr_dirname, trail->tr_filename); } strlcpy(filename, trail->tr_filename, sizeof(filename)); if (!trail_find(trail)) { pjdlog_error("Trail file \"%s/%s\" disappeared.", trail->tr_dirname, trail->tr_filename); return (true); } pjdlog_debug(1, "Trail file \"%s/%s\" was renamed to \"%s/%s\".", trail->tr_dirname, filename, trail->tr_dirname, trail->tr_filename); return (true); } const char * trail_filename(const struct trail *trail) { PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); return (trail->tr_filename); } int trail_filefd(const struct trail *trail) { PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); return (trail->tr_filefd); } int trail_dirfd(const struct trail *trail) { PJDLOG_ASSERT(trail->tr_magic == TRAIL_MAGIC); return (dirfd(trail->tr_dirfp)); } /* * Find the last file in the directory opened under dirfp. */ void trail_last(DIR *dirfp, char *filename, size_t filenamesize) { char curfile[PATH_MAX]; struct dirent *dp; PJDLOG_ASSERT(dirfp != NULL); curfile[0] = '\0'; rewinddir(dirfp); while ((dp = readdir(dirfp)) != NULL) { if (dp->d_name[0] < '0' || dp->d_name[0] > '9') continue; if (dp->d_type == DT_UNKNOWN) dp->d_type = trail_type(dirfp, dp->d_name); /* We are only interested in regular files, skip the rest. */ if (dp->d_type != DT_REG) continue; /* Skip all files "greater" than curfile. */ if (curfile[0] != '\0' && strcmp(dp->d_name, curfile) < 0) continue; PJDLOG_VERIFY(strlcpy(curfile, dp->d_name, sizeof(curfile)) < sizeof(curfile)); } if (curfile[0] == '\0') { /* * There are no trail files, so we return. */ pjdlog_debug(1, "No trail files."); bzero(filename, filenamesize); return; } PJDLOG_VERIFY(strlcpy(filename, curfile, filenamesize) < filenamesize); pjdlog_debug(1, "Found the most recent trail file: \"%s\".", filename); } /* * Check if the given file name is a valid audit trail file name. * Possible names: * 20120106132657.20120106132805 * 20120106132657.not_terminated * 20120106132657.crash_recovery * If two names are given, check if the first name can be renamed * to the second name. When renaming, first part of the name has * to be identical and only the following renames are valid: * 20120106132657.not_terminated -> 20120106132657.20120106132805 * 20120106132657.not_terminated -> 20120106132657.crash_recovery */ bool trail_validate_name(const char *srcname, const char *dstname) { int i; PJDLOG_ASSERT(srcname != NULL); if (strlen(srcname) != 2 * HALF_LEN + 1) return (false); if (srcname[HALF_LEN] != '.') return (false); for (i = 0; i < HALF_LEN; i++) { if (srcname[i] < '0' || srcname[i] > '9') return (false); } for (i = HALF_LEN + 1; i < 2 * HALF_LEN - 1; i++) { if (srcname[i] < '0' || srcname[i] > '9') break; } if (i < 2 * HALF_LEN - 1 && strcmp(srcname + HALF_LEN + 1, "not_terminated") != 0 && strcmp(srcname + HALF_LEN + 1, "crash_recovery") != 0) { return (false); } if (dstname == NULL) return (true); /* We tolarate if both names are identical. */ if (strcmp(srcname, dstname) == 0) return (true); /* We can only rename not_terminated files. */ if (strcmp(srcname + HALF_LEN + 1, "not_terminated") != 0) return (false); if (strlen(dstname) != 2 * HALF_LEN + 1) return (false); if (strncmp(srcname, dstname, HALF_LEN + 1) != 0) return (false); for (i = HALF_LEN + 1; i < 2 * HALF_LEN - 1; i++) { if (dstname[i] < '0' || dstname[i] > '9') break; } if (i < 2 * HALF_LEN - 1 && strcmp(dstname + HALF_LEN + 1, "crash_recovery") != 0) { return (false); } return (true); } int trail_name_compare(const char *name0, const char *name1) { int ret; ret = strcmp(name0, name1); if (ret == 0) return (TRAIL_IDENTICAL); if (strncmp(name0, name1, HALF_LEN + 1) == 0) return (TRAIL_RENAMED); return (ret < 0 ? TRAIL_OLDER : TRAIL_NEWER); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/trail.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/trail.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/trail.h (revision 292449) @@ -1,62 +1,60 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/trail.h#1 $ */ #ifndef _AUDITDISTD_TRAIL_H_ #define _AUDITDISTD_TRAIL_H_ #include #include /* off_t */ #define TRAIL_IDENTICAL 0 #define TRAIL_RENAMED 1 #define TRAIL_OLDER 2 #define TRAIL_NEWER 3 struct trail; struct trail *trail_new(const char *dirname, bool create); void trail_free(struct trail *trail); bool trail_is_not_terminated(const char *filename); bool trail_is_crash_recovery(const char *filename); void trail_start(struct trail *trail, const char *filename, off_t offset); void trail_next(struct trail *trail); void trail_close(struct trail *trail); void trail_reset(struct trail *trail); void trail_unlink(struct trail *trail, const char *filename); bool trail_switch(struct trail *trail); const char *trail_filename(const struct trail *trail); int trail_filefd(const struct trail *trail); int trail_dirfd(const struct trail *trail); void trail_last(DIR *dirfp, char *filename, size_t filenamesize); bool trail_validate_name(const char *srcname, const char *dstname); int trail_name_compare(const char *name0, const char *name1); #endif /* !_AUDITDISTD_TRAIL_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/unlinkat.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/unlinkat.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditdistd/unlinkat.h (revision 292449) @@ -1,68 +1,66 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/unlinkat.h#1 $ */ #ifndef _UNLINKAT_H_ #define _UNLINKAT_H_ #include #include #define AT_REMOVEDIR 0x01 static int unlinkat(int fd, const char *path, int flag) { int cfd, error, ret; cfd = open(".", O_RDONLY | O_DIRECTORY); if (cfd == -1) return (-1); if (fchdir(fd) == -1) { error = errno; (void)close(cfd); errno = error; return (-1); } if (flag == AT_REMOVEDIR) ret = rmdir(path); else ret = unlink(path); error = errno; (void)fchdir(cfd); (void)close(cfd); errno = error; return (ret); } #endif /* !_UNLINKAT_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditfilterd/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditfilterd/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditfilterd/Makefile.am (revision 292449) @@ -1,14 +1,10 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/bin/auditfilterd/Makefile.am#4 $ -## - if USE_NATIVE_INCLUDES INCLUDES = -I$(top_builddir) -I$(top_srcdir) else INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys endif sbin_PROGRAMS = auditfilterd auditfilterd_SOURCES = auditfilterd_conf.c auditfilterd.c auditfilterd_LDADD = $(top_builddir)/libbsm/libbsm.la man8_MANS = auditfilterd.8 Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditfilterd/auditfilterd.8 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditfilterd/auditfilterd.8 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditfilterd/auditfilterd.8 (revision 292449) @@ -1,86 +1,84 @@ .\"- .\" Copyright (c) 2006 Robert N. M. Watson .\" 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/bin/auditfilterd/auditfilterd.8#6 $ -.\" .Dd October 3, 2006 .Dt AUDITFILTERD 8 .Os .Sh NAME .Nm auditfilterd .Nd audit filter daemon .Sh SYNOPSIS .Nm .Op Fl d .Op Fl c Ar conffile .Op Fl p Ar pipefile .Op Fl t Ar trailfile .Sh DESCRIPTION The .Nm daemon is an extensible audit event monitoring daemon, allowing pluggable modules to track audit events from a live audit source. It is configured using the audit_filter configuration file. The source can either be a pipe or a file. .Pp The options are as follows: .Bl -tag -width indent .It Fl c Ar conffile Specify an alternative configuration file. .It Fl d Starts the daemon in debug mode \[em] it will not daemonize. .It Fl p Ar pipefile Specify a pipe as an alternative source of audit event records. Default is .Pa /dev/auditpipe . .It Fl t Ar trailfile Specify a file as an alternative source of audit event records. .El .Sh FILES .Bl -tag -width ".Pa /etc/security/audit_filterd" -compact .It Pa /etc/security/audit_filterd Default configuration file for .Nm . .It Pa /dev/auditpipe Default audit record source for .Nm . .El .Sh SEE ALSO .Xr audit 8 , .Xr auditd 8 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS The .Nm daemon and audit filter APIs were created by .An Robert Watson . .Sh BUGS .Nm is experimental, and should not be relied on in production. APIs and services it offers can and will change in future OpenBSM releases. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditfilterd/auditfilterd.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditfilterd/auditfilterd.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditfilterd/auditfilterd.c (revision 292449) @@ -1,354 +1,352 @@ /*- * Copyright (c) 2006 Robert N. M. Watson * All rights reserved. * * This software was developed by Robert Watson for the TrustedBSD Project. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditfilterd/auditfilterd.c#13 $ */ /* * Main file for the audit filter daemon, which presents audit records to a * set of run-time registered loadable modules. This is the main event loop * of the daemon, which handles starting up, waiting for records, and * presenting records to configured modules. auditfilterd_conf.c handles the * reading and management of the configuration, module list and module state, * etc. */ #include #include #include #include #ifdef HAVE_FULL_QUEUE_H #include #else #include #endif #ifndef HAVE_CLOCK_GETTIME #include #endif #include #include #include #include #include #include #include #include #include #include "auditfilterd.h" /* * Global list of registered filters. */ struct auditfilter_module_list filter_list; /* * Configuration and signal->main flags. */ int debug; /* Debugging mode requested, don't detach. */ int reread_config; /* SIGHUP has been received. */ int quit; /* SIGQUIT/TERM/INT has been received. */ static void usage(void) { fprintf(stderr, "auditfilterd [-d] [-c conffile] [-p pipefile]" " [-t trailfile]\n"); fprintf(stderr, " -c Specify configuration file (default: %s)\n", AUDITFILTERD_CONFFILE); fprintf(stderr, " -d Debugging mode, don't daemonize\n"); fprintf(stderr, " -p Specify pipe file (default: %s)\n", AUDITFILTERD_PIPEFILE); fprintf(stderr, " -t Specify audit trail file (default: none)\n"); exit(-1); } static void auditfilterd_init(void) { TAILQ_INIT(&filter_list); } static void signal_handler(int signum) { switch (signum) { case SIGHUP: reread_config++; break; case SIGINT: case SIGTERM: case SIGQUIT: quit++; break; } } /* * Present raw BSM to a set of registered and interested filters. */ static void present_rawrecord(struct timespec *ts, u_char *data, u_int len) { struct auditfilter_module *am; TAILQ_FOREACH(am, &filter_list, am_list) { if (am->am_rawrecord != NULL) (am->am_rawrecord)(am, ts, data, len); } } /* - * Parse the BSM into a set of tokens, which will be pased to registered + * Parse the BSM into a set of tokens, which will be passed to registered * and interested filters. */ #define MAX_TOKENS 128 /* Maximum tokens we handle per record. */ static void present_tokens(struct timespec *ts, u_char *data, u_int len) { struct auditfilter_module *am; tokenstr_t tokens[MAX_TOKENS]; u_int bytesread; int tokencount; tokencount = 0; while (bytesread < len) { if (au_fetch_tok(&tokens[tokencount], data + bytesread, len - bytesread) == -1) break; bytesread += tokens[tokencount].len; tokencount++; } TAILQ_FOREACH(am, &filter_list, am_list) { if (am->am_record != NULL) (am->am_record)(am, ts, tokencount, tokens); } } /* * The main loop spins pulling records out of the record source and passing * them to modules for processing. */ static void mainloop_file(const char *conffile, const char *trailfile, FILE *trail_fp) { struct timespec ts; FILE *conf_fp; u_char *buf; int reclen; while (1) { /* * On SIGHUP, we reread the configuration file and reopen * the trail file. */ if (reread_config) { reread_config = 0; warnx("rereading configuration"); conf_fp = fopen(conffile, "r"); if (conf_fp == NULL) err(-1, "%s", conffile); auditfilterd_conf(conffile, conf_fp); fclose(conf_fp); fclose(trail_fp); trail_fp = fopen(trailfile, "r"); if (trail_fp == NULL) err(-1, "%s", trailfile); } if (quit) { warnx("quitting"); break; } /* * For now, be relatively unrobust about incomplete records, * but in the future will want to do better. Need to look * more at the right blocking and signal behavior here. */ reclen = au_read_rec(trail_fp, &buf); if (reclen == -1) continue; if (clock_gettime(CLOCK_REALTIME, &ts) < 0) err(-1, "clock_gettime"); present_rawrecord(&ts, buf, reclen); present_tokens(&ts, buf, reclen); free(buf); } } /* * The main loop spins pulling records out of the record source and passing * them to modules for processing. This version of the function accepts * discrete record input from a file descriptor, as opposed to buffered input * from a file stream. */ static void mainloop_pipe(const char *conffile, const char *pipefile __unused, int pipe_fd) { u_char record[MAX_AUDIT_RECORD_SIZE]; struct timespec ts; FILE *conf_fp; int reclen; while (1) { /* * On SIGHUP, we reread the configuration file. Unlike with * a trail file, we don't reopen the pipe, as we don't want * to miss records which will be flushed if we do. */ if (reread_config) { reread_config = 0; warnx("rereading configuration"); conf_fp = fopen(conffile, "r"); if (conf_fp == NULL) err(-1, "%s", conffile); auditfilterd_conf(conffile, conf_fp); fclose(conf_fp); } if (quit) { warnx("quitting"); break; } /* * For now, be relatively unrobust about incomplete records, * but in the future will want to do better. Need to look * more at the right blocking and signal behavior here. */ reclen = read(pipe_fd, record, MAX_AUDIT_RECORD_SIZE); if (reclen < 0) continue; if (clock_gettime(CLOCK_REALTIME, &ts) < 0) err(-1, "clock_gettime"); present_rawrecord(&ts, record, reclen); present_tokens(&ts, record, reclen); } } int main(int argc, char *argv[]) { const char *pipefile, *trailfile, *conffile; FILE *trail_fp, *conf_fp; struct stat sb; int pipe_fd; int ch; conffile = AUDITFILTERD_CONFFILE; trailfile = NULL; pipefile = NULL; while ((ch = getopt(argc, argv, "c:dp:t:")) != -1) { switch (ch) { case 'c': conffile = optarg; break; case 'd': debug++; break; case 't': if (trailfile != NULL || pipefile != NULL) usage(); trailfile = optarg; break; case 'p': if (pipefile != NULL || trailfile != NULL) usage(); pipefile = optarg; break; default: usage(); } } argc -= optind; argv += optind; if (argc != 0) usage(); /* * We allow only one of a pipe or a trail to be used. If none is * specified, we provide a default pipe path. */ if (pipefile == NULL && trailfile == NULL) pipefile = AUDITFILTERD_PIPEFILE; if (pipefile != NULL) { pipe_fd = open(pipefile, O_RDONLY); if (pipe_fd < 0) err(-1, "open:%s", pipefile); if (fstat(pipe_fd, &sb) < 0) err(-1, "stat: %s", pipefile); if (!S_ISCHR(sb.st_mode)) errx(-1, "fstat: %s not device", pipefile); } else { trail_fp = fopen(trailfile, "r"); if (trail_fp == NULL) err(-1, "%s", trailfile); } conf_fp = fopen(conffile, "r"); if (conf_fp == NULL) err(-1, "%s", conffile); auditfilterd_init(); if (auditfilterd_conf(conffile, conf_fp) < 0) exit(-1); fclose(conf_fp); if (!debug) { if (daemon(0, 0) < 0) err(-1, "daemon"); } signal(SIGHUP, signal_handler); signal(SIGINT, signal_handler); signal(SIGQUIT, signal_handler); signal(SIGTERM, signal_handler); if (pipefile != NULL) mainloop_pipe(conffile, pipefile, pipe_fd); else mainloop_file(conffile, trailfile, trail_fp); auditfilterd_conf_shutdown(); return (0); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditfilterd/auditfilterd.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditfilterd/auditfilterd.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditfilterd/auditfilterd.h (revision 292449) @@ -1,79 +1,77 @@ /*- * Copyright (c) 2006 Robert N. M. Watson * All rights reserved. * * This software was developed by Robert Watson for the TrustedBSD Project. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditfilterd/auditfilterd.h#5 $ */ #define AUDITFILTERD_CONFFILE "/etc/security/audit_filter" #define AUDITFILTERD_PIPEFILE "/dev/auditpipe" /* * Limit on the number of arguments that can appear in an audit_filterd * configuration line. */ #define AUDITFILTERD_CONF_MAXARGS 256 /* * Data structure description each instantiated module. */ struct auditfilter_module { /* * Fields from configuration file and dynamic linker. */ char *am_modulename; char *am_arg_buffer; int am_argc; char **am_argv; void *am_dlhandle; /* * Fields provided by or extracted from the module. */ void *am_cookie; audit_filter_attach_t am_attach; audit_filter_reinit_t am_reinit; audit_filter_record_t am_record; audit_filter_rawrecord_t am_rawrecord; audit_filter_detach_t am_detach; /* * Fields for maintaining the list of modules. */ TAILQ_ENTRY(auditfilter_module) am_list; }; TAILQ_HEAD(auditfilter_module_list, auditfilter_module); /* * List of currently registered modules. */ extern struct auditfilter_module_list filter_list; /* * Function definitions. */ int auditfilterd_conf(const char *filename, FILE *fp); void auditfilterd_conf_shutdown(void); Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditfilterd/auditfilterd_conf.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditfilterd/auditfilterd_conf.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditfilterd/auditfilterd_conf.c (revision 292449) @@ -1,513 +1,511 @@ /*- * Copyright (c) 2006 Robert N. M. Watson * All rights reserved. * * This software was developed by Robert Watson for the TrustedBSD Project. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditfilterd/auditfilterd_conf.c#5 $ */ /* * Configuration file parser for auditfilterd. The configuration file is a * very simple format, similar to other BSM configuration files, consisting * of configuration entries of one line each. The configuration function is * aware of previous runs, and will update the current configuration as * needed. * * Modules are in one of two states: attached, or detached. If attach fails, * detach is not called because it was not attached. If a module is attached * and a call to its reinit method fails, we will detach it. * * Modules are passed a (void *) reference to their configuration state so * that they may pass this into any common APIs we provide which may rely on * that state. Currently, the only such API is the cookie API, which allows * per-instance state to be maintained by a module. In the future, this will * also be used to support per-instance preselection state. */ #include #include #ifdef HAVE_FULL_QUEUE_H #include #else #include #endif #include #include #include #include #include #include #include #include #include #include "auditfilterd.h" /* * Free an individual auditfilter_module structure. Will not shut down the * module, just frees the memory. Does so conditional on pointers being * non-NULL so that it can be used on partially allocated structures. */ static void auditfilter_module_free(struct auditfilter_module *am) { if (am->am_modulename != NULL) free(am->am_modulename); if (am->am_arg_buffer != NULL) free(am->am_arg_buffer); if (am->am_argv != NULL) free(am->am_argv); } /* * Free all memory associated with an auditfilter_module list. Does not * dlclose() or shut down the modules, just free the memory. Use * auditfilter_module_list_detach() for that, if required. */ static void auditfilter_module_list_free(struct auditfilter_module_list *list) { struct auditfilter_module *am; while (!(TAILQ_EMPTY(list))) { am = TAILQ_FIRST(list); TAILQ_REMOVE(list, am, am_list); auditfilter_module_free(am); } } /* * Detach an attached module from an auditfilter_module structure. Does not * free the data structure itself. */ static void auditfilter_module_detach(struct auditfilter_module *am) { if (am->am_detach != NULL) am->am_detach(am); am->am_cookie = NULL; (void)dlclose(am->am_dlhandle); am->am_dlhandle = NULL; } /* * Walk an auditfilter_module list, detaching each module. Intended to be * combined with auditfilter_module_list_free(). */ static void auditfilter_module_list_detach(struct auditfilter_module_list *list) { struct auditfilter_module *am; TAILQ_FOREACH(am, list, am_list) auditfilter_module_detach(am); } /* * Given a filled out auditfilter_module, use dlopen() and dlsym() to attach * the module. If we fail, leave fields in the state we found them. * * XXXRW: Need a better way to report errors. */ static int auditfilter_module_attach(struct auditfilter_module *am) { am->am_dlhandle = dlopen(am->am_modulename, RTLD_NOW); if (am->am_dlhandle == NULL) { warnx("auditfilter_module_attach: %s: %s", am->am_modulename, dlerror()); return (-1); } /* * Not implementing these is not considered a failure condition, * although we might want to consider warning if obvious stuff is * not implemented, such as am_record. */ am->am_attach = dlsym(am->am_dlhandle, AUDIT_FILTER_ATTACH_STRING); am->am_reinit = dlsym(am->am_dlhandle, AUDIT_FILTER_REINIT_STRING); am->am_record = dlsym(am->am_dlhandle, AUDIT_FILTER_RECORD_STRING); am->am_rawrecord = dlsym(am->am_dlhandle, AUDIT_FILTER_RAWRECORD_STRING); am->am_detach = dlsym(am->am_dlhandle, AUDIT_FILTER_DETACH_STRING); if (am->am_attach != NULL) { if (am->am_attach(am, am->am_argc, am->am_argv) != AUDIT_FILTER_SUCCESS) { warnx("auditfilter_module_attach: %s: failed", am->am_modulename); dlclose(am->am_dlhandle); am->am_dlhandle = NULL; am->am_cookie = NULL; am->am_attach = NULL; am->am_reinit = NULL; am->am_record = NULL; am->am_rawrecord = NULL; am->am_detach = NULL; return (-1); } } return (0); } /* * When the arguments for a module are changed, we notify the module through * a call to its reinit method, if any. Return 0 on success, or -1 on * failure. */ static int auditfilter_module_reinit(struct auditfilter_module *am) { if (am->am_reinit == NULL) return (0); if (am->am_reinit(am, am->am_argc, am->am_argv) != AUDIT_FILTER_SUCCESS) { warnx("auditfilter_module_reinit: %s: failed", am->am_modulename); return (-1); } return (0); } /* * Given a configuration line, generate an auditfilter_module structure that * describes it; caller will not pass comments in, so they are not looked * for. Do not attempt to instantiate it. Will destroy the contents of * 'buffer'. * * Configuration lines consist of two parts: the module name and arguments * separated by a ':', and then a ','-delimited list of arguments. * * XXXRW: Need to decide where to send the warning output -- stderr for now. */ struct auditfilter_module * auditfilter_module_parse(const char *filename, int linenumber, char *buffer) { char *arguments, *module, **ap; struct auditfilter_module *am; am = malloc(sizeof(*am)); if (am == NULL) { warn("auditfilter_module_parse: %s:%d", filename, linenumber); return (NULL); } bzero(am, sizeof(*am)); /* * First, break out the module and arguments strings. We look for * one extra argument to make sure there are no more :'s in the line. * That way, we prevent modules from using argument strings that, in * the future, may cause problems for adding additional columns. */ arguments = buffer; module = strsep(&arguments, ":"); if (module == NULL || arguments == NULL) { warnx("auditfilter_module_parse: %s:%d: parse error", filename, linenumber); return (NULL); } am->am_modulename = strdup(module); if (am->am_modulename == NULL) { warn("auditfilter_module_parse: %s:%d", filename, linenumber); auditfilter_module_free(am); return (NULL); } am->am_arg_buffer = strdup(buffer); if (am->am_arg_buffer == NULL) { warn("auditfilter_module_parse: %s:%d", filename, linenumber); auditfilter_module_free(am); return (NULL); } /* * Now, break out the arguments string into a series of arguments. * This is a bit more complicated, and requires cleanup if things go * wrong. */ am->am_argv = malloc(sizeof(char *) * AUDITFILTERD_CONF_MAXARGS); if (am->am_argv == NULL) { warn("auditfilter_module_parse: %s:%d", filename, linenumber); auditfilter_module_free(am); return (NULL); } bzero(am->am_argv, sizeof(char *) * AUDITFILTERD_CONF_MAXARGS); am->am_argc = 0; for (ap = am->am_argv; (*ap = strsep(&arguments, " \t")) != NULL;) { if (**ap != '\0') { am->am_argc++; if (++ap >= &am->am_argv[AUDITFILTERD_CONF_MAXARGS]) break; } } if (ap >= &am->am_argv[AUDITFILTERD_CONF_MAXARGS]) { warnx("auditfilter_module_parse: %s:%d: too many arguments", filename, linenumber); auditfilter_module_free(am); return (NULL); } return (am); } /* * Read a configuration file, and populate 'list' with the configuration * lines. Does not attempt to instantiate the configuration, just read it * into a useful set of data structures. */ static int auditfilterd_conf_read(const char *filename, FILE *fp, struct auditfilter_module_list *list) { int error, linenumber, syntaxerror; struct auditfilter_module *am; char buffer[LINE_MAX]; syntaxerror = 0; linenumber = 0; while (!feof(fp) && !ferror(fp)) { if (fgets(buffer, LINE_MAX, fp) == NULL) break; linenumber++; if (buffer[0] == '#' || strlen(buffer) < 1) continue; buffer[strlen(buffer)-1] = '\0'; am = auditfilter_module_parse(filename, linenumber, buffer); if (am == NULL) { syntaxerror = 1; break; } TAILQ_INSERT_HEAD(list, am, am_list); } /* * File I/O error. */ if (ferror(fp)) { error = errno; auditfilter_module_list_free(list); errno = error; return (-1); } /* * Syntax error. */ if (syntaxerror) { auditfilter_module_list_free(list); errno = EINVAL; return (-1); } return (0); } /* * Apply changes necessary to bring a new configuration into force. The new * configuration data is passed in, and the current configuration is updated * to match it. The contents of 'list' are freed or otherwise disposed of * before return. * * The algorithms here are not very efficient, but this is an infrequent * operation on very short lists. */ static void auditfilterd_conf_apply(struct auditfilter_module_list *list) { struct auditfilter_module *am1, *am2, *am_tmp; int argc_tmp, found; char **argv_tmp; /* * First, remove remove and detach any entries that appear in the * current configuration, but not the new configuration. */ TAILQ_FOREACH_SAFE(am1, &filter_list, am_list, am_tmp) { found = 0; TAILQ_FOREACH(am2, list, am_list) { if (strcmp(am1->am_modulename, am2->am_modulename) == 0) { found = 1; break; } } if (found) continue; /* * am1 appears in filter_list, but not the new list, detach * and free the module. */ warnx("detaching module %s", am1->am_modulename); TAILQ_REMOVE(&filter_list, am1, am_list); auditfilter_module_detach(am1); auditfilter_module_free(am1); } /* * Next, update the configuration of any modules that appear in both * lists. We do this by swapping the two argc and argv values and * freeing the new one, rather than detaching the old one and * attaching the new one. That way module state is preserved. */ TAILQ_FOREACH(am1, &filter_list, am_list) { found = 0; TAILQ_FOREACH(am2, list, am_list) { if (strcmp(am1->am_modulename, am2->am_modulename) == 0) { found = 1; break; } } if (!found) continue; /* * Swap the arguments. */ argc_tmp = am1->am_argc; argv_tmp = am1->am_argv; am1->am_argc = am2->am_argc; am1->am_argv = am2->am_argv; am2->am_argc = argc_tmp; am2->am_argv = argv_tmp; /* * The reinit is a bit tricky: if reinit fails, we actually * remove the old entry and detach that, as we don't allow * running modules to be out of sync with the configuration * file. */ warnx("reiniting module %s", am1->am_modulename); if (auditfilter_module_reinit(am1) != 0) { warnx("reinit failed for module %s, detaching", am1->am_modulename); TAILQ_REMOVE(&filter_list, am1, am_list); auditfilter_module_detach(am1); auditfilter_module_free(am1); } /* * Free the entry from the new list, which will discard the * old arguments. No need to detach, as it was never * attached in the first place. */ TAILQ_REMOVE(list, am2, am_list); auditfilter_module_free(am2); } /* * Finally, attach any new entries that don't appear in the old * configuration, and if they attach successfully, move them to the * real configuration list. */ TAILQ_FOREACH(am1, list, am_list) { found = 0; TAILQ_FOREACH(am2, &filter_list, am_list) { if (strcmp(am1->am_modulename, am2->am_modulename) == 0) { found = 1; break; } } if (found) continue; /* * Attach the entry. If it succeeds, add to filter_list, * otherwise, free. No need to detach if attach failed. */ warnx("attaching module %s", am1->am_modulename); TAILQ_REMOVE(list, am1, am_list); if (auditfilter_module_attach(am1) != 0) { warnx("attaching module %s failed", am1->am_modulename); auditfilter_module_free(am1); } else TAILQ_INSERT_HEAD(&filter_list, am1, am_list); } if (TAILQ_FIRST(list) != NULL) warnx("auditfilterd_conf_apply: new list not empty\n"); } /* * Read the new configuration file into a local list. If the configuration * file is parsed OK, then apply the changes. */ int auditfilterd_conf(const char *filename, FILE *fp) { struct auditfilter_module_list list; TAILQ_INIT(&list); if (auditfilterd_conf_read(filename, fp, &list) < 0) return (-1); auditfilterd_conf_apply(&list); return (0); } /* * Detach and free all active filter modules for daemon shutdown. */ void auditfilterd_conf_shutdown(void) { auditfilter_module_list_detach(&filter_list); auditfilter_module_list_free(&filter_list); } /* * APIs to allow modules to query and set their per-instance cookie. */ void audit_filter_getcookie(void *instance, void **cookie) { struct auditfilter_module *am; am = (struct auditfilter_module *)instance; *cookie = am->am_cookie; } void audit_filter_setcookie(void *instance, void *cookie) { struct auditfilter_module *am; am = (struct auditfilter_module *)instance; am->am_cookie = cookie; } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditreduce/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditreduce/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditreduce/Makefile.am (revision 292449) @@ -1,14 +1,10 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/bin/auditreduce/Makefile.am#4 $ -## - if USE_NATIVE_INCLUDES INCLUDES = -I$(top_builddir) -I$(top_srcdir) else INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys endif sbin_PROGRAMS = auditreduce auditreduce_SOURCES = auditreduce.c auditreduce_LDADD = $(top_builddir)/libbsm/libbsm.la man1_MANS = auditreduce.1 Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditreduce/auditreduce.1 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditreduce/auditreduce.1 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditreduce/auditreduce.1 (revision 292449) @@ -1,197 +1,195 @@ .\" Copyright (c) 2004 Apple Inc. .\" 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR .\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/bin/auditreduce/auditreduce.1#18 $ -.\" .Dd January 24, 2004 .Dt AUDITREDUCE 1 .Os .Sh NAME .Nm auditreduce .Nd "select records from audit trail files" .Sh SYNOPSIS .Nm .Op Fl A .Op Fl a Ar YYYYMMDD Ns Op Ar HH Ns Op Ar MM Ns Op Ar SS .Op Fl b Ar YYYYMMDD Ns Op Ar HH Ns Op Ar MM Ns Op Ar SS .Op Fl c Ar flags .Op Fl d Ar YYYYMMDD .Op Fl e Ar euid .Op Fl f Ar egid .Op Fl g Ar rgid .Op Fl j Ar id .Op Fl m Ar event .Op Fl o Ar object Ns = Ns Ar value .Op Fl r Ar ruid .Op Fl u Ar auid .Op Fl v .Op Ar .Sh DESCRIPTION The .Nm utility selects records from the audit trail files based on the specified criteria. Matching audit records are printed to the standard output in their raw binary form. If no .Ar file argument is specified, the standard input is used by default. Use the .Xr praudit 1 utility to print the selected audit records in human-readable form. .Pp The options are as follows: .Bl -tag -width indent .It Fl A Select all records. .It Fl a Ar YYYYMMDD Ns Op Ar HH Ns Op Ar MM Ns Op Ar SS Select records that occurred after or on the given datetime. .It Fl b Ar YYYYMMDD Ns Op Ar HH Ns Op Ar MM Ns Op Ar SS Select records that occurred before the given datetime. .It Fl c Ar flags Select records matching the given audit classes specified as a comma separated list of audit flags. See .Xr audit_control 5 for a description of audit flags. .It Fl d Ar YYYYMMDD Select records that occurred on a given date. This option cannot be used with .Fl a or .Fl b . .It Fl e Ar euid Select records with the given effective user ID or name. .It Fl f Ar egid Select records with the given effective group ID or name. .It Fl g Ar rgid Select records with the given real group ID or name. .It Fl j Ar id Select records having a subject token with matching ID, where ID is a process ID. .It Fl m Ar event Select records with the given event name or number. This option can be used more then once to select records of multiple event types. See .Xr audit_event 5 for a description of audit event names and numbers. .It Fl o Ar object Ns = Ns Ar value .Bl -tag -width ".Cm msgqid" .It Cm file Select records containing path tokens, where the pathname matches one of the comma delimited extended regular expression contained in given specification. Regular expressions which are prefixed with a tilde .Pq Ql ~ are excluded from the search results. These extended regular expressions are processed from left to right, and a path will either be selected or deslected based on the first match. .Pp Since commas are used to delimit the regular expressions, a backslash .Pq Ql \e character should be used to escape the comma if it is a part of the search pattern. .It Cm msgqid Select records containing the given message queue ID. .It Cm pid Select records containing the given process ID. .It Cm semid Select records containing the given semaphore ID. .It Cm shmid Select records containing the given shared memory ID. .El .It Fl r Ar ruid Select records with the given real user ID or name. .It Fl u Ar auid Select records with the given audit ID. .It Fl v Invert sense of matching, to select records that do not match. .El .Sh EXAMPLES To select all records associated with effective user ID root from the audit log .Pa /var/audit/20031016184719.20031017122634 : .Bd -literal -offset indent auditreduce -e root \e /var/audit/20031016184719.20031017122634 .Ed .Pp To select all .Xr setlogin 2 events from that log: .Bd -literal -offset indent auditreduce -m AUE_SETLOGIN \e /var/audit/20031016184719.20031017122634 .Ed .Pp Output from the above command lines will typically be piped to a new trail file, or via standard output to the .Xr praudit 1 command. .Pp Select all records containing a path token where the pathname contains .Pa /etc/master.passwd : .Bd -literal -offset indent auditreduce -o file="/etc/master.passwd" \e /var/audit/20031016184719.20031017122634 .Ed .Pp Select all records containing path tokens, where the pathname is a TTY device: .Bd -literal -offset indent auditreduce -o file="/dev/tty[a-zA-Z][0-9]+" \e /var/audit/20031016184719.20031017122634 .Ed .Pp Select all records containing path tokens, where the pathname is a TTY except for .Pa /dev/ttyp2 : .Bd -literal -offset indent auditreduce -o file="~/dev/ttyp2,/dev/tty[a-zA-Z][0-9]+" \e /var/audit/20031016184719.20031017122634 .Ed .Sh SEE ALSO .Xr praudit 1 , .Xr audit_control 5 , .Xr audit_event 5 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer Inc. Additional authors include .An Wayne Salamon , .An Robert Watson , and SPARTA Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditreduce/auditreduce.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditreduce/auditreduce.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditreduce/auditreduce.c (revision 292449) @@ -1,803 +1,801 @@ /*- * Copyright (c) 2004-2008 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditreduce/auditreduce.c#31 $ */ /* * Tool used to merge and select audit records from audit trail files */ /* * XXX Currently we do not support merging of records from multiple * XXX audit trail files * XXX We assume that records are sorted chronologically - both wrt to * XXX the records present within the file and between the files themselves */ #include #define _GNU_SOURCE /* Required for strptime() on glibc2. */ #ifdef HAVE_FULL_QUEUE_H #include #else #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #ifndef HAVE_STRLCPY #include #endif #include "auditreduce.h" static TAILQ_HEAD(tailhead, re_entry) re_head = TAILQ_HEAD_INITIALIZER(re_head); extern char *optarg; extern int optind, optopt, opterr,optreset; static au_mask_t maskp; /* Class. */ static time_t p_atime; /* Created after this time. */ static time_t p_btime; /* Created before this time. */ static int p_auid; /* Audit id. */ static int p_euid; /* Effective user id. */ static int p_egid; /* Effective group id. */ static int p_rgid; /* Real group id. */ static int p_ruid; /* Real user id. */ static int p_subid; /* Subject id. */ /* * Maintain a dynamically sized array of events for -m */ static uint16_t *p_evec; /* Event type list */ static int p_evec_used; /* Number of events used */ static int p_evec_alloc; /* Number of events allocated */ /* * Following are the objects (-o option) that we can select upon. */ static char *p_fileobj = NULL; static char *p_msgqobj = NULL; static char *p_pidobj = NULL; static char *p_semobj = NULL; static char *p_shmobj = NULL; static char *p_sockobj = NULL; static uint32_t opttochk = 0; static void parse_regexp(char *re_string) { char *orig, *copy, re_error[64]; struct re_entry *rep; int error, nstrs, i, len; copy = strdup(re_string); orig = copy; len = strlen(copy); for (nstrs = 0, i = 0; i < len; i++) { if (copy[i] == ',' && i > 0) { if (copy[i - 1] == '\\') strlcpy(©[i - 1], ©[i], len); else { nstrs++; copy[i] = '\0'; } } } TAILQ_INIT(&re_head); for (i = 0; i < nstrs + 1; i++) { rep = calloc(1, sizeof(*rep)); if (rep == NULL) { (void) fprintf(stderr, "calloc: %s\n", strerror(errno)); exit(1); } if (*copy == '~') { copy++; rep->re_negate = 1; } rep->re_pattern = strdup(copy); error = regcomp(&rep->re_regexp, rep->re_pattern, REG_EXTENDED | REG_NOSUB); if (error != 0) { regerror(error, &rep->re_regexp, re_error, 64); (void) fprintf(stderr, "regcomp: %s\n", re_error); exit(1); } TAILQ_INSERT_TAIL(&re_head, rep, re_glue); len = strlen(copy); copy += len + 1; } free(orig); } static void usage(const char *msg) { fprintf(stderr, "%s\n", msg); fprintf(stderr, "Usage: auditreduce [options] [file ...]\n"); fprintf(stderr, "\tOptions are : \n"); fprintf(stderr, "\t-A : all records\n"); fprintf(stderr, "\t-a YYYYMMDD[HH[[MM[SS]]] : after date\n"); fprintf(stderr, "\t-b YYYYMMDD[HH[[MM[SS]]] : before date\n"); fprintf(stderr, "\t-c : matching class\n"); fprintf(stderr, "\t-d YYYYMMDD : on date\n"); fprintf(stderr, "\t-e : effective user\n"); fprintf(stderr, "\t-f : effective group\n"); fprintf(stderr, "\t-g : real group\n"); fprintf(stderr, "\t-j : subject id \n"); fprintf(stderr, "\t-m : matching event\n"); fprintf(stderr, "\t-o objecttype=objectvalue\n"); fprintf(stderr, "\t\t file=\n"); fprintf(stderr, "\t\t msgqid=\n"); fprintf(stderr, "\t\t pid=\n"); fprintf(stderr, "\t\t semid=\n"); fprintf(stderr, "\t\t shmid=\n"); fprintf(stderr, "\t-r : real user\n"); fprintf(stderr, "\t-u : audit user\n"); fprintf(stderr, "\t-v : select non-matching records\n"); exit(EX_USAGE); } /* * Check if the given auid matches the selection criteria. */ static int select_auid(int au) { /* Check if we want to select on auid. */ if (ISOPTSET(opttochk, OPT_u)) { if (au != p_auid) return (0); } return (1); } /* * Check if the given euid matches the selection criteria. */ static int select_euid(int euser) { /* Check if we want to select on euid. */ if (ISOPTSET(opttochk, OPT_e)) { if (euser != p_euid) return (0); } return (1); } /* * Check if the given egid matches the selection criteria. */ static int select_egid(int egrp) { /* Check if we want to select on egid. */ if (ISOPTSET(opttochk, OPT_f)) { if (egrp != p_egid) return (0); } return (1); } /* * Check if the given rgid matches the selection criteria. */ static int select_rgid(int grp) { /* Check if we want to select on rgid. */ if (ISOPTSET(opttochk, OPT_g)) { if (grp != p_rgid) return (0); } return (1); } /* * Check if the given ruid matches the selection criteria. */ static int select_ruid(int user) { /* Check if we want to select on rgid. */ if (ISOPTSET(opttochk, OPT_r)) { if (user != p_ruid) return (0); } return (1); } /* * Check if the given subject id (pid) matches the selection criteria. */ static int select_subid(int subid) { /* Check if we want to select on subject uid. */ if (ISOPTSET(opttochk, OPT_j)) { if (subid != p_subid) return (0); } return (1); } /* * Check if object's pid maches the given pid. */ static int select_pidobj(uint32_t pid) { if (ISOPTSET(opttochk, OPT_op)) { if (pid != (uint32_t)strtol(p_pidobj, (char **)NULL, 10)) return (0); } return (1); } /* * Check if the given ipc object with the given type matches the selection * criteria. */ static int select_ipcobj(u_char type, uint32_t id, uint32_t *optchkd) { if (type == AT_IPC_MSG) { SETOPT((*optchkd), OPT_om); if (ISOPTSET(opttochk, OPT_om)) { if (id != (uint32_t)strtol(p_msgqobj, (char **)NULL, 10)) return (0); } return (1); } else if (type == AT_IPC_SEM) { SETOPT((*optchkd), OPT_ose); if (ISOPTSET(opttochk, OPT_ose)) { if (id != (uint32_t)strtol(p_semobj, (char **)NULL, 10)) return (0); } return (1); } else if (type == AT_IPC_SHM) { SETOPT((*optchkd), OPT_osh); if (ISOPTSET(opttochk, OPT_osh)) { if (id != (uint32_t)strtol(p_shmobj, (char **)NULL, 10)) return (0); } return (1); } /* Unknown type -- filter if *any* ipc filtering is required. */ if (ISOPTSET(opttochk, OPT_om) || ISOPTSET(opttochk, OPT_ose) || ISOPTSET(opttochk, OPT_osh)) return (0); return (1); } /* * Check if the file name matches selection criteria. */ static int select_filepath(char *path, uint32_t *optchkd) { struct re_entry *rep; int match; SETOPT((*optchkd), OPT_of); match = 1; if (ISOPTSET(opttochk, OPT_of)) { match = 0; TAILQ_FOREACH(rep, &re_head, re_glue) { if (regexec(&rep->re_regexp, path, 0, NULL, 0) != REG_NOMATCH) return (!rep->re_negate); } } return (match); } /* * Returns 1 if the following pass the selection rules: * * before-time, * after time, * date, * class, * event */ static int select_hdr32(tokenstr_t tok, uint32_t *optchkd) { uint16_t *ev; int match; SETOPT((*optchkd), (OPT_A | OPT_a | OPT_b | OPT_c | OPT_m | OPT_v)); /* The A option overrides a, b and d. */ if (!ISOPTSET(opttochk, OPT_A)) { if (ISOPTSET(opttochk, OPT_a)) { if (difftime((time_t)tok.tt.hdr32.s, p_atime) < 0) { /* Record was created before p_atime. */ return (0); } } if (ISOPTSET(opttochk, OPT_b)) { if (difftime(p_btime, (time_t)tok.tt.hdr32.s) < 0) { /* Record was created after p_btime. */ return (0); } } } if (ISOPTSET(opttochk, OPT_c)) { /* * Check if the classes represented by the event matches * given class. */ if (au_preselect(tok.tt.hdr32.e_type, &maskp, AU_PRS_BOTH, AU_PRS_USECACHE) != 1) return (0); } /* Check if event matches. */ if (ISOPTSET(opttochk, OPT_m)) { match = 0; for (ev = p_evec; ev < &p_evec[p_evec_used]; ev++) if (tok.tt.hdr32.e_type == *ev) match = 1; if (match == 0) return (0); } return (1); } static int select_return32(tokenstr_t tok_ret32, tokenstr_t tok_hdr32, uint32_t *optchkd) { int sorf; SETOPT((*optchkd), (OPT_c)); if (tok_ret32.tt.ret32.status == 0) sorf = AU_PRS_SUCCESS; else sorf = AU_PRS_FAILURE; if (ISOPTSET(opttochk, OPT_c)) { if (au_preselect(tok_hdr32.tt.hdr32.e_type, &maskp, sorf, AU_PRS_USECACHE) != 1) return (0); } return (1); } /* * Return 1 if checks for the the following succeed * auid, * euid, * egid, * rgid, * ruid, * process id */ static int select_proc32(tokenstr_t tok, uint32_t *optchkd) { SETOPT((*optchkd), (OPT_u | OPT_e | OPT_f | OPT_g | OPT_r | OPT_op)); if (!select_auid(tok.tt.proc32.auid)) return (0); if (!select_euid(tok.tt.proc32.euid)) return (0); if (!select_egid(tok.tt.proc32.egid)) return (0); if (!select_rgid(tok.tt.proc32.rgid)) return (0); if (!select_ruid(tok.tt.proc32.ruid)) return (0); if (!select_pidobj(tok.tt.proc32.pid)) return (0); return (1); } /* * Return 1 if checks for the the following succeed * auid, * euid, * egid, * rgid, * ruid, * subject id */ static int select_subj32(tokenstr_t tok, uint32_t *optchkd) { SETOPT((*optchkd), (OPT_u | OPT_e | OPT_f | OPT_g | OPT_r | OPT_j)); if (!select_auid(tok.tt.subj32.auid)) return (0); if (!select_euid(tok.tt.subj32.euid)) return (0); if (!select_egid(tok.tt.subj32.egid)) return (0); if (!select_rgid(tok.tt.subj32.rgid)) return (0); if (!select_ruid(tok.tt.subj32.ruid)) return (0); if (!select_subid(tok.tt.subj32.pid)) return (0); return (1); } /* * Read each record from the audit trail. Check if it is selected after * passing through each of the options */ static int select_records(FILE *fp) { tokenstr_t tok_hdr32_copy; u_char *buf; tokenstr_t tok; int reclen; int bytesread; int selected; uint32_t optchkd; int print; int err = 0; while ((reclen = au_read_rec(fp, &buf)) != -1) { optchkd = 0; bytesread = 0; selected = 1; while ((selected == 1) && (bytesread < reclen)) { if (-1 == au_fetch_tok(&tok, buf + bytesread, reclen - bytesread)) { /* Is this an incomplete record? */ err = 1; break; } /* * For each token type we have have different * selection criteria. */ switch(tok.id) { case AUT_HEADER32: selected = select_hdr32(tok, &optchkd); bcopy(&tok, &tok_hdr32_copy, sizeof(tok)); break; case AUT_PROCESS32: selected = select_proc32(tok, &optchkd); break; case AUT_SUBJECT32: selected = select_subj32(tok, &optchkd); break; case AUT_IPC: selected = select_ipcobj( tok.tt.ipc.type, tok.tt.ipc.id, &optchkd); break; case AUT_PATH: selected = select_filepath( tok.tt.path.path, &optchkd); break; case AUT_RETURN32: selected = select_return32(tok, tok_hdr32_copy, &optchkd); break; default: break; } bytesread += tok.len; } /* Check if all the options were matched. */ print = ((selected == 1) && (!err) && (!(opttochk & ~optchkd))); if (ISOPTSET(opttochk, OPT_v)) print = !print; if (print) (void) fwrite(buf, 1, reclen, stdout); free(buf); } return (0); } /* * The -o option has the form object_type=object_value. Identify the object * components. */ static void parse_object_type(char *name, char *val) { if (val == NULL) return; if (!strcmp(name, FILEOBJ)) { p_fileobj = val; parse_regexp(val); SETOPT(opttochk, OPT_of); } else if (!strcmp(name, MSGQIDOBJ)) { p_msgqobj = val; SETOPT(opttochk, OPT_om); } else if (!strcmp(name, PIDOBJ)) { p_pidobj = val; SETOPT(opttochk, OPT_op); } else if (!strcmp(name, SEMIDOBJ)) { p_semobj = val; SETOPT(opttochk, OPT_ose); } else if (!strcmp(name, SHMIDOBJ)) { p_shmobj = val; SETOPT(opttochk, OPT_osh); } else if (!strcmp(name, SOCKOBJ)) { p_sockobj = val; SETOPT(opttochk, OPT_oso); } else usage("unknown value for -o"); } int main(int argc, char **argv) { struct group *grp; struct passwd *pw; struct tm tm; au_event_t *n; FILE *fp; int i; char *objval, *converr; int ch; char timestr[128]; char *fname; uint16_t *etp; converr = NULL; while ((ch = getopt(argc, argv, "Aa:b:c:d:e:f:g:j:m:o:r:u:v")) != -1) { switch(ch) { case 'A': SETOPT(opttochk, OPT_A); break; case 'a': if (ISOPTSET(opttochk, OPT_a)) { usage("d is exclusive with a and b"); } SETOPT(opttochk, OPT_a); bzero(&tm, sizeof(tm)); strptime(optarg, "%Y%m%d%H%M%S", &tm); strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S", &tm); /* fprintf(stderr, "Time converted = %s\n", timestr); */ p_atime = mktime(&tm); break; case 'b': if (ISOPTSET(opttochk, OPT_b)) { usage("d is exclusive with a and b"); } SETOPT(opttochk, OPT_b); bzero(&tm, sizeof(tm)); strptime(optarg, "%Y%m%d%H%M%S", &tm); strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S", &tm); /* fprintf(stderr, "Time converted = %s\n", timestr); */ p_btime = mktime(&tm); break; case 'c': if (0 != getauditflagsbin(optarg, &maskp)) { /* Incorrect class */ usage("Incorrect class"); } SETOPT(opttochk, OPT_c); break; case 'd': if (ISOPTSET(opttochk, OPT_b) || ISOPTSET(opttochk, OPT_a)) usage("'d' is exclusive with 'a' and 'b'"); SETOPT(opttochk, OPT_d); bzero(&tm, sizeof(tm)); strptime(optarg, "%Y%m%d", &tm); strftime(timestr, sizeof(timestr), "%Y%m%d", &tm); /* fprintf(stderr, "Time converted = %s\n", timestr); */ p_atime = mktime(&tm); tm.tm_hour = 23; tm.tm_min = 59; tm.tm_sec = 59; strftime(timestr, sizeof(timestr), "%Y%m%d", &tm); /* fprintf(stderr, "Time converted = %s\n", timestr); */ p_btime = mktime(&tm); break; case 'e': p_euid = strtol(optarg, &converr, 10); if (*converr != '\0') { /* Try the actual name */ if ((pw = getpwnam(optarg)) == NULL) break; p_euid = pw->pw_uid; } SETOPT(opttochk, OPT_e); break; case 'f': p_egid = strtol(optarg, &converr, 10); if (*converr != '\0') { /* Try actual group name. */ if ((grp = getgrnam(optarg)) == NULL) break; p_egid = grp->gr_gid; } SETOPT(opttochk, OPT_f); break; case 'g': p_rgid = strtol(optarg, &converr, 10); if (*converr != '\0') { /* Try actual group name. */ if ((grp = getgrnam(optarg)) == NULL) break; p_rgid = grp->gr_gid; } SETOPT(opttochk, OPT_g); break; case 'j': p_subid = strtol(optarg, (char **)NULL, 10); SETOPT(opttochk, OPT_j); break; case 'm': if (p_evec == NULL) { p_evec_alloc = 32; p_evec = malloc(sizeof(*etp) * p_evec_alloc); if (p_evec == NULL) err(1, "malloc"); } else if (p_evec_alloc == p_evec_used) { p_evec_alloc <<= 1; p_evec = realloc(p_evec, sizeof(*p_evec) * p_evec_alloc); if (p_evec == NULL) err(1, "realloc"); } etp = &p_evec[p_evec_used++]; *etp = strtol(optarg, (char **)NULL, 10); if (*etp == 0) { /* Could be the string representation. */ n = getauevnonam(optarg); if (n == NULL) usage("Incorrect event name"); *etp = *n; } SETOPT(opttochk, OPT_m); break; case 'o': objval = strchr(optarg, '='); if (objval != NULL) { *objval = '\0'; objval += 1; parse_object_type(optarg, objval); } break; case 'r': p_ruid = strtol(optarg, &converr, 10); if (*converr != '\0') { if ((pw = getpwnam(optarg)) == NULL) break; p_ruid = pw->pw_uid; } SETOPT(opttochk, OPT_r); break; case 'u': p_auid = strtol(optarg, &converr, 10); if (*converr != '\0') { if ((pw = getpwnam(optarg)) == NULL) break; p_auid = pw->pw_uid; } SETOPT(opttochk, OPT_u); break; case 'v': SETOPT(opttochk, OPT_v); break; case '?': default: usage("Unknown option"); } } argv += optind; argc -= optind; if (argc == 0) { if (select_records(stdin) == -1) errx(EXIT_FAILURE, "Couldn't select records from stdin"); exit(EXIT_SUCCESS); } /* * XXX: We should actually be merging records here. */ for (i = 0; i < argc; i++) { fname = argv[i]; fp = fopen(fname, "r"); if (fp == NULL) errx(EXIT_FAILURE, "Couldn't open %s", fname); if (select_records(fp) == -1) { errx(EXIT_FAILURE, "Couldn't select records %s", fname); } fclose(fp); } exit(EXIT_SUCCESS); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditreduce/auditreduce.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditreduce/auditreduce.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/auditreduce/auditreduce.h (revision 292449) @@ -1,75 +1,73 @@ /*- * Copyright (c) 2004 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditreduce/auditreduce.h#7 $ */ #ifndef _AUDITREDUCE_H_ #define _AUDITREDUCE_H_ struct re_entry { char *re_pattern; int re_negate; regex_t re_regexp; TAILQ_ENTRY(re_entry) re_glue; }; #define OPT_a 0x00000001 #define OPT_b 0x00000002 #define OPT_c 0x00000004 #define OPT_d (OPT_a | OPT_b) #define OPT_e 0x00000010 #define OPT_f 0x00000020 #define OPT_g 0x00000040 #define OPT_j 0x00000080 #define OPT_m 0x00000100 #define OPT_of 0x00000200 #define OPT_om 0x00000400 #define OPT_op 0x00000800 #define OPT_ose 0x00001000 #define OPT_osh 0x00002000 #define OPT_oso 0x00004000 #define OPT_r 0x00008000 #define OPT_u 0x00010000 #define OPT_A 0x00020000 #define OPT_v 0x00040000 #define FILEOBJ "file" #define MSGQIDOBJ "msgqid" #define PIDOBJ "pid" #define SEMIDOBJ "semid" #define SHMIDOBJ "shmid" #define SOCKOBJ "sock" #define SETOPT(optmask, bit) (optmask |= bit) #define ISOPTSET(optmask, bit) (optmask & bit) #endif /* !_AUDITREDUCE_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/praudit/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/praudit/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/praudit/Makefile.am (revision 292449) @@ -1,14 +1,10 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/bin/praudit/Makefile.am#4 $ -## - if USE_NATIVE_INCLUDES INCLUDES = -I$(top_builddir) -I$(top_srcdir) else INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys endif sbin_PROGRAMS = praudit praudit_SOURCES = praudit.c praudit_LDADD = $(top_builddir)/libbsm/libbsm.la man1_MANS = praudit.1 Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/praudit/praudit.1 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/praudit/praudit.1 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/praudit/praudit.1 (revision 292449) @@ -1,121 +1,119 @@ .\" Copyright (c) 2004-2009 Apple Inc. .\" 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR .\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/bin/praudit/praudit.1#14 $ -.\" .Dd August 4, 2009 .Dt PRAUDIT 1 .Os .Sh NAME .Nm praudit .Nd "print the contents of audit trail files" .Sh SYNOPSIS .Nm .Op Fl lnpx .Op Fl r | s .Op Fl d Ar del .Op Ar .Sh DESCRIPTION The .Nm utility prints the contents of the audit trail files to the standard output in human-readable form. If no .Ar file argument is specified, the standard input is used by default. .Pp The options are as follows: .Bl -tag -width indent .It Fl d Ar del Specifies the delimiter. The default delimiter is the comma. .It Fl l Prints the entire record on the same line. If this option is not specified, every token is displayed on a different line. .It Fl n Do not convert user and group IDs to their names but leave in their numeric forms. .It Fl p Specify this option if input to .Nm is piped from the .Xr tail 1 utility. This causes .Nm to sync to the start of the next record. .It Fl r Prints the records in their raw, numeric form. This option is exclusive from .Fl s . .It Fl s Prints the tokens in their short form. Short text representations for record and event type are displayed. This option is exclusive from .Fl r . .It Fl x Print audit records in the XML output format. .El .Pp If the raw or short forms are not specified, the default is to print the tokens in their long form. Events are displayed as per their descriptions given in .Pa /etc/security/audit_event ; UIDs and GIDs are expanded to their names; dates and times are displayed in human-readable format. .Sh FILES .Bl -tag -width ".Pa /etc/security/audit_control" -compact .It Pa /etc/security/audit_class Descriptions of audit event classes. .It Pa /etc/security/audit_event Descriptions of audit events. .El .Sh SEE ALSO .Xr auditreduce 1 , .Xr audit 4 , .Xr auditpipe 4 , .Xr audit_class 5 , .Xr audit_event 5 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer Inc. Additional authors include .An Wayne Salamon , .An Robert Watson , and SPARTA Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bin/praudit/praudit.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bin/praudit/praudit.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bin/praudit/praudit.c (revision 292449) @@ -1,175 +1,173 @@ /*- * Copyright (c) 2004-2009 Apple Inc. * Copyright (c) 2006 Martin Voros * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/bin/praudit/praudit.c#16 $ */ /* * Tool used to parse audit records conforming to the BSM structure. */ /* * praudit [-lnpx] [-r | -s] [-d del] [file ...] */ #include #include #include #include extern char *optarg; extern int optind, optopt, opterr,optreset; static char *del = ","; /* Default delimiter. */ static int oneline = 0; static int partial = 0; static int oflags = AU_OFLAG_NONE; static void usage(void) { fprintf(stderr, "usage: praudit [-lnpx] [-r | -s] [-d del] " "[file ...]\n"); exit(1); } /* * Token printing for each token type . */ static int print_tokens(FILE *fp) { u_char *buf; tokenstr_t tok; int reclen; int bytesread; /* Allow tail -f | praudit to work. */ if (partial) { u_char type = 0; /* Record must begin with a header token. */ do { type = fgetc(fp); } while(type != AUT_HEADER32); ungetc(type, fp); } while ((reclen = au_read_rec(fp, &buf)) != -1) { bytesread = 0; while (bytesread < reclen) { /* Is this an incomplete record? */ if (-1 == au_fetch_tok(&tok, buf + bytesread, reclen - bytesread)) break; au_print_flags_tok(stdout, &tok, del, oflags); bytesread += tok.len; if (oneline) { if (!(oflags & AU_OFLAG_XML)) printf("%s", del); } else printf("\n"); } free(buf); if (oneline) printf("\n"); fflush(stdout); } return (0); } int main(int argc, char **argv) { int ch; int i; FILE *fp; while ((ch = getopt(argc, argv, "d:lnprsx")) != -1) { switch(ch) { case 'd': del = optarg; break; case 'l': oneline = 1; break; case 'n': oflags |= AU_OFLAG_NORESOLVE; break; case 'p': partial = 1; break; case 'r': if (oflags & AU_OFLAG_SHORT) usage(); /* Exclusive from shortfrm. */ oflags |= AU_OFLAG_RAW; break; case 's': if (oflags & AU_OFLAG_RAW) usage(); /* Exclusive from raw. */ oflags |= AU_OFLAG_SHORT; break; case 'x': oflags |= AU_OFLAG_XML; break; case '?': default: usage(); } } if (oflags & AU_OFLAG_XML) au_print_xml_header(stdout); /* For each of the files passed as arguments dump the contents. */ if (optind == argc) { print_tokens(stdin); return (1); } for (i = optind; i < argc; i++) { fp = fopen(argv[i], "r"); if ((fp == NULL) || (print_tokens(fp) == -1)) perror(argv[i]); if (fp != NULL) fclose(fp); } if (oflags & AU_OFLAG_XML) au_print_xml_footer(stdout); return (1); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bsm/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bsm/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bsm/Makefile.am (revision 292449) @@ -1,12 +1,8 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/bsm/Makefile.am#5 $ -## - openbsmdir = $(includedir)/bsm openbsm_HEADERS = \ audit_filter.h \ audit_uevents.h \ auditd_lib.h \ libbsm.h Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bsm/audit_filter.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bsm/audit_filter.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bsm/audit_filter.h (revision 292449) @@ -1,83 +1,81 @@ /*- * Copyright (c) 2006 Robert N. M. Watson * All rights reserved. * * This software was developed by Robert Watson for the TrustedBSD Project. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/bsm/audit_filter.h#4 $ */ #ifndef _BSM_AUDIT_FILTER_H_ #define _BSM_AUDIT_FILTER_H_ /* * Module interface for audit filter modules. * * audit_filter_attach_t - filter module is being attached with arguments * audit_filter_reinit_t - arguments to module have changed * audit_filter_record_t - present parsed record to filter module, with * receipt time * audit_filter_rawrecord_t - present BSM format record to filter module, * with receipt time * audit_filter_destach_t - filter module is being detached * * There may be many instances of the same filter, identified by the instance * void pointer maintained by the filter instance. */ typedef int (*audit_filter_attach_t)(void *instance, int argc, char *argv[]); typedef int (*audit_filter_reinit_t)(void *instance, int argc, char *argv[]); typedef void (*audit_filter_record_t)(void *instance, struct timespec *ts, int token_count, const tokenstr_t tok[]); typedef void (*audit_filter_rawrecord_t)(void *instance, struct timespec *ts, void *data, u_int len); typedef void (*audit_filter_detach_t)(void *instance); /* * APIs that may be called by audit filters. */ void audit_filter_getcookie(void *instance, void **cookie); void audit_filter_setcookie(void *instance, void *cookie); /* * Values to be returned by audit_filter_init_t. */ #define AUDIT_FILTER_SUCCESS (0) #define AUDIT_FILTER_FAILURE (-1) /* * Standard name for filter module initialization functions, which will be * found using dlsym(). */ #define AUDIT_FILTER_ATTACH audit_filter_attach #define AUDIT_FILTER_REINIT audit_filter_reinit #define AUDIT_FILTER_RECORD audit_filter_record #define AUDIT_FILTER_RAWRECORD audit_filter_rawrecord #define AUDIT_FILTER_DETACH audit_filter_detach #define AUDIT_FILTER_ATTACH_STRING "audit_filter_attach" #define AUDIT_FILTER_REINIT_STRING "audit_filter_reinit" #define AUDIT_FILTER_RECORD_STRING "audit_filter_record" #define AUDIT_FILTER_RAWRECORD_STRING "audit_filter_rawrecord" #define AUDIT_FILTER_DETACH_STRING "audit_filter_detach" #endif /* !_BSM_AUDIT_FILTER_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bsm/audit_uevents.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bsm/audit_uevents.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bsm/audit_uevents.h (revision 292449) @@ -1,143 +1,141 @@ /*- * Copyright (c) 2004-2008 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/bsm/audit_uevents.h#11 $ */ #ifndef _BSM_AUDIT_UEVENTS_H_ #define _BSM_AUDIT_UEVENTS_H_ /* * Solaris userspace events. */ #define AUE_at_create 6144 #define AUE_at_delete 6145 #define AUE_at_perm 6146 #define AUE_cron_invoke 6147 #define AUE_crontab_create 6148 #define AUE_crontab_delete 6149 #define AUE_crontab_perm 6150 #define AUE_inetd_connect 6151 #define AUE_login 6152 #define AUE_logout 6153 #define AUE_telnet 6154 #define AUE_rlogin 6155 #define AUE_mountd_mount 6156 #define AUE_mountd_umount 6157 #define AUE_rshd 6158 #define AUE_su 6159 #define AUE_halt 6160 #define AUE_reboot 6161 #define AUE_rexecd 6162 #define AUE_passwd 6163 #define AUE_rexd 6164 #define AUE_ftpd 6165 #define AUE_init 6166 #define AUE_uadmin 6167 #define AUE_shutdown 6168 #define AUE_poweroff 6169 #define AUE_crontab_mod 6170 #define AUE_ftpd_logout 6171 #define AUE_ssh 6172 #define AUE_role_login 6173 #define AUE_prof_cmd 6180 #define AUE_filesystem_add 6181 #define AUE_filesystem_delete 6182 #define AUE_filesystem_modify 6183 #define AUE_allocate_succ 6200 #define AUE_allocate_fail 6201 #define AUE_deallocate_succ 6202 #define AUE_deallocate_fail 6203 #define AUE_listdevice_succ 6205 #define AUE_listdevice_fail 6206 #define AUE_create_user 6207 #define AUE_modify_user 6208 #define AUE_delete_user 6209 #define AUE_disable_user 6210 #define AUE_enable_user 6211 #define AUE_newgrp_login 6212 #define AUE_admin_authentication 6213 #define AUE_kadmind_auth 6214 #define AUE_kadmind_unauth 6215 #define AUE_krb5kdc_as_req 6216 #define AUE_krb5kdc_tgs_req 6217 #define AUE_krb5kdc_tgs_req_2ndtktmm 6218 #define AUE_krb5kdc_tgs_req_alt_tgt 6219 /* * Historic Darwin use of the low event numbering space, which collided with * the Solaris event space. Now obsoleted and new, higher, event numbers * assigned to make it easier to interpret Solaris events using the OpenBSM * tools. */ #define AUE_DARWIN_audit_startup 6171 #define AUE_DARWIN_audit_shutdown 6172 #define AUE_DARWIN_sudo 6300 #define AUE_DARWIN_modify_password 6501 #define AUE_DARWIN_create_group 6511 #define AUE_DARWIN_delete_group 6512 #define AUE_DARWIN_modify_group 6513 #define AUE_DARWIN_add_to_group 6514 #define AUE_DARWIN_remove_from_group 6515 #define AUE_DARWIN_revoke_obj 6521 #define AUE_DARWIN_lw_login 6600 #define AUE_DARWIN_lw_logout 6601 #define AUE_DARWIN_auth_user 7000 #define AUE_DARWIN_ssconn 7001 #define AUE_DARWIN_ssauthorize 7002 #define AUE_DARWIN_ssauthint 7003 /* * Historic/third-party appliation allocations of event idenfiers. */ #define AUE_openssh 32800 /* * OpenBSM-managed application event space. */ #define AUE_audit_startup 45000 /* Darwin-specific. */ #define AUE_audit_shutdown 45001 /* Darwin-specific. */ #define AUE_modify_password 45014 /* Darwin-specific. */ #define AUE_create_group 45015 /* Darwin-specific. */ #define AUE_delete_group 45016 /* Darwin-specific. */ #define AUE_modify_group 45017 /* Darwin-specific. */ #define AUE_add_to_group 45018 /* Darwin-specific. */ #define AUE_remove_from_group 45019 /* Darwin-specific. */ #define AUE_revoke_obj 45020 /* Darwin-specific. */ #define AUE_lw_login 45021 /* Darwin-specific. */ #define AUE_lw_logout 45022 /* Darwin-specific. */ #define AUE_auth_user 45023 /* Darwin-specific. */ #define AUE_ssconn 45024 /* Darwin-specific. */ #define AUE_ssauthorize 45025 /* Darwin-specific. */ #define AUE_ssauthint 45026 /* Darwin-specific. */ #define AUE_calife 45027 /* OpenBSM-allocated. */ #define AUE_sudo 45028 /* OpenBSM-allocated. */ #define AUE_audit_recovery 45029 /* OpenBSM-allocated. */ #define AUE_ssauthmech 45030 /* Darwin-specific. */ #endif /* !_BSM_AUDIT_UEVENTS_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bsm/auditd_lib.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bsm/auditd_lib.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bsm/auditd_lib.h (revision 292449) @@ -1,110 +1,108 @@ /*- * Copyright (c) 2008 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/bsm/auditd_lib.h#5 $ */ #ifndef _BSM_AUDITD_LIB_H_ #define _BSM_AUDITD_LIB_H_ /* * Lengths for audit trail file components. */ #define NOT_TERMINATED "not_terminated" #define CRASH_RECOVERY "crash_recovery" #define PREFIX_LEN (sizeof("YYYYMMDDhhmmss") - 1) #define POSTFIX_LEN PREFIX_LEN #define FILENAME_LEN (PREFIX_LEN + 1 + POSTFIX_LEN) #define TIMESTAMP_LEN POSTFIX_LEN /* * Macro to generate the timestamp string for trail file. */ #define getTSstr(t, b, l) \ ( (((t) = time(0)) == (time_t)-1 ) || \ !strftime((b), (l), "%Y%m%d%H%M%S", gmtime(&(t)) ) ) ? -1 : 0 /* * The symbolic link to the currently active audit trail file. */ #define AUDIT_CURRENT_LINK "/var/audit/current" /* * Path of auditd plist file for launchd. */ #define AUDITD_PLIST_FILE \ "/System/Library/LaunchDaemons/com.apple.auditd.plist" /* * Error return codes for auditd_lib functions. */ #define ADE_NOERR 0 /* No Error or Success. */ #define ADE_PARSE -1 /* Error parsing audit_control(5). */ #define ADE_AUDITON -2 /* auditon(2) call failed. */ #define ADE_NOMEM -3 /* Error allocating memory. */ #define ADE_SOFTLIM -4 /* All audit log directories over soft limit. */ #define ADE_HARDLIM -5 /* All audit log directories over hard limit. */ #define ADE_STRERR -6 /* Error creating file name string. */ #define ADE_AU_OPEN -7 /* au_open(3) failed. */ #define ADE_AU_CLOSE -8 /* au_close(3) failed. */ #define ADE_SETAUDIT -9 /* setaudit(2) or setaudit_addr(2) failed. */ #define ADE_ACTL -10 /* "Soft" error with auditctl(2). */ #define ADE_ACTLERR -11 /* "Hard" error with auditctl(2). */ #define ADE_SWAPERR -12 /* The audit trail file could not be swap. */ #define ADE_RENAME -13 /* Error renaming crash recovery file. */ #define ADE_READLINK -14 /* Error reading 'current' link. */ #define ADE_SYMLINK -15 /* Error creating 'current' link. */ #define ADE_INVAL -16 /* Invalid argument. */ #define ADE_GETADDR -17 /* Error resolving address from hostname. */ #define ADE_ADDRFAM -18 /* Address family not supported. */ #define ADE_EXPIRE -19 /* Error expiring audit trail files. */ /* * auditd_lib functions. */ const char *auditd_strerror(int errcode); int auditd_set_minfree(void); int auditd_expire_trails(int (*warn_expired)(char *)); int auditd_read_dirs(int (*warn_soft)(char *), int (*warn_hard)(char *)); void auditd_close_dirs(void); int auditd_set_dist(void); int auditd_set_evcmap(void); int auditd_set_namask(void); int auditd_set_policy(void); int auditd_set_fsize(void); int auditd_set_host(void); int auditd_swap_trail(char *TS, char **newfile, gid_t gid, int (*warn_getacdir)(char *)); int auditd_prevent_audit(void); int auditd_gen_record(int event, char *path); int auditd_new_curlink(char *curfile); int auditd_rename(const char *fromname, const char *toname); int audit_quick_start(void); int audit_quick_stop(void); #endif /* !_BSM_AUDITD_LIB_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/bsm/libbsm.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/bsm/libbsm.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/bsm/libbsm.h (revision 292449) @@ -1,1342 +1,1340 @@ /*- * Copyright (c) 2004-2009 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/bsm/libbsm.h#50 $ */ #ifndef _LIBBSM_H_ #define _LIBBSM_H_ /* * NB: definitions, etc., marked with "OpenSSH compatibility" were introduced * solely to allow OpenSSH to compile; Darwin/Apple code should not use them. */ #include #include #include /* Required for audit.h. */ #include /* Required for clock_t on Linux. */ #include #include #include #ifdef __APPLE__ #include /* audit_token_t */ #endif /* * Size parsed token vectors for execve(2) arguments and environmental * variables. Note: changing these sizes affects the ABI of the token * structure, and as the token structure is often placed in the caller stack, * this is undesirable. */ #define AUDIT_MAX_ARGS 128 #define AUDIT_MAX_ENV 128 /* * Arguments to au_preselect(3). */ #define AU_PRS_USECACHE 0 #define AU_PRS_REREAD 1 #define AU_PRS_SUCCESS 1 #define AU_PRS_FAILURE 2 #define AU_PRS_BOTH (AU_PRS_SUCCESS|AU_PRS_FAILURE) #define AUDIT_EVENT_FILE "/etc/security/audit_event" #define AUDIT_CLASS_FILE "/etc/security/audit_class" #define AUDIT_CONTROL_FILE "/etc/security/audit_control" #define AUDIT_USER_FILE "/etc/security/audit_user" #define DIR_CONTROL_ENTRY "dir" #define DIST_CONTROL_ENTRY "dist" #define FILESZ_CONTROL_ENTRY "filesz" #define FLAGS_CONTROL_ENTRY "flags" #define HOST_CONTROL_ENTRY "host" #define MINFREE_CONTROL_ENTRY "minfree" #define NA_CONTROL_ENTRY "naflags" #define POLICY_CONTROL_ENTRY "policy" #define EXPIRE_AFTER_CONTROL_ENTRY "expire-after" #define AU_CLASS_NAME_MAX 8 #define AU_CLASS_DESC_MAX 72 #define AU_EVENT_NAME_MAX 30 #define AU_EVENT_DESC_MAX 50 #define AU_USER_NAME_MAX 50 #define AU_LINE_MAX 256 #define MAX_AUDITSTRING_LEN 256 #define BSM_TEXTBUFSZ MAX_AUDITSTRING_LEN /* OpenSSH compatibility */ /* * Arguments to au_close(3). */ #define AU_TO_NO_WRITE 0 /* Abandon audit record. */ #define AU_TO_WRITE 1 /* Commit audit record. */ /* * Output format flags for au_print_flags_tok(). */ #define AU_OFLAG_NONE 0x0000 /* Default form. */ #define AU_OFLAG_RAW 0x0001 /* Raw, numeric form. */ #define AU_OFLAG_SHORT 0x0002 /* Short form. */ #define AU_OFLAG_XML 0x0004 /* XML form. */ #define AU_OFLAG_NORESOLVE 0x0008 /* No user/group name resolution. */ __BEGIN_DECLS struct au_event_ent { au_event_t ae_number; char *ae_name; char *ae_desc; au_class_t ae_class; }; typedef struct au_event_ent au_event_ent_t; struct au_class_ent { char *ac_name; au_class_t ac_class; char *ac_desc; }; typedef struct au_class_ent au_class_ent_t; struct au_user_ent { char *au_name; au_mask_t au_always; au_mask_t au_never; }; typedef struct au_user_ent au_user_ent_t; __END_DECLS #define ADD_TO_MASK(m, c, sel) do { \ if (sel & AU_PRS_SUCCESS) \ (m)->am_success |= c; \ if (sel & AU_PRS_FAILURE) \ (m)->am_failure |= c; \ } while (0) #define SUB_FROM_MASK(m, c, sel) do { \ if (sel & AU_PRS_SUCCESS) \ (m)->am_success &= ((m)->am_success ^ c); \ if (sel & AU_PRS_FAILURE) \ (m)->am_failure &= ((m)->am_failure ^ c); \ } while (0) #define ADDMASK(m, v) do { \ (m)->am_success |= (v)->am_success; \ (m)->am_failure |= (v)->am_failure; \ } while(0) #define SUBMASK(m, v) do { \ (m)->am_success &= ((m)->am_success ^ (v)->am_success); \ (m)->am_failure &= ((m)->am_failure ^ (v)->am_failure); \ } while(0) __BEGIN_DECLS typedef struct au_tid32 { u_int32_t port; u_int32_t addr; } au_tid32_t; typedef struct au_tid64 { u_int64_t port; u_int32_t addr; } au_tid64_t; typedef struct au_tidaddr32 { u_int32_t port; u_int32_t type; u_int32_t addr[4]; } au_tidaddr32_t; typedef struct au_tidaddr64 { u_int64_t port; u_int32_t type; u_int32_t addr[4]; } au_tidaddr64_t; /* * argument # 1 byte * argument value 4 bytes/8 bytes (32-bit/64-bit value) * text length 2 bytes * text N bytes + 1 terminating NULL byte */ typedef struct { u_char no; u_int32_t val; u_int16_t len; char *text; } au_arg32_t; typedef struct { u_char no; u_int64_t val; u_int16_t len; char *text; } au_arg64_t; /* * how to print 1 byte * basic unit 1 byte * unit count 1 byte * data items (depends on basic unit) */ typedef struct { u_char howtopr; u_char bu; u_char uc; u_char *data; } au_arb_t; /* * file access mode 4 bytes * owner user ID 4 bytes * owner group ID 4 bytes * file system ID 4 bytes * node ID 8 bytes * device 4 bytes/8 bytes (32-bit/64-bit) */ typedef struct { u_int32_t mode; u_int32_t uid; u_int32_t gid; u_int32_t fsid; u_int64_t nid; u_int32_t dev; } au_attr32_t; typedef struct { u_int32_t mode; u_int32_t uid; u_int32_t gid; u_int32_t fsid; u_int64_t nid; u_int64_t dev; } au_attr64_t; /* * count 4 bytes * text count null-terminated string(s) */ typedef struct { u_int32_t count; char *text[AUDIT_MAX_ARGS]; } au_execarg_t; /* * count 4 bytes * text count null-terminated string(s) */ typedef struct { u_int32_t count; char *text[AUDIT_MAX_ENV]; } au_execenv_t; /* * status 4 bytes * return value 4 bytes */ typedef struct { u_int32_t status; u_int32_t ret; } au_exit_t; /* * seconds of time 4 bytes * milliseconds of time 4 bytes * file name length 2 bytes * file pathname N bytes + 1 terminating NULL byte */ typedef struct { u_int32_t s; u_int32_t ms; u_int16_t len; char *name; } au_file_t; /* * number groups 2 bytes * group list N * 4 bytes */ typedef struct { u_int16_t no; u_int32_t list[AUDIT_MAX_GROUPS]; } au_groups_t; /* * record byte count 4 bytes * version # 1 byte [2] * event type 2 bytes * event modifier 2 bytes * seconds of time 4 bytes/8 bytes (32-bit/64-bit value) * milliseconds of time 4 bytes/8 bytes (32-bit/64-bit value) */ typedef struct { u_int32_t size; u_char version; u_int16_t e_type; u_int16_t e_mod; u_int32_t s; u_int32_t ms; } au_header32_t; /* * record byte count 4 bytes * version # 1 byte [2] * event type 2 bytes * event modifier 2 bytes * address type/length 1 byte (XXX: actually, 4 bytes) * machine address 4 bytes/16 bytes (IPv4/IPv6 address) * seconds of time 4 bytes/8 bytes (32/64-bits) * nanoseconds of time 4 bytes/8 bytes (32/64-bits) */ typedef struct { u_int32_t size; u_char version; u_int16_t e_type; u_int16_t e_mod; u_int32_t ad_type; u_int32_t addr[4]; u_int32_t s; u_int32_t ms; } au_header32_ex_t; typedef struct { u_int32_t size; u_char version; u_int16_t e_type; u_int16_t e_mod; u_int64_t s; u_int64_t ms; } au_header64_t; typedef struct { u_int32_t size; u_char version; u_int16_t e_type; u_int16_t e_mod; u_int32_t ad_type; u_int32_t addr[4]; u_int64_t s; u_int64_t ms; } au_header64_ex_t; /* * internet address 4 bytes */ typedef struct { u_int32_t addr; } au_inaddr_t; /* * type 4 bytes * internet address 16 bytes */ typedef struct { u_int32_t type; u_int32_t addr[4]; } au_inaddr_ex_t; /* * version and ihl 1 byte * type of service 1 byte * length 2 bytes * id 2 bytes * offset 2 bytes * ttl 1 byte * protocol 1 byte * checksum 2 bytes * source address 4 bytes * destination address 4 bytes */ typedef struct { u_char version; u_char tos; u_int16_t len; u_int16_t id; u_int16_t offset; u_char ttl; u_char prot; u_int16_t chksm; u_int32_t src; u_int32_t dest; } au_ip_t; /* * object ID type 1 byte * object ID 4 bytes */ typedef struct { u_char type; u_int32_t id; } au_ipc_t; /* * owner user ID 4 bytes * owner group ID 4 bytes * creator user ID 4 bytes * creator group ID 4 bytes * access mode 4 bytes * slot sequence # 4 bytes * key 4 bytes */ typedef struct { u_int32_t uid; u_int32_t gid; u_int32_t puid; u_int32_t pgid; u_int32_t mode; u_int32_t seq; u_int32_t key; } au_ipcperm_t; /* * port IP address 2 bytes */ typedef struct { u_int16_t port; } au_iport_t; /* * length 2 bytes * data length bytes */ typedef struct { u_int16_t size; char *data; } au_opaque_t; /* * path length 2 bytes * path N bytes + 1 terminating NULL byte */ typedef struct { u_int16_t len; char *path; } au_path_t; /* * audit ID 4 bytes * effective user ID 4 bytes * effective group ID 4 bytes * real user ID 4 bytes * real group ID 4 bytes * process ID 4 bytes * session ID 4 bytes * terminal ID * port ID 4 bytes/8 bytes (32-bit/64-bit value) * machine address 4 bytes */ typedef struct { u_int32_t auid; u_int32_t euid; u_int32_t egid; u_int32_t ruid; u_int32_t rgid; u_int32_t pid; u_int32_t sid; au_tid32_t tid; } au_proc32_t; typedef struct { u_int32_t auid; u_int32_t euid; u_int32_t egid; u_int32_t ruid; u_int32_t rgid; u_int32_t pid; u_int32_t sid; au_tid64_t tid; } au_proc64_t; /* * audit ID 4 bytes * effective user ID 4 bytes * effective group ID 4 bytes * real user ID 4 bytes * real group ID 4 bytes * process ID 4 bytes * session ID 4 bytes * terminal ID * port ID 4 bytes/8 bytes (32-bit/64-bit value) * type 4 bytes * machine address 16 bytes */ typedef struct { u_int32_t auid; u_int32_t euid; u_int32_t egid; u_int32_t ruid; u_int32_t rgid; u_int32_t pid; u_int32_t sid; au_tidaddr32_t tid; } au_proc32ex_t; typedef struct { u_int32_t auid; u_int32_t euid; u_int32_t egid; u_int32_t ruid; u_int32_t rgid; u_int32_t pid; u_int32_t sid; au_tidaddr64_t tid; } au_proc64ex_t; /* * error status 1 byte * return value 4 bytes/8 bytes (32-bit/64-bit value) */ typedef struct { u_char status; u_int32_t ret; } au_ret32_t; typedef struct { u_char err; u_int64_t val; } au_ret64_t; /* * sequence number 4 bytes */ typedef struct { u_int32_t seqno; } au_seq_t; /* * socket type 2 bytes * local port 2 bytes * local Internet address 4 bytes * remote port 2 bytes * remote Internet address 4 bytes */ typedef struct { u_int16_t type; u_int16_t l_port; u_int32_t l_addr; u_int16_t r_port; u_int32_t r_addr; } au_socket_t; /* * socket type 2 bytes * local port 2 bytes * address type/length 4 bytes * local Internet address 4 bytes/16 bytes (IPv4/IPv6 address) * remote port 4 bytes * address type/length 4 bytes * remote Internet address 4 bytes/16 bytes (IPv4/IPv6 address) */ typedef struct { u_int16_t domain; u_int16_t type; u_int16_t atype; u_int16_t l_port; u_int32_t l_addr[4]; u_int32_t r_port; u_int32_t r_addr[4]; } au_socket_ex32_t; /* * socket family 2 bytes * local port 2 bytes * socket address 4 bytes/16 bytes (IPv4/IPv6 address) */ typedef struct { u_int16_t family; u_int16_t port; u_int32_t addr[4]; } au_socketinet_ex32_t; typedef struct { u_int16_t family; u_int16_t port; u_int32_t addr; } au_socketinet32_t; /* * socket family 2 bytes * path 104 bytes */ typedef struct { u_int16_t family; char path[104]; } au_socketunix_t; /* * audit ID 4 bytes * effective user ID 4 bytes * effective group ID 4 bytes * real user ID 4 bytes * real group ID 4 bytes * process ID 4 bytes * session ID 4 bytes * terminal ID * port ID 4 bytes/8 bytes (32-bit/64-bit value) * machine address 4 bytes */ typedef struct { u_int32_t auid; u_int32_t euid; u_int32_t egid; u_int32_t ruid; u_int32_t rgid; u_int32_t pid; u_int32_t sid; au_tid32_t tid; } au_subject32_t; typedef struct { u_int32_t auid; u_int32_t euid; u_int32_t egid; u_int32_t ruid; u_int32_t rgid; u_int32_t pid; u_int32_t sid; au_tid64_t tid; } au_subject64_t; /* * audit ID 4 bytes * effective user ID 4 bytes * effective group ID 4 bytes * real user ID 4 bytes * real group ID 4 bytes * process ID 4 bytes * session ID 4 bytes * terminal ID * port ID 4 bytes/8 bytes (32-bit/64-bit value) * type 4 bytes * machine address 16 bytes */ typedef struct { u_int32_t auid; u_int32_t euid; u_int32_t egid; u_int32_t ruid; u_int32_t rgid; u_int32_t pid; u_int32_t sid; au_tidaddr32_t tid; } au_subject32ex_t; typedef struct { u_int32_t auid; u_int32_t euid; u_int32_t egid; u_int32_t ruid; u_int32_t rgid; u_int32_t pid; u_int32_t sid; au_tidaddr64_t tid; } au_subject64ex_t; /* * text length 2 bytes * text N bytes + 1 terminating NULL byte */ typedef struct { u_int16_t len; char *text; } au_text_t; /* * upriv status 1 byte * privstr len 2 bytes * privstr N bytes + 1 (\0 byte) */ typedef struct { u_int8_t sorf; u_int16_t privstrlen; char *priv; } au_priv_t; /* * privset * privtstrlen 2 bytes * privtstr N Bytes + 1 * privstrlen 2 bytes * privstr N Bytes + 1 */ typedef struct { u_int16_t privtstrlen; char *privtstr; u_int16_t privstrlen; char *privstr; } au_privset_t; /* * zonename length 2 bytes * zonename text N bytes + 1 NULL terminator */ typedef struct { u_int16_t len; char *zonename; } au_zonename_t; typedef struct { u_int32_t ident; u_int16_t filter; u_int16_t flags; u_int32_t fflags; u_int32_t data; } au_kevent_t; typedef struct { u_int16_t length; char *data; } au_invalid_t; /* * trailer magic number 2 bytes * record byte count 4 bytes */ typedef struct { u_int16_t magic; u_int32_t count; } au_trailer_t; struct tokenstr { u_char id; u_char *data; size_t len; union { au_arg32_t arg32; au_arg64_t arg64; au_arb_t arb; au_attr32_t attr32; au_attr64_t attr64; au_execarg_t execarg; au_execenv_t execenv; au_exit_t exit; au_file_t file; au_groups_t grps; au_header32_t hdr32; au_header32_ex_t hdr32_ex; au_header64_t hdr64; au_header64_ex_t hdr64_ex; au_inaddr_t inaddr; au_inaddr_ex_t inaddr_ex; au_ip_t ip; au_ipc_t ipc; au_ipcperm_t ipcperm; au_iport_t iport; au_opaque_t opaque; au_path_t path; au_proc32_t proc32; au_proc32ex_t proc32_ex; au_proc64_t proc64; au_proc64ex_t proc64_ex; au_ret32_t ret32; au_ret64_t ret64; au_seq_t seq; au_socket_t socket; au_socket_ex32_t socket_ex32; au_socketinet_ex32_t sockinet_ex32; au_socketunix_t sockunix; au_subject32_t subj32; au_subject32ex_t subj32_ex; au_subject64_t subj64; au_subject64ex_t subj64_ex; au_text_t text; au_kevent_t kevent; au_invalid_t invalid; au_trailer_t trail; au_zonename_t zonename; au_priv_t priv; au_privset_t privset; } tt; /* The token is one of the above types */ }; typedef struct tokenstr tokenstr_t; int audit_submit(short au_event, au_id_t auid, char status, int reterr, const char *fmt, ...); /* * Functions relating to querying audit class information. */ void setauclass(void); void endauclass(void); struct au_class_ent *getauclassent(void); struct au_class_ent *getauclassent_r(au_class_ent_t *class_int); struct au_class_ent *getauclassnam(const char *name); struct au_class_ent *getauclassnam_r(au_class_ent_t *class_int, const char *name); struct au_class_ent *getauclassnum(au_class_t class_number); struct au_class_ent *getauclassnum_r(au_class_ent_t *class_int, au_class_t class_number); /* * Functions relating to querying audit control information. */ void setac(void); void endac(void); int getacdir(char *name, int len); int getacdist(void); int getacexpire(int *andflg, time_t *age, size_t *size); int getacfilesz(size_t *size_val); int getacflg(char *auditstr, int len); int getachost(char *auditstr, size_t len); int getacmin(int *min_val); int getacna(char *auditstr, int len); int getacpol(char *auditstr, size_t len); int getauditflagsbin(char *auditstr, au_mask_t *masks); int getauditflagschar(char *auditstr, au_mask_t *masks, int verbose); int au_preselect(au_event_t event, au_mask_t *mask_p, int sorf, int flag); ssize_t au_poltostr(int policy, size_t maxsize, char *buf); int au_strtopol(const char *polstr, int *policy); /* * Functions relating to querying audit event information. */ void setauevent(void); void endauevent(void); struct au_event_ent *getauevent(void); struct au_event_ent *getauevent_r(struct au_event_ent *e); struct au_event_ent *getauevnam(const char *name); struct au_event_ent *getauevnam_r(struct au_event_ent *e, const char *name); struct au_event_ent *getauevnum(au_event_t event_number); struct au_event_ent *getauevnum_r(struct au_event_ent *e, au_event_t event_number); au_event_t *getauevnonam(const char *event_name); au_event_t *getauevnonam_r(au_event_t *ev, const char *event_name); /* * Functions relating to querying audit user information. */ void setauuser(void); void endauuser(void); struct au_user_ent *getauuserent(void); struct au_user_ent *getauuserent_r(struct au_user_ent *u); struct au_user_ent *getauusernam(const char *name); struct au_user_ent *getauusernam_r(struct au_user_ent *u, const char *name); int au_user_mask(char *username, au_mask_t *mask_p); int getfauditflags(au_mask_t *usremask, au_mask_t *usrdmask, au_mask_t *lastmask); /* * Functions for reading and printing records and tokens from audit trails. */ int au_read_rec(FILE *fp, u_char **buf); int au_fetch_tok(tokenstr_t *tok, u_char *buf, int len); //XXX The following interface has different prototype from BSM void au_print_tok(FILE *outfp, tokenstr_t *tok, char *del, char raw, char sfrm); void au_print_flags_tok(FILE *outfp, tokenstr_t *tok, char *del, int oflags); void au_print_tok_xml(FILE *outfp, tokenstr_t *tok, char *del, char raw, char sfrm); /* * Functions relating to XML output. */ void au_print_xml_header(FILE *outfp); void au_print_xml_footer(FILE *outfp); /* * BSM library routines for converting between local and BSM constant spaces. * (Note: some of these are replicated in audit_record.h for the benefit of * the FreeBSD and Mac OS X kernels) */ int au_bsm_to_domain(u_short bsm_domain, int *local_domainp); int au_bsm_to_errno(u_char bsm_error, int *errorp); int au_bsm_to_fcntl_cmd(u_short bsm_fcntl_cmd, int *local_fcntl_cmdp); int au_bsm_to_socket_type(u_short bsm_socket_type, int *local_socket_typep); u_short au_domain_to_bsm(int local_domain); u_char au_errno_to_bsm(int local_errno); u_short au_fcntl_cmd_to_bsm(int local_fcntl_command); u_short au_socket_type_to_bsm(int local_socket_type); const char *au_strerror(u_char bsm_error); __END_DECLS /* * The remaining APIs are associated with Apple's BSM implementation, in * particular as relates to Mach IPC auditing and triggers passed via Mach * IPC. */ #ifdef __APPLE__ #include /************************************************************************** ************************************************************************** ** The following definitions, functions, etc., are NOT officially ** supported: they may be changed or removed in the future. Do not use ** them unless you are prepared to cope with that eventuality. ************************************************************************** **************************************************************************/ #ifdef __APPLE_API_PRIVATE #define __BSM_INTERNAL_NOTIFY_KEY "com.apple.audit.change" #endif /* __APPLE_API_PRIVATE */ /* * au_get_state() return values * XXX use AUC_* values directly instead (); AUDIT_OFF and * AUDIT_ON are deprecated and WILL be removed. */ #ifdef __APPLE_API_PRIVATE #define AUDIT_OFF AUC_NOAUDIT #define AUDIT_ON AUC_AUDITING #endif /* __APPLE_API_PRIVATE */ #endif /* !__APPLE__ */ /* * Error return codes for audit_set_terminal_id(), audit_write() and its * brethren. We have 255 (not including kAUNoErr) to play with. * * XXXRW: In Apple's bsm-8, these are marked __APPLE_API_PRIVATE. */ enum { kAUNoErr = 0, kAUBadParamErr = -66049, kAUStatErr, kAUSysctlErr, kAUOpenErr, kAUMakeSubjectTokErr, kAUWriteSubjectTokErr, kAUWriteCallerTokErr, kAUMakeReturnTokErr, kAUWriteReturnTokErr, kAUCloseErr, kAUMakeTextTokErr, kAULastErr }; #ifdef __APPLE__ /* * Error return codes for au_get_state() and/or its private support * functions. These codes are designed to be compatible with the * NOTIFY_STATUS_* codes defined in but non-overlapping. * Any changes to notify(3) may cause these values to change in future. * * AU_UNIMPL should never happen unless you've changed your system software * without rebooting. Shame on you. */ #ifdef __APPLE_API_PRIVATE #define AU_UNIMPL NOTIFY_STATUS_FAILED + 1 /* audit unimplemented */ #endif /* __APPLE_API_PRIVATE */ #endif /* !__APPLE__ */ __BEGIN_DECLS /* * XXX This prototype should be in audit_record.h * * au_free_token() * * @summary - au_free_token() deallocates a token_t created by any of * the au_to_*() BSM API functions. * * The BSM API generally manages deallocation of token_t objects. However, * if au_write() is passed a bad audit descriptor, the token_t * parameter * will be left untouched. In that case, the caller can deallocate the * token_t using au_free_token() if desired. This is, in fact, what * audit_write() does, in keeping with the existing memory management model * of the BSM API. * * @param tok - A token_t * generated by one of the au_to_*() BSM API * calls. For convenience, tok may be NULL, in which case * au_free_token() returns immediately. * * XXXRW: In Apple's bsm-8, these are marked __APPLE_API_PRIVATE. */ void au_free_token(token_t *tok); /* * Lightweight check to determine if auditing is enabled. If a client * wants to use this to govern whether an entire series of audit calls * should be made--as in the common case of a caller building a set of * tokens, then writing them--it should cache the audit status in a local * variable. This call always returns the current state of auditing. * * @return - AUC_AUDITING or AUC_NOAUDIT if no error occurred. * Otherwise the function can return any of the errno values defined for * setaudit(2), or AU_UNIMPL if audit does not appear to be supported by * the system. * * XXXRW: In Apple's bsm-8, these are marked __APPLE_API_PRIVATE. */ int au_get_state(void); /* * Initialize the audit notification. If it has not already been initialized * it will automatically on the first call of au_get_state(). */ uint32_t au_notify_initialize(void); /* * Cancel audit notification and free the resources associated with it. * Responsible code that no longer needs to use au_get_state() should call * this. */ int au_notify_terminate(void); __END_DECLS /* OpenSSH compatibility */ int cannot_audit(int); __BEGIN_DECLS /* * audit_set_terminal_id() * * @summary - audit_set_terminal_id() fills in an au_tid_t struct, which is * used in audit session initialization by processes like /usr/bin/login. * * @param tid - A pointer to an au_tid_t struct. * * @return - kAUNoErr on success; kAUBadParamErr if tid is NULL, kAUStatErr * or kAUSysctlErr if one of the underlying system calls fails (a message * is sent to the system log in those cases). * * XXXRW: In Apple's bsm-8, these are marked __APPLE_API_PRIVATE. */ int audit_set_terminal_id(au_tid_t *tid); /* * BEGIN au_write() WRAPPERS * * The following calls all wrap the existing BSM API. They use the * provided subject information, if any, to construct the subject token * required for every log message. They use the provided return/error * value(s), if any, to construct the success/failure indication required * for every log message. They only permit one "miscellaneous" token, * which should contain the event-specific logging information mandated by * CAPP. * * All these calls assume the caller has previously determined that * auditing is enabled by calling au_get_state(). */ /* * audit_write() * * @summary - audit_write() is the basis for the other audit_write_*() * calls. Performs a basic write of an audit record (subject, additional * info, success/failure). Note that this call only permits logging one * caller-specified token; clients needing to log more flexibly must use * the existing BSM API (au_open(), et al.) directly. * * Note on memory management: audit_write() guarantees that the token_t *s * passed to it will be deallocated whether or not the underlying write to * the audit log succeeded. This addresses an inconsistency in the * underlying BSM API in which token_t *s are usually but not always * deallocated. * * @param event_code - The code for the event being logged. This should * be one of the AUE_ values in /usr/include/bsm/audit_uevents.h. * * @param subject - A token_t * generated by au_to_subject(), * au_to_subject32(), au_to_subject64(), or au_to_me(). If no subject is * required, subject should be NULL. * * @param misctok - A token_t * generated by one of the au_to_*() BSM API * calls. This should correspond to the additional information required by * CAPP for the event being audited. If no additional information is * required, misctok should be NULL. * * @param retval - The return value to be logged for this event. This * should be 0 (zero) for success, otherwise the value is event-specific. * * @param errcode - Any error code associated with the return value (e.g., * errno or h_errno). If there was no error, errcode should be 0 (zero). * * @return - The status of the call: 0 (zero) on success, else one of the * kAU*Err values defined above. * * XXXRW: In Apple's bsm-8, these are marked __APPLE_API_PRIVATE. */ int audit_write(short event_code, token_t *subject, token_t *misctok, char retval, int errcode); /* * audit_write_success() * * @summary - audit_write_success() records an auditable event that did not * encounter an error. The interface is designed to require as little * direct use of the au_to_*() API as possible. It builds a subject token * from the information passed in and uses that to invoke audit_write(). * A subject, as defined by CAPP, is a process acting on the user's behalf. * * If the subject information is the same as the current process, use * au_write_success_self(). * * @param event_code - The code for the event being logged. This should * be one of the AUE_ values in /usr/include/bsm/audit_uevents.h. * * @param misctok - A token_t * generated by one of the au_to_*() BSM API * calls. This should correspond to the additional information required by * CAPP for the event being audited. If no additional information is * required, misctok should be NULL. * * @param auid - The subject's audit ID. * * @param euid - The subject's effective user ID. * * @param egid - The subject's effective group ID. * * @param ruid - The subject's real user ID. * * @param rgid - The subject's real group ID. * * @param pid - The subject's process ID. * * @param sid - The subject's session ID. * * @param tid - The subject's terminal ID. * * @return - The status of the call: 0 (zero) on success, else one of the * kAU*Err values defined above. * * XXXRW: In Apple's bsm-8, these are marked __APPLE_API_PRIVATE. */ int audit_write_success(short event_code, token_t *misctok, au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_t *tid); /* * audit_write_success_self() * * @summary - Similar to audit_write_success(), but used when the subject * (process) is owned and operated by the auditable user him/herself. * * @param event_code - The code for the event being logged. This should * be one of the AUE_ values in /usr/include/bsm/audit_uevents.h. * * @param misctok - A token_t * generated by one of the au_to_*() BSM API * calls. This should correspond to the additional information required by * CAPP for the event being audited. If no additional information is * required, misctok should be NULL. * * @return - The status of the call: 0 (zero) on success, else one of the * kAU*Err values defined above. * * XXXRW: In Apple's bsm-8, these are marked __APPLE_API_PRIVATE. */ int audit_write_success_self(short event_code, token_t *misctok); /* * audit_write_failure() * * @summary - audit_write_failure() records an auditable event that * encountered an error. The interface is designed to require as little * direct use of the au_to_*() API as possible. It builds a subject token * from the information passed in and uses that to invoke audit_write(). * A subject, as defined by CAPP, is a process acting on the user's behalf. * * If the subject information is the same as the current process, use * au_write_failure_self(). * * @param event_code - The code for the event being logged. This should * be one of the AUE_ values in /usr/include/bsm/audit_uevents.h. * * @param errmsg - A text message providing additional information about * the event being audited. * * @param errret - A numerical value providing additional information about * the error. This is intended to store the value of errno or h_errno if * it's relevant. This can be 0 (zero) if no additional information is * available. * * @param auid - The subject's audit ID. * * @param euid - The subject's effective user ID. * * @param egid - The subject's effective group ID. * * @param ruid - The subject's real user ID. * * @param rgid - The subject's real group ID. * * @param pid - The subject's process ID. * * @param sid - The subject's session ID. * * @param tid - The subject's terminal ID. * * @return - The status of the call: 0 (zero) on success, else one of the * kAU*Err values defined above. * * XXXRW: In Apple's bsm-8, these are marked __APPLE_API_PRIVATE. */ int audit_write_failure(short event_code, char *errmsg, int errret, au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_t *tid); /* * audit_write_failure_self() * * @summary - Similar to audit_write_failure(), but used when the subject * (process) is owned and operated by the auditable user him/herself. * * @param event_code - The code for the event being logged. This should * be one of the AUE_ values in /usr/include/bsm/audit_uevents.h. * * @param errmsg - A text message providing additional information about * the event being audited. * * @param errret - A numerical value providing additional information about * the error. This is intended to store the value of errno or h_errno if * it's relevant. This can be 0 (zero) if no additional information is * available. * * @return - The status of the call: 0 (zero) on success, else one of the * kAU*Err values defined above. * * XXXRW: In Apple's bsm-8, these are marked __APPLE_API_PRIVATE. */ int audit_write_failure_self(short event_code, char *errmsg, int errret); /* * audit_write_failure_na() * * @summary - audit_write_failure_na() records errors during login. Such * errors are implicitly non-attributable (i.e., not ascribable to any user). * * @param event_code - The code for the event being logged. This should * be one of the AUE_ values in /usr/include/bsm/audit_uevents.h. * * @param errmsg - A text message providing additional information about * the event being audited. * * @param errret - A numerical value providing additional information about * the error. This is intended to store the value of errno or h_errno if * it's relevant. This can be 0 (zero) if no additional information is * available. * * @param euid - The subject's effective user ID. * * @param egid - The subject's effective group ID. * * @param pid - The subject's process ID. * * @param tid - The subject's terminal ID. * * @return - The status of the call: 0 (zero) on success, else one of the * kAU*Err values defined above. * * XXXRW: In Apple's bsm-8, these are marked __APPLE_API_PRIVATE. */ int audit_write_failure_na(short event_code, char *errmsg, int errret, uid_t euid, gid_t egid, pid_t pid, au_tid_t *tid); /* END au_write() WRAPPERS */ #ifdef __APPLE__ /* * audit_token_to_au32() * * @summary - Extract information from an audit_token_t, used to identify * Mach tasks and senders of Mach messages as subjects to the audit system. * audit_tokent_to_au32() is the only method that should be used to parse * an audit_token_t, since its internal representation may change over * time. A pointer parameter may be NULL if that information is not * needed. * * @param atoken - the audit token containing the desired information * * @param auidp - Pointer to a uid_t; on return will be set to the task or * sender's audit user ID * * @param euidp - Pointer to a uid_t; on return will be set to the task or * sender's effective user ID * * @param egidp - Pointer to a gid_t; on return will be set to the task or * sender's effective group ID * * @param ruidp - Pointer to a uid_t; on return will be set to the task or * sender's real user ID * * @param rgidp - Pointer to a gid_t; on return will be set to the task or * sender's real group ID * * @param pidp - Pointer to a pid_t; on return will be set to the task or * sender's process ID * * @param asidp - Pointer to an au_asid_t; on return will be set to the * task or sender's audit session ID * * @param tidp - Pointer to an au_tid_t; on return will be set to the task * or sender's terminal ID * * XXXRW: In Apple's bsm-8, these are marked __APPLE_API_PRIVATE. */ void audit_token_to_au32( audit_token_t atoken, uid_t *auidp, uid_t *euidp, gid_t *egidp, uid_t *ruidp, gid_t *rgidp, pid_t *pidp, au_asid_t *asidp, au_tid_t *tidp); #endif /* !__APPLE__ */ /* * Wrapper functions to auditon(2). */ int audit_get_car(char *path, size_t sz); int audit_get_class(au_evclass_map_t *evc_map, size_t sz); int audit_set_class(au_evclass_map_t *evc_map, size_t sz); int audit_get_cond(int *cond); int audit_set_cond(int *cond); int audit_get_cwd(char *path, size_t sz); int audit_get_fsize(au_fstat_t *fstat, size_t sz); int audit_set_fsize(au_fstat_t *fstat, size_t sz); int audit_get_kmask(au_mask_t *kmask, size_t sz); int audit_set_kmask(au_mask_t *kmask, size_t sz); int audit_get_kaudit(auditinfo_addr_t *aia, size_t sz); int audit_set_kaudit(auditinfo_addr_t *aia, size_t sz); int audit_set_pmask(auditpinfo_t *api, size_t sz); int audit_get_pinfo(auditpinfo_t *api, size_t sz); int audit_get_pinfo_addr(auditpinfo_addr_t *apia, size_t sz); int audit_get_policy(int *policy); int audit_set_policy(int *policy); int audit_get_qctrl(au_qctrl_t *qctrl, size_t sz); int audit_set_qctrl(au_qctrl_t *qctrl, size_t sz); int audit_get_sinfo_addr(auditinfo_addr_t *aia, size_t sz); int audit_get_stat(au_stat_t *stats, size_t sz); int audit_set_stat(au_stat_t *stats, size_t sz); int audit_send_trigger(int *trigger); __END_DECLS #endif /* !_LIBBSM_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/compat/clock_gettime.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/compat/clock_gettime.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/compat/clock_gettime.h (revision 292449) @@ -1,54 +1,52 @@ /*- * Copyright (c) 2006 Robert N. M. Watson * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/compat/clock_gettime.h#3 $ */ /* * Compatibility routines for clock_gettime(CLOCK_REALTIME, ...) for systems * that don't have it. We don't use clockid_t in order to avoid conflicts * with the native OS if it has one but not clock_gettime(). We also assume * that the sys/time.h include has already happened at this point, so we have * access to gettimeofday(). */ #include #define CLOCK_REALTIME 0x2d4e1588 static inline int clock_gettime(int clock_id, struct timespec *ts) { struct timeval tv; if (clock_id != CLOCK_REALTIME) { errno = EINVAL; return (-1); } if (gettimeofday(&tv, NULL) < 0) return (-1); ts->tv_sec = tv.tv_sec; ts->tv_nsec = tv.tv_usec * 1000; return (0); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/compat/closefrom.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/compat/closefrom.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/compat/closefrom.h (revision 292449) @@ -1,53 +1,51 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/compat/closefrom.h#1 $ */ #ifndef _CLOSEFROM_H_ #define _CLOSEFROM_H_ #include static void closefrom(int lowfd) { int error, fd, maxfd; error = errno; maxfd = sysconf(_SC_OPEN_MAX); if (maxfd < 0) maxfd = 16384; for (fd = lowfd; fd <= maxfd; fd++) (void)close(fd); errno = error; } #endif /* !_CLOSEFROM_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/compat/compat.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/compat/compat.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/compat/compat.h (revision 292449) @@ -1,59 +1,57 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. - * - * $P4: //depot/projects/trustedbsd/openbsm/compat/compat.h#1 $ */ #ifndef _COMPAT_H_ #define _COMPAT_H_ #include #include #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 #endif #ifndef __unused #define __unused __attribute__((__unused__)) #endif #ifndef __packed #define __packed __attribute__((__packed__)) #endif #ifndef __dead2 #define __dead2 __attribute__((__noreturn__)) #endif #ifndef __printflike #define __printflike(fmtarg, firstvararg) \ __attribute__((__format__ (__printf__, fmtarg, firstvararg))) #endif #endif /* !_COMPAT_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/compat/endian.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/compat/endian.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/compat/endian.h (revision 292449) @@ -1,156 +1,155 @@ /*- * Copyright (c) 2002 Thomas Moestl * Copyright (c) 2005 Robert N. M. Watson * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Derived from FreeBSD src/sys/sys/endian.h:1.6. - * $P4: //depot/projects/trustedbsd/openbsm/compat/endian.h#10 $ */ #ifndef _COMPAT_ENDIAN_H_ #define _COMPAT_ENDIAN_H_ /* * Some systems will have the uint/int types defined here already, others * will need stdint.h. */ #ifdef HAVE_STDINT_H #include #endif /* * Some operating systems do not yet have the more recent endian APIs that * permit encoding to and decoding from byte streams. For those systems, we * implement local non-optimized versions. */ static __inline uint16_t bswap16(uint16_t int16) { const unsigned char *from; unsigned char *to; uint16_t t; from = (const unsigned char *) &int16; to = (unsigned char *) &t; to[0] = from[1]; to[1] = from[0]; return (t); } static __inline uint32_t bswap32(uint32_t int32) { const unsigned char *from; unsigned char *to; uint32_t t; from = (const unsigned char *) &int32; to = (unsigned char *) &t; to[0] = from[3]; to[1] = from[2]; to[2] = from[1]; to[3] = from[0]; return (t); } static __inline uint64_t bswap64(uint64_t int64) { const unsigned char *from; unsigned char *to; uint64_t t; from = (const unsigned char *) &int64; to = (unsigned char *) &t; to[0] = from[7]; to[1] = from[6]; to[2] = from[5]; to[3] = from[4]; to[4] = from[3]; to[5] = from[2]; to[6] = from[1]; to[7] = from[0]; return (t); } #if defined(BYTE_ORDER) && !defined(_BYTE_ORDER) #define _BYTE_ORDER BYTE_ORDER #endif #if !defined(_BYTE_ORDER) #error "Neither BYTE_ORDER nor _BYTE_ORDER defined" #endif #if defined(BIG_ENDIAN) && !defined(_BIG_ENDIAN) #define _BIG_ENDIAN BIG_ENDIAN #endif #if defined(LITTLE_ENDIAN) && !defined(_LITTLE_ENDIAN) #define _LITTLE_ENDIAN LITTLE_ENDIAN #endif /* XXX: Hack. */ #ifndef htobe16 /* * Host to big endian, host to little endian, big endian to host, and little * endian to host byte order functions as detailed in byteorder(9). */ #if _BYTE_ORDER == _LITTLE_ENDIAN #define htobe16(x) bswap16((x)) #define htobe32(x) bswap32((x)) #define htobe64(x) bswap64((x)) #define htole16(x) ((uint16_t)(x)) #define htole32(x) ((uint32_t)(x)) #define htole64(x) ((uint64_t)(x)) #define be16toh(x) bswap16((x)) #define be32toh(x) bswap32((x)) #define be64toh(x) bswap64((x)) #define le16toh(x) ((uint16_t)(x)) #define le32toh(x) ((uint32_t)(x)) #define le64toh(x) ((uint64_t)(x)) #else /* _BYTE_ORDER != _LITTLE_ENDIAN */ #define htobe16(x) ((uint16_t)(x)) #define htobe32(x) ((uint32_t)(x)) #define htobe64(x) ((uint64_t)(x)) #define htole16(x) bswap16((x)) #define htole32(x) bswap32((x)) #define htole64(x) bswap64((x)) #define be16toh(x) ((uint16_t)(x)) #define be32toh(x) ((uint32_t)(x)) #define be64toh(x) ((uint64_t)(x)) #define le16toh(x) bswap16((x)) #define le32toh(x) bswap32((x)) #define le64toh(x) bswap64((x)) #endif /* _BYTE_ORDER == _LITTLE_ENDIAN */ #endif #endif /* _COMPAT_ENDIAN_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/compat/endian_enc.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/compat/endian_enc.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/compat/endian_enc.h (revision 292449) @@ -1,150 +1,149 @@ /*- * Copyright (c) 2002 Thomas Moestl * Copyright (c) 2005 Robert N. M. Watson * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Derived from FreeBSD src/sys/sys/endian.h:1.6. - * $P4: //depot/projects/trustedbsd/openbsm/compat/endian_enc.h#1 $ */ #ifndef _COMPAT_ENDIAN_ENC_H_ #define _COMPAT_ENDIAN_ENC_H_ /* * Some systems will have the uint/int types defined here already, others * will need stdint.h. */ #ifdef HAVE_STDINT_H #include #endif /* Alignment-agnostic encode/decode bytestream to/from little/big endian. */ static __inline uint16_t be16dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; return ((p[0] << 8) | p[1]); } static __inline uint32_t be32dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); } static __inline uint64_t be64dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; return (((uint64_t)be32dec(p) << 32) | be32dec(p + 4)); } static __inline uint16_t le16dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; return ((p[1] << 8) | p[0]); } static __inline uint32_t le32dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); } static __inline uint64_t le64dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p)); } static __inline void be16enc(void *pp, uint16_t u) { unsigned char *p = (unsigned char *)pp; p[0] = (u >> 8) & 0xff; p[1] = u & 0xff; } static __inline void be32enc(void *pp, uint32_t u) { unsigned char *p = (unsigned char *)pp; p[0] = (u >> 24) & 0xff; p[1] = (u >> 16) & 0xff; p[2] = (u >> 8) & 0xff; p[3] = u & 0xff; } static __inline void be64enc(void *pp, uint64_t u) { unsigned char *p = (unsigned char *)pp; be32enc(p, u >> 32); be32enc(p + 4, u & 0xffffffff); } static __inline void le16enc(void *pp, uint16_t u) { unsigned char *p = (unsigned char *)pp; p[0] = u & 0xff; p[1] = (u >> 8) & 0xff; } static __inline void le32enc(void *pp, uint32_t u) { unsigned char *p = (unsigned char *)pp; p[0] = u & 0xff; p[1] = (u >> 8) & 0xff; p[2] = (u >> 16) & 0xff; p[3] = (u >> 24) & 0xff; } static __inline void le64enc(void *pp, uint64_t u) { unsigned char *p = (unsigned char *)pp; le32enc(p, u & 0xffffffff); le32enc(p + 4, u >> 32); } #endif /* _COMPAT_ENDIAN_ENC_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/compat/flopen.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/compat/flopen.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/compat/flopen.h (revision 292449) @@ -1,103 +1,102 @@ /*- * Copyright (c) 2007 Dag-Erling Coïdan Smørgrav * 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 * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Derived from FreeBSD head/lib/libutil/flopen.c r193591 - * $P4: //depot/projects/trustedbsd/openbsm/compat/flopen.h#1 $ */ #include #include #include #include #include static int flopen(const char *path, int flags, ...) { int fd, operation, serrno, trunc; struct stat sb, fsb; mode_t mode; #ifdef O_EXLOCK flags &= ~O_EXLOCK; #endif mode = 0; if (flags & O_CREAT) { va_list ap; va_start(ap, flags); mode = (mode_t)va_arg(ap, int); /* mode_t promoted to int */ va_end(ap); } operation = LOCK_EX; if (flags & O_NONBLOCK) operation |= LOCK_NB; trunc = (flags & O_TRUNC); flags &= ~O_TRUNC; for (;;) { if ((fd = open(path, flags, mode)) == -1) /* non-existent or no access */ return (-1); if (flock(fd, operation) == -1) { /* unsupported or interrupted */ serrno = errno; (void)close(fd); errno = serrno; return (-1); } if (stat(path, &sb) == -1) { /* disappeared from under our feet */ (void)close(fd); continue; } if (fstat(fd, &fsb) == -1) { /* can't happen [tm] */ serrno = errno; (void)close(fd); errno = serrno; return (-1); } if (sb.st_dev != fsb.st_dev || sb.st_ino != fsb.st_ino) { /* changed under our feet */ (void)close(fd); continue; } if (trunc && ftruncate(fd, 0) != 0) { /* can't happen [tm] */ serrno = errno; (void)close(fd); errno = serrno; return (-1); } return (fd); } } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/compat/pidfile.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/compat/pidfile.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/compat/pidfile.h (revision 292449) @@ -1,293 +1,292 @@ /*- * Copyright (c) 2005 Pawel Jakub Dawidek * 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 AUTHORS 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 AUTHORS 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. * * Derived from FreeBSD head/lib/libutil/pidfile.c r231938 - * $P4: //depot/projects/trustedbsd/openbsm/compat/pidfile.h#1 $ */ #include #include #include #include #include #include #include #include #include #include #include #include "flopen.h" struct pidfh { int pf_fd; char pf_path[MAXPATHLEN + 1]; dev_t pf_dev; ino_t pf_ino; }; static int _pidfile_remove(struct pidfh *pfh, int freeit); static int pidfile_verify(const struct pidfh *pfh) { struct stat sb; if (pfh == NULL || pfh->pf_fd == -1) return (EINVAL); /* * Check remembered descriptor. */ if (fstat(pfh->pf_fd, &sb) == -1) return (errno); if (sb.st_dev != pfh->pf_dev || sb.st_ino != pfh->pf_ino) return (EINVAL); return (0); } static int pidfile_read(const char *path, pid_t *pidptr) { char buf[16], *endptr; int error, fd, i; fd = open(path, O_RDONLY); if (fd == -1) return (errno); i = read(fd, buf, sizeof(buf) - 1); error = errno; /* Remember errno in case close() wants to change it. */ close(fd); if (i == -1) return (error); else if (i == 0) return (EAGAIN); buf[i] = '\0'; *pidptr = strtol(buf, &endptr, 10); if (endptr != &buf[i]) return (EINVAL); return (0); } static struct pidfh * pidfile_open(const char *path, mode_t mode, pid_t *pidptr) { struct pidfh *pfh; struct stat sb; int error, fd, len, count; struct timespec rqtp; if (pidptr != NULL) *pidptr = -1; if (path == NULL) return (NULL); pfh = malloc(sizeof(*pfh)); if (pfh == NULL) return (NULL); len = snprintf(pfh->pf_path, sizeof(pfh->pf_path), "%s", path); if (len >= (int)sizeof(pfh->pf_path)) { free(pfh); errno = ENAMETOOLONG; return (NULL); } /* * Open the PID file and obtain exclusive lock. * We truncate PID file here only to remove old PID immediatelly, * PID file will be truncated again in pidfile_write(), so * pidfile_write() can be called multiple times. */ fd = flopen(pfh->pf_path, #ifdef O_CLOEXEC O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK | O_CLOEXEC, mode); #else O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode); #endif if (fd == -1) { if (errno == EWOULDBLOCK && pidptr != NULL) { count = 20; rqtp.tv_sec = 0; rqtp.tv_nsec = 5000000; for (;;) { errno = pidfile_read(pfh->pf_path, pidptr); if (errno != EAGAIN || --count == 0) break; nanosleep(&rqtp, 0); } if (errno == EAGAIN) *pidptr = -1; if (errno == 0 || errno == EAGAIN) errno = EEXIST; } free(pfh); return (NULL); } #ifndef O_CLOEXEC if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { error = errno; unlink(pfh->pf_path); close(fd); free(pfh); errno = error; return (NULL); } #endif /* * Remember file information, so in pidfile_write() we are sure we write * to the proper descriptor. */ if (fstat(fd, &sb) == -1) { error = errno; unlink(pfh->pf_path); close(fd); free(pfh); errno = error; return (NULL); } pfh->pf_fd = fd; pfh->pf_dev = sb.st_dev; pfh->pf_ino = sb.st_ino; return (pfh); } static int pidfile_write(struct pidfh *pfh) { char pidstr[16]; int error, fd; /* * Check remembered descriptor, so we don't overwrite some other * file if pidfile was closed and descriptor reused. */ errno = pidfile_verify(pfh); if (errno != 0) { /* * Don't close descriptor, because we are not sure if it's ours. */ return (-1); } fd = pfh->pf_fd; /* * Truncate PID file, so multiple calls of pidfile_write() are allowed. */ if (ftruncate(fd, 0) == -1) { error = errno; _pidfile_remove(pfh, 0); errno = error; return (-1); } snprintf(pidstr, sizeof(pidstr), "%u", getpid()); if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) { error = errno; _pidfile_remove(pfh, 0); errno = error; return (-1); } return (0); } static int pidfile_close(struct pidfh *pfh) { int error; error = pidfile_verify(pfh); if (error != 0) { errno = error; return (-1); } if (close(pfh->pf_fd) == -1) error = errno; free(pfh); if (error != 0) { errno = error; return (-1); } return (0); } static int _pidfile_remove(struct pidfh *pfh, int freeit) { int error; error = pidfile_verify(pfh); if (error != 0) { errno = error; return (-1); } if (unlink(pfh->pf_path) == -1) error = errno; if (close(pfh->pf_fd) == -1) { if (error == 0) error = errno; } if (freeit) free(pfh); else pfh->pf_fd = -1; if (error != 0) { errno = error; return (-1); } return (0); } static int pidfile_remove(struct pidfh *pfh) { return (_pidfile_remove(pfh, 1)); } #if 0 static int pidfile_fileno(const struct pidfh *pfh) { if (pfh == NULL || pfh->pf_fd == -1) { errno = EINVAL; return (-1); } return (pfh->pf_fd); } #endif Index: user/alc/PQ_LAUNDRY/contrib/openbsm/compat/queue.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/compat/queue.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/compat/queue.h (revision 292449) @@ -1,542 +1,541 @@ /*- * 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. * 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. * * @(#)queue.h 8.5 (Berkeley) 8/20/94 * * Derived from FreeBSD src/sys/sys/queue.h:1.63. - * $P4: //depot/projects/trustedbsd/openbsm/compat/queue.h#3 $ */ #ifndef _COMPAT_QUEUE_H_ #define _COMPAT_QUEUE_H_ #include /* * This file defines four types of data structures: singly-linked lists, * singly-linked tail queues, lists and tail queues. * * A singly-linked list is headed by a single forward pointer. The elements * are singly linked for minimum space and pointer manipulation overhead at * the expense of O(n) removal for arbitrary elements. New elements can be * added to the list after an existing element or at the head of the list. * Elements being removed from the head of the list should use the explicit * macro for this purpose for optimum efficiency. A singly-linked list may * only be traversed in the forward direction. Singly-linked lists are ideal * for applications with large datasets and few or no removals or for * implementing a LIFO queue. * * A singly-linked tail queue is headed by a pair of pointers, one to the * head of the list and the other to the tail of the list. The elements are * singly linked for minimum space and pointer manipulation overhead at the * expense of O(n) removal for arbitrary elements. New elements can be added * to the list after an existing element, at the head of the list, or at the * end of the list. Elements being removed from the head of the tail queue * should use the explicit macro for this purpose for optimum efficiency. * A singly-linked tail queue may only be traversed in the forward direction. * Singly-linked tail queues are ideal for applications with large datasets * and few or no removals or for implementing a FIFO queue. * * A list is headed by a single forward pointer (or an array of forward * pointers for a hash table header). The elements are doubly linked * so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before * or after an existing element or at the head of the list. A list * may only be traversed in the forward direction. * * A tail queue is headed by a pair of pointers, one to the head of the * list and the other to the tail of the list. The elements are doubly * linked so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before or * after an existing element, at the head of the list, or at the end of * the list. A tail queue may be traversed in either direction. * * For details on the use of these macros, see the queue(3) manual page. * * * SLIST LIST STAILQ TAILQ * _HEAD + + + + * _HEAD_INITIALIZER + + + + * _ENTRY + + + + * _INIT + + + + * _EMPTY + + + + * _FIRST + + + + * _NEXT + + + + * _PREV - - - + * _LAST - - + + * _FOREACH + + + + * _FOREACH_SAFE + + + + * _FOREACH_REVERSE - - - + * _FOREACH_REVERSE_SAFE - - - + * _INSERT_HEAD + + + + * _INSERT_BEFORE - + - + * _INSERT_AFTER + + + + * _INSERT_TAIL - - + + * _CONCAT - - + + * _REMOVE_HEAD + - + - * _REMOVE + + + + * */ #ifdef QUEUE_MACRO_DEBUG /* Store the last 2 places the queue element or head was altered */ struct qm_trace { char * lastfile; int lastline; char * prevfile; int prevline; }; #define TRACEBUF struct qm_trace trace; #define TRASHIT(x) do {(x) = (void *)-1;} while (0) #define QMD_TRACE_HEAD(head) do { \ (head)->trace.prevline = (head)->trace.lastline; \ (head)->trace.prevfile = (head)->trace.lastfile; \ (head)->trace.lastline = __LINE__; \ (head)->trace.lastfile = __FILE__; \ } while (0) #define QMD_TRACE_ELEM(elem) do { \ (elem)->trace.prevline = (elem)->trace.lastline; \ (elem)->trace.prevfile = (elem)->trace.lastfile; \ (elem)->trace.lastline = __LINE__; \ (elem)->trace.lastfile = __FILE__; \ } while (0) #else #define QMD_TRACE_ELEM(elem) #define QMD_TRACE_HEAD(head) #define TRACEBUF #define TRASHIT(x) #endif /* QUEUE_MACRO_DEBUG */ /* * Singly-linked List declarations. */ #define SLIST_HEAD(name, type) \ struct name { \ struct type *slh_first; /* first element */ \ } #define SLIST_HEAD_INITIALIZER(head) \ { NULL } #define SLIST_ENTRY(type) \ struct { \ struct type *sle_next; /* next element */ \ } /* * Singly-linked List functions. */ #define SLIST_EMPTY(head) ((head)->slh_first == NULL) #define SLIST_FIRST(head) ((head)->slh_first) #define SLIST_FOREACH(var, head, field) \ for ((var) = SLIST_FIRST((head)); \ (var); \ (var) = SLIST_NEXT((var), field)) #define SLIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = SLIST_FIRST((head)); \ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ (var) = (tvar)) #define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ for ((varp) = &SLIST_FIRST((head)); \ ((var) = *(varp)) != NULL; \ (varp) = &SLIST_NEXT((var), field)) #define SLIST_INIT(head) do { \ SLIST_FIRST((head)) = NULL; \ } while (0) #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ SLIST_NEXT((slistelm), field) = (elm); \ } while (0) #define SLIST_INSERT_HEAD(head, elm, field) do { \ SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ SLIST_FIRST((head)) = (elm); \ } while (0) #define SLIST_NEXT(elm, field) ((elm)->field.sle_next) #define SLIST_REMOVE(head, elm, type, field) do { \ if (SLIST_FIRST((head)) == (elm)) { \ SLIST_REMOVE_HEAD((head), field); \ } \ else { \ struct type *curelm = SLIST_FIRST((head)); \ while (SLIST_NEXT(curelm, field) != (elm)) \ curelm = SLIST_NEXT(curelm, field); \ SLIST_NEXT(curelm, field) = \ SLIST_NEXT(SLIST_NEXT(curelm, field), field); \ } \ TRASHIT((elm)->field.sle_next); \ } while (0) #define SLIST_REMOVE_HEAD(head, field) do { \ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ } while (0) /* * Singly-linked Tail queue declarations. */ #define STAILQ_HEAD(name, type) \ struct name { \ struct type *stqh_first;/* first element */ \ struct type **stqh_last;/* addr of last next element */ \ } #define STAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).stqh_first } #define STAILQ_ENTRY(type) \ struct { \ struct type *stqe_next; /* next element */ \ } /* * Singly-linked Tail queue functions. */ #define STAILQ_CONCAT(head1, head2) do { \ if (!STAILQ_EMPTY((head2))) { \ *(head1)->stqh_last = (head2)->stqh_first; \ (head1)->stqh_last = (head2)->stqh_last; \ STAILQ_INIT((head2)); \ } \ } while (0) #define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) #define STAILQ_FIRST(head) ((head)->stqh_first) #define STAILQ_FOREACH(var, head, field) \ for((var) = STAILQ_FIRST((head)); \ (var); \ (var) = STAILQ_NEXT((var), field)) #define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = STAILQ_FIRST((head)); \ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ (var) = (tvar)) #define STAILQ_INIT(head) do { \ STAILQ_FIRST((head)) = NULL; \ (head)->stqh_last = &STAILQ_FIRST((head)); \ } while (0) #define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ (head)->stqh_last = &STAILQ_NEXT((elm), field); \ STAILQ_NEXT((tqelm), field) = (elm); \ } while (0) #define STAILQ_INSERT_HEAD(head, elm, field) do { \ if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ (head)->stqh_last = &STAILQ_NEXT((elm), field); \ STAILQ_FIRST((head)) = (elm); \ } while (0) #define STAILQ_INSERT_TAIL(head, elm, field) do { \ STAILQ_NEXT((elm), field) = NULL; \ *(head)->stqh_last = (elm); \ (head)->stqh_last = &STAILQ_NEXT((elm), field); \ } while (0) #define STAILQ_LAST(head, type, field) \ (STAILQ_EMPTY((head)) ? \ NULL : \ ((struct type *) \ ((char *)((head)->stqh_last) - __offsetof(struct type, field)))) #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) #define STAILQ_REMOVE(head, elm, type, field) do { \ if (STAILQ_FIRST((head)) == (elm)) { \ STAILQ_REMOVE_HEAD((head), field); \ } \ else { \ struct type *curelm = STAILQ_FIRST((head)); \ while (STAILQ_NEXT(curelm, field) != (elm)) \ curelm = STAILQ_NEXT(curelm, field); \ if ((STAILQ_NEXT(curelm, field) = \ STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\ (head)->stqh_last = &STAILQ_NEXT((curelm), field);\ } \ TRASHIT((elm)->field.stqe_next); \ } while (0) #define STAILQ_REMOVE_HEAD(head, field) do { \ if ((STAILQ_FIRST((head)) = \ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ (head)->stqh_last = &STAILQ_FIRST((head)); \ } while (0) #define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \ if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \ (head)->stqh_last = &STAILQ_FIRST((head)); \ } while (0) /* * List declarations. */ #define LIST_HEAD(name, type) \ struct name { \ struct type *lh_first; /* first element */ \ } #define LIST_HEAD_INITIALIZER(head) \ { NULL } #define LIST_ENTRY(type) \ struct { \ struct type *le_next; /* next element */ \ struct type **le_prev; /* address of previous next element */ \ } /* * List functions. */ #if (defined(_KERNEL) && defined(INVARIANTS)) || defined(QUEUE_MACRO_DEBUG) #define QMD_LIST_CHECK_HEAD(head, field) do { \ if (LIST_FIRST((head)) != NULL && \ LIST_FIRST((head))->field.le_prev != \ &LIST_FIRST((head))) \ panic("Bad list head %p first->prev != head", (head)); \ } while (0) #define QMD_LIST_CHECK_NEXT(elm, field) do { \ if (LIST_NEXT((elm), field) != NULL && \ LIST_NEXT((elm), field)->field.le_prev != \ &((elm)->field.le_next)) \ panic("Bad link elm %p next->prev != elm", (elm)); \ } while (0) #define QMD_LIST_CHECK_PREV(elm, field) do { \ if (*(elm)->field.le_prev != (elm)) \ panic("Bad link elm %p prev->next != elm", (elm)); \ } while (0) #else #define QMD_LIST_CHECK_HEAD(head, field) #define QMD_LIST_CHECK_NEXT(elm, field) #define QMD_LIST_CHECK_PREV(elm, field) #endif /* (_KERNEL && INVARIANTS) || QUEUE_MACRO_DEBUG */ #define LIST_EMPTY(head) ((head)->lh_first == NULL) #define LIST_FIRST(head) ((head)->lh_first) #define LIST_FOREACH(var, head, field) \ for ((var) = LIST_FIRST((head)); \ (var); \ (var) = LIST_NEXT((var), field)) #define LIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = LIST_FIRST((head)); \ (var) && ((tvar) = LIST_NEXT((var), field), 1); \ (var) = (tvar)) #define LIST_INIT(head) do { \ LIST_FIRST((head)) = NULL; \ } while (0) #define LIST_INSERT_AFTER(listelm, elm, field) do { \ QMD_LIST_CHECK_NEXT(listelm, field); \ if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ LIST_NEXT((listelm), field)->field.le_prev = \ &LIST_NEXT((elm), field); \ LIST_NEXT((listelm), field) = (elm); \ (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ } while (0) #define LIST_INSERT_BEFORE(listelm, elm, field) do { \ QMD_LIST_CHECK_PREV(listelm, field); \ (elm)->field.le_prev = (listelm)->field.le_prev; \ LIST_NEXT((elm), field) = (listelm); \ *(listelm)->field.le_prev = (elm); \ (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ } while (0) #define LIST_INSERT_HEAD(head, elm, field) do { \ QMD_LIST_CHECK_HEAD((head), field); \ if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ LIST_FIRST((head)) = (elm); \ (elm)->field.le_prev = &LIST_FIRST((head)); \ } while (0) #define LIST_NEXT(elm, field) ((elm)->field.le_next) #define LIST_REMOVE(elm, field) do { \ QMD_LIST_CHECK_NEXT(elm, field); \ QMD_LIST_CHECK_PREV(elm, field); \ if (LIST_NEXT((elm), field) != NULL) \ LIST_NEXT((elm), field)->field.le_prev = \ (elm)->field.le_prev; \ *(elm)->field.le_prev = LIST_NEXT((elm), field); \ TRASHIT((elm)->field.le_next); \ TRASHIT((elm)->field.le_prev); \ } while (0) /* * Tail queue declarations. */ #define TAILQ_HEAD(name, type) \ struct name { \ struct type *tqh_first; /* first element */ \ struct type **tqh_last; /* addr of last next element */ \ TRACEBUF \ } #define TAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).tqh_first } #define TAILQ_ENTRY(type) \ struct { \ struct type *tqe_next; /* next element */ \ struct type **tqe_prev; /* address of previous next element */ \ TRACEBUF \ } /* * Tail queue functions. */ #define TAILQ_CONCAT(head1, head2, field) do { \ if (!TAILQ_EMPTY(head2)) { \ *(head1)->tqh_last = (head2)->tqh_first; \ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ (head1)->tqh_last = (head2)->tqh_last; \ TAILQ_INIT((head2)); \ QMD_TRACE_HEAD(head1); \ QMD_TRACE_HEAD(head2); \ } \ } while (0) #define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) #define TAILQ_FIRST(head) ((head)->tqh_first) #define TAILQ_FOREACH(var, head, field) \ for ((var) = TAILQ_FIRST((head)); \ (var); \ (var) = TAILQ_NEXT((var), field)) #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = TAILQ_FIRST((head)); \ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ (var) = (tvar)) #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ for ((var) = TAILQ_LAST((head), headname); \ (var); \ (var) = TAILQ_PREV((var), headname, field)) #define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ for ((var) = TAILQ_LAST((head), headname); \ (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ (var) = (tvar)) #define TAILQ_INIT(head) do { \ TAILQ_FIRST((head)) = NULL; \ (head)->tqh_last = &TAILQ_FIRST((head)); \ QMD_TRACE_HEAD(head); \ } while (0) #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ TAILQ_NEXT((elm), field)->field.tqe_prev = \ &TAILQ_NEXT((elm), field); \ else { \ (head)->tqh_last = &TAILQ_NEXT((elm), field); \ QMD_TRACE_HEAD(head); \ } \ TAILQ_NEXT((listelm), field) = (elm); \ (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ QMD_TRACE_ELEM(&(elm)->field); \ QMD_TRACE_ELEM(&listelm->field); \ } while (0) #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ TAILQ_NEXT((elm), field) = (listelm); \ *(listelm)->field.tqe_prev = (elm); \ (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ QMD_TRACE_ELEM(&(elm)->field); \ QMD_TRACE_ELEM(&listelm->field); \ } while (0) #define TAILQ_INSERT_HEAD(head, elm, field) do { \ if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ TAILQ_FIRST((head))->field.tqe_prev = \ &TAILQ_NEXT((elm), field); \ else \ (head)->tqh_last = &TAILQ_NEXT((elm), field); \ TAILQ_FIRST((head)) = (elm); \ (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ QMD_TRACE_HEAD(head); \ QMD_TRACE_ELEM(&(elm)->field); \ } while (0) #define TAILQ_INSERT_TAIL(head, elm, field) do { \ TAILQ_NEXT((elm), field) = NULL; \ (elm)->field.tqe_prev = (head)->tqh_last; \ *(head)->tqh_last = (elm); \ (head)->tqh_last = &TAILQ_NEXT((elm), field); \ QMD_TRACE_HEAD(head); \ QMD_TRACE_ELEM(&(elm)->field); \ } while (0) #define TAILQ_LAST(head, headname) \ (*(((struct headname *)((head)->tqh_last))->tqh_last)) #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) #define TAILQ_PREV(elm, headname, field) \ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) #define TAILQ_REMOVE(head, elm, field) do { \ if ((TAILQ_NEXT((elm), field)) != NULL) \ TAILQ_NEXT((elm), field)->field.tqe_prev = \ (elm)->field.tqe_prev; \ else { \ (head)->tqh_last = (elm)->field.tqe_prev; \ QMD_TRACE_HEAD(head); \ } \ *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ TRASHIT((elm)->field.tqe_next); \ TRASHIT((elm)->field.tqe_prev); \ QMD_TRACE_ELEM(&(elm)->field); \ } while (0) #endif /* !_COMPAT_QUEUE_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/compat/strlcat.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/compat/strlcat.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/compat/strlcat.h (revision 292449) @@ -1,67 +1,66 @@ /*- * 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. * * dollar OpenBSD: strlcat.c,v 1.2 1999/06/17 16:28:58 millert Exp dollar - * $P4: //depot/projects/trustedbsd/openbsm/compat/strlcat.h#3 $ */ /* * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters * will be copied. Always NUL terminates (unless siz <= strlen(dst)). * Returns strlen(src) + MIN(siz, strlen(initial dst)). * If retval >= siz, truncation occurred. */ static size_t strlcat(dst, src, siz) char *dst; const char *src; size_t siz; { char *d = dst; const char *s = src; size_t n = siz; size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end */ while (n-- != 0 && *d != '\0') d++; dlen = d - dst; n = siz - dlen; if (n == 0) return(dlen + strlen(s)); while (*s != '\0') { if (n != 1) { *d++ = *s; n--; } s++; } *d = '\0'; return(dlen + (s - src)); /* count does not include NUL */ } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/compat/strlcpy.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/compat/strlcpy.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/compat/strlcpy.h (revision 292449) @@ -1,63 +1,62 @@ /* * 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. * * dollar OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp dollar - * $P4: //depot/projects/trustedbsd/openbsm/compat/strlcpy.h#1 $ */ /* * 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. */ static size_t strlcpy(dst, src, siz) char *dst; const char *src; size_t siz; { char *d = dst; const char *s = src; 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 */ } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/config/config.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/config/config.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/config/config.h (revision 292449) @@ -1,311 +1,311 @@ /* config/config.h. Generated from config.h.in by configure. */ /* config/config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if you have the `alarm' function. */ #define HAVE_ALARM 1 /* Define to 1 if you have the `arc4random' function. */ #define HAVE_ARC4RANDOM 1 /* Define to 1 if you have the `arc4random_buf' function. */ #define HAVE_ARC4RANDOM_BUF 1 /* Define if audit system calls present */ #define HAVE_AUDIT_SYSCALLS /**/ /* Define to 1 if you have the `bzero' function. */ #define HAVE_BZERO 1 /* Define to 1 if you have the `cap_enter' function. */ #define HAVE_CAP_ENTER 1 /* Define to 1 if your system has a working `chown' function. */ #define HAVE_CHOWN 1 /* Define to 1 if you have the `clock_gettime' function. */ #define HAVE_CLOCK_GETTIME 1 /* Define to 1 if you have the `closefrom' function. */ #define HAVE_CLOSEFROM 1 /* Define to 1 if you have the header file. */ #define HAVE_DLFCN_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_ENDIAN_H */ /* Define to 1 if you have the `faccessat' function. */ #define HAVE_FACCESSAT 1 /* Define to 1 if you have the `fdopendir' function. */ #define HAVE_FDOPENDIR 1 /* Define to 1 if you have the `fork' function. */ #define HAVE_FORK 1 /* Define to 1 if you have the `fstatat' function. */ #define HAVE_FSTATAT 1 /* Define to 1 if you have the `ftruncate' function. */ #define HAVE_FTRUNCATE 1 /* Define if queue.h includes LIST_FIRST */ #define HAVE_FULL_QUEUE_H /**/ /* Define to 1 if you have the `getresgid' function. */ #define HAVE_GETRESGID 1 /* Define to 1 if you have the `getresuid' function. */ #define HAVE_GETRESUID 1 /* Define to 1 if you have the `gettimeofday' function. */ #define HAVE_GETTIMEOFDAY 1 /* Define to 1 if you have the `inet_ntoa' function. */ #define HAVE_INET_NTOA 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define if ipc_perm._key instead of key */ /* #undef HAVE_IPC_PERM__KEY */ /* Define if ipc_perm._seq instead of seq */ /* #undef HAVE_IPC_PERM__SEQ */ /* Define if ipc_perm.__key instead of key */ /* #undef HAVE_IPC_PERM___KEY */ /* Define if ipc_perm.__seq instead of seq */ /* #undef HAVE_IPC_PERM___SEQ */ /* Define to 1 if you have the `jail' function. */ #define HAVE_JAIL 1 /* Define to 1 if you have the `kqueue' function. */ #define HAVE_KQUEUE 1 /* Define to 1 if you have the header file. */ #define HAVE_MACHINE_ENDIAN_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MACH_MACH_H */ /* Define to 1 if your system has a GNU libc compatible `malloc' function, and to 0 otherwise. */ #define HAVE_MALLOC 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `memset' function. */ #define HAVE_MEMSET 1 /* Define to 1 if you have the `openat' function. */ #define HAVE_OPENAT 1 /* Define to 1 if you have the header file. */ #define HAVE_PRINTF_H 1 /* Define to 1 if you have the `pthread_condattr_setclock' function. */ #define HAVE_PTHREAD_CONDATTR_SETCLOCK 1 /* Define to 1 if you have the `pthread_cond_timedwait_relative_np' function. */ /* #undef HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP */ /* Define to 1 if you have the `pthread_mutex_lock' function. */ #define HAVE_PTHREAD_MUTEX_LOCK 1 /* Define to 1 if you have the header file. */ #define HAVE_PTHREAD_NP_H 1 /* Define to 1 if you have the `renameat' function. */ #define HAVE_RENAMEAT 1 /* Define to 1 if you have the `setproctitle' function. */ #define HAVE_SETPROCTITLE 1 /* Define to 1 if you have the `sigtimedwait' function. */ #define HAVE_SIGTIMEDWAIT 1 /* Define if sockaddr_storage.ss_len field exists */ #define HAVE_SOCKADDR_STORAGE_SS_LEN /**/ /* Define to 1 if `stat' has the bug that it succeeds when given the zero-length file name argument. */ /* #undef HAVE_STAT_EMPTY_STRING_BUG */ /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strchr' function. */ #define HAVE_STRCHR 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the `strftime' function. */ #define HAVE_STRFTIME 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strlcat' function. */ #define HAVE_STRLCAT 1 /* Define to 1 if you have the `strlcpy' function. */ #define HAVE_STRLCPY 1 /* Define to 1 if you have the `strndup' function. */ #define HAVE_STRNDUP 1 /* Define to 1 if you have the `strrchr' function. */ #define HAVE_STRRCHR 1 /* Define to 1 if you have the `strstr' function. */ #define HAVE_STRSTR 1 /* Define to 1 if you have the `strtol' function. */ #define HAVE_STRTOL 1 /* Define to 1 if you have the `strtoul' function. */ #define HAVE_STRTOUL 1 /* Define to 1 if `st_rdev' is a member of `struct stat'. */ #define HAVE_STRUCT_STAT_ST_RDEV 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_ENDIAN_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have that is POSIX.1 compatible. */ #define HAVE_SYS_WAIT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the `unlinkat' function. */ #define HAVE_UNLINKAT 1 /* Define to 1 if you have the `vfork' function. */ #define HAVE_VFORK 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_VFORK_H */ /* Define to 1 if you have the `vis' function. */ #define HAVE_VIS 1 /* Define to 1 if `fork' works. */ #define HAVE_WORKING_FORK 1 /* Define to 1 if `vfork' works. */ #define HAVE_WORKING_VFORK 1 /* Define to 1 if `lstat' dereferences a symlink specified with a trailing slash. */ #define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #define LT_OBJDIR ".libs/" /* Name of package */ #define PACKAGE "OpenBSM" /* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "trustedbsd-audit@TrustesdBSD.org" +#define PACKAGE_BUGREPORT "trustedbsd-audit@TrustedBSD.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "OpenBSM" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "OpenBSM 1.2-alpha3" +#define PACKAGE_STRING "OpenBSM 1.2-alpha4" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "openbsm" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "1.2-alpha3" +#define PACKAGE_VERSION "1.2-alpha4" /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE void /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define to 1 if you can safely include both and . */ #define TIME_WITH_SYS_TIME 1 /* Define to 1 if your declares `struct tm'. */ /* #undef TM_IN_SYS_TIME */ /* Define if compat/endian_enc.h is required */ /* #undef USE_COMPAT_ENDIAN_ENC_H */ /* Define if compat/endian.h is required */ /* #undef USE_COMPAT_ENDIAN_H */ /* Define if endian.h should be included */ /* #undef USE_ENDIAN_H */ /* Define if machine/endian.h should be included */ /* #undef USE_MACHINE_ENDIAN_H */ /* Define if uses Mach IPC for Triggers messages */ /* #undef USE_MACH_IPC */ /* Define to use native include files */ /* #undef USE_NATIVE_INCLUDES */ /* Define if sys/endian.h should be included */ #define USE_SYS_ENDIAN_H /**/ /* Version number of package */ -#define VERSION "1.2-alpha3" +#define VERSION "1.2-alpha4" /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a `char[]'. */ #define YYTEXT_POINTER 1 /* Use extended API on platforms that require it */ #define _GNU_SOURCE /**/ /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to `int' if doesn't define. */ /* #undef gid_t */ /* Define to rpl_malloc if the replacement function should be used. */ /* #undef malloc */ /* Define to `int' if does not define. */ /* #undef pid_t */ /* Define to `unsigned int' if does not define. */ /* #undef size_t */ /* Define to `int' if doesn't define. */ /* #undef uid_t */ /* Define as `fork' if `vfork' does not work. */ /* #undef vfork */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/configure =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/configure (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/configure (revision 292449) @@ -1,16026 +1,16035 @@ #! /bin/sh -# From configure.ac P4: //depot/projects/trustedbsd/openbsm/configure.ac#65 . # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for OpenBSM 1.2-alpha3. +# Generated by GNU Autoconf 2.69 for OpenBSM 1.2-alpha4. # -# Report bugs to . +# 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 -$0: trustedbsd-audit@TrustesdBSD.org about your system, +$0: trustedbsd-audit@TrustedBSD.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a 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='OpenBSM' PACKAGE_TARNAME='openbsm' -PACKAGE_VERSION='1.2-alpha3' -PACKAGE_STRING='OpenBSM 1.2-alpha3' -PACKAGE_BUGREPORT='trustedbsd-audit@TrustesdBSD.org' +PACKAGE_VERSION='1.2-alpha4' +PACKAGE_STRING='OpenBSM 1.2-alpha4' +PACKAGE_BUGREPORT='trustedbsd-audit@TrustedBSD.org' PACKAGE_URL='' ac_unique_file="bin/auditreduce/auditreduce.c" # 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_header_list= ac_func_list= ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS USE_MACH_IPC_FALSE USE_MACH_IPC_TRUE HAVE_AUDIT_SYSCALLS_FALSE HAVE_AUDIT_SYSCALLS_TRUE LIBOBJS am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR am__untar am__tar AMTAR am__leading_dot SET_MAKE mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc YFLAGS YACC CPP OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL AWK RANLIB STRIP ac_ct_AR AR DLLTOOL OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL LEXLIB LEX_OUTPUT_ROOT LEX INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC MIG USE_NATIVE_INCLUDES_FALSE USE_NATIVE_INCLUDES_TRUE MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE 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 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' ac_subst_files='' ac_user_opts=' enable_option_checking enable_maintainer_mode with_native_includes enable_shared enable_static with_pic enable_fast_install with_gnu_ld with_sysroot enable_libtool_lock enable_dependency_tracking ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP YACC YFLAGS' # 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' 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 ;; -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 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 OpenBSM 1.2-alpha3 to adapt to many kinds of systems. +\`configure' configures OpenBSM 1.2-alpha4 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] --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/openbsm] --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 OpenBSM 1.2-alpha3:";; + short | recursive ) echo "Configuration of OpenBSM 1.2-alpha4:";; 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-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer --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-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-native-includes Use the system native include files instead of those included with openbsm. --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --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). 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 YACC The `Yet Another Compiler Compiler' implementation to use. Defaults to the first program found out of: `bison -y', `byacc', `yacc'. YFLAGS The list of arguments that will be passed by default to $YACC. This script will default YFLAGS to the empty string to avoid a default value of `-d' given by some make applications. 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 . +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 -OpenBSM configure 1.2-alpha3 +OpenBSM configure 1.2-alpha4 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 trustedbsd-audit@TrustesdBSD.org ## -## ----------------------------------------------- ##" +( $as_echo "## ---------------------------------------------- ## +## Report this to trustedbsd-audit@TrustedBSD.org ## +## ---------------------------------------------- ##" ) | 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_member LINENO AGGR MEMBER VAR INCLUDES # ---------------------------------------------------- # Tries to find if the field MEMBER exists in type AGGR, after including # INCLUDES, setting cache variable VAR accordingly. ac_fn_c_check_member () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 $as_echo_n "checking for $2.$3... " >&6; } if eval \${$4+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (sizeof ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else eval "$4=no" 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=\$$4 { $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_member 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 OpenBSM $as_me 1.2-alpha3, which was +It was created by OpenBSM $as_me 1.2-alpha4, 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 as_fn_append ac_header_list " sys/time.h" as_fn_append ac_header_list " unistd.h" as_fn_append ac_func_list " alarm" # 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 config "$srcdir"/config; 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 config \"$srcdir\"/config" "$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. ac_config_headers="$ac_config_headers config/config.h" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then : enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 $as_echo "$USE_MAINTAINER_MODE" >&6; } if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE # --with-native-includes forces the use of the system bsm headers. # Check whether --with-native-includes was given. if test "${with_native_includes+set}" = set; then : withval=$with_native_includes; $as_echo "#define USE_NATIVE_INCLUDES /**/" >>confdefs.h use_native_includes=true else use_native_includes=false fi if $use_native_includes; then USE_NATIVE_INCLUDES_TRUE= USE_NATIVE_INCLUDES_FALSE='#' else USE_NATIVE_INCLUDES_TRUE='#' USE_NATIVE_INCLUDES_FALSE= fi for ac_prog in mig 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_path_MIG+:} false; then : $as_echo_n "(cached) " >&6 else case $MIG in [\\/]* | ?:[\\/]*) ac_cv_path_MIG="$MIG" # 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_MIG="$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 MIG=$ac_cv_path_MIG if test -n "$MIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MIG" >&5 $as_echo "$MIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$MIG" && break done # Checks for programs. 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 # 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' for ac_prog in flex lex 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_LEX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LEX"; then ac_cv_prog_LEX="$LEX" # 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_LEX="$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 LEX=$ac_cv_prog_LEX if test -n "$LEX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5 $as_echo "$LEX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$LEX" && break done test -n "$LEX" || LEX=":" if test "x$LEX" != "x:"; then cat >conftest.l <<_ACEOF %% a { ECHO; } b { REJECT; } c { yymore (); } d { yyless (1); } e { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument. */ yyless ((input () != 0)); } f { unput (yytext[0]); } . { BEGIN INITIAL; } %% #ifdef YYTEXT_POINTER extern char *yytext; #endif int main (void) { return ! yylex () + ! yywrap (); } _ACEOF { { ac_try="$LEX conftest.l" 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 "$LEX conftest.l") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex output file root" >&5 $as_echo_n "checking lex output file root... " >&6; } if ${ac_cv_prog_lex_root+:} false; then : $as_echo_n "(cached) " >&6 else if test -f lex.yy.c; then ac_cv_prog_lex_root=lex.yy elif test -f lexyy.c; then ac_cv_prog_lex_root=lexyy else as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5 $as_echo "$ac_cv_prog_lex_root" >&6; } LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root if test -z "${LEXLIB+set}"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex library" >&5 $as_echo_n "checking lex library... " >&6; } if ${ac_cv_lib_lex+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_LIBS=$LIBS ac_cv_lib_lex='none needed' for ac_lib in '' -lfl -ll; do LIBS="$ac_lib $ac_save_LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ `cat $LEX_OUTPUT_ROOT.c` _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_lex=$ac_lib fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext test "$ac_cv_lib_lex" != 'none needed' && break done LIBS=$ac_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5 $as_echo "$ac_cv_lib_lex" >&6; } test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5 $as_echo_n "checking whether yytext is a pointer... " >&6; } if ${ac_cv_prog_lex_yytext_pointer+:} false; then : $as_echo_n "(cached) " >&6 else # POSIX says lex can declare yytext either as a pointer or an array; the # default is implementation-dependent. Figure out which it is, since # not all implementations provide the %pointer and %array declarations. ac_cv_prog_lex_yytext_pointer=no ac_save_LIBS=$LIBS LIBS="$LEXLIB $ac_save_LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define YYTEXT_POINTER 1 `cat $LEX_OUTPUT_ROOT.c` _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_prog_lex_yytext_pointer=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5 $as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; } if test $ac_cv_prog_lex_yytext_pointer = yes; then $as_echo "#define YYTEXT_POINTER 1" >>confdefs.h fi rm -f conftest.l $LEX_OUTPUT_ROOT.c 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.2' macro_revision='1.3337' 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 { $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 "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; 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 "$with_gnu_ld" = yes; 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 case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) 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 "$lt_cv_path_NM" != "no"; 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 /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) 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; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # 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"; 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 $i != 17 # 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"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } 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 "$GCC" != yes; then reload_cmds=false fi ;; darwin*) if test "$GCC" = yes; 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 # which 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. # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. if ( test "$lt_cv_nm_interface" = "BSD nm" && 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 ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; 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) lt_cv_deplibs_check_method=pass_all ;; netbsd*) 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*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; 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 ;; 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 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=cru} { $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 "$ac_status" -eq 0; 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 "$ac_status" -ne 0; 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 "x$lt_cv_ar_at_file" = xno; 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 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 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 # 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 "$host_cpu" = ia64; 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 # 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 -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$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 -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/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 # and D for any global 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};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print 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 if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && 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 con'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* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$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 "$pipe_works" = yes; 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 "$GCC" = yes; 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; } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && 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 which ABI we are using. 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 which ABI we are using. 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 "$lt_cv_prog_gnu_ld" = yes; 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* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. 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*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|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" ;; ppc*-*linux*|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 x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. 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*) 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 "x$lt_cv_path_mainfest_tool" != xyes; 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 $_lt_result -eq 0; 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 cru libconftest.a conftest.o" >&5 $AR cru 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 $_lt_result -eq 0 && $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[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; 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 "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; 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 test -z "$pic_mode" && pic_mode=default # 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 # 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 "X${COLLECT_NAMES+set}" != Xset; 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 for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` # 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* if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; 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" # 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 x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; 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 "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; 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' ;; 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 "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; 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' ;; 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) 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' ;; # 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' ;; 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 which 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" # 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 x"$lt_cv_prog_compiler_pic_works" = xyes; 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 x"$lt_cv_prog_compiler_static_works" = xyes; 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 "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; 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 "$hard_links" = no; 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 "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=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 "$with_gnu_ld" = yes; 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 "$lt_use_gnu_ld_interface" = yes; 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 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 "$host_cpu" != ia64; 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 (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; 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 ;; 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 "$host_os" = linux-dietlibc; 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 "$tmp_diet" = no 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' ;; 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 "x$supports_anon_versioning" = xyes; 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 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 "x$supports_anon_versioning" = xyes; 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*) 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 can not *** 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 "$ld_shlibs" = no; 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 "$GCC" = yes && 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 "$host_cpu" = ia64; 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 AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". 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) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | 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 # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; 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,' if test "$GCC" = yes; 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 "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; 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 "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi 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_use_runtimelinking" = yes; 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 "${lt_cv_aix_libpath+set}" = 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 "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; 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 "${lt_cv_aix_libpath+set}" = 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 "$with_gnu_ld" = yes; 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 # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' 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~linknames=' archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $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 "$lt_cv_ld_force_load" = "yes"; 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*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; 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 "$GCC" = yes; 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 $output_objdir/$soname = $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 $output_objdir/$soname = $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 "$GCC" = yes && test "$with_gnu_ld" = no; 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 "$with_gnu_ld" = no; 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 "$GCC" = yes && test "$with_gnu_ld" = no; 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 x"$lt_cv_prog_compiler__b" = xyes; 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 "$with_gnu_ld" = no; 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 "$GCC" = yes; 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 "$lt_cv_irix_exported_symbol" = yes; 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 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 ;; netbsd*) 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*) 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__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; 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 case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; 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 "$GCC" = yes; 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 "$GCC" = yes; 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 "$GCC" = yes; 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 "x$host_vendor" = xsequent; 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 "$GCC" = yes; 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 can NOT 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 "$GCC" = yes; 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 x$host_vendor = xsni; 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 "$ld_shlibs" = no && 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 "$enable_shared" = yes && test "$GCC" = yes; 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 "$GCC" = yes; 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` 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" else 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 "$host_cpu" = ia64; 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 # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # 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}' else # 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' fi 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%'\''`; test $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} $libname${shared_ext}' 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 ;; 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' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; 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=yes 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 "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; 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 "$lt_cv_prog_gnu_ld" = yes; 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 ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-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 # Append ld.so.conf contents 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' ;; 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*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac 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 if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; 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 "$with_gnu_ld" = yes; 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=freebsd-elf 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 "$with_gnu_ld" = yes; 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 "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $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 "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # 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 "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; 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 "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; 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 ;; *) 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 "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && 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 "$cross_compiling" = yes; 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 -fvisbility=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 "x$lt_cv_dlopen_self" = xyes; 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 "$cross_compiling" = yes; 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 -fvisbility=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 which 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 "$can_build_shared" = "no" && 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 "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no 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 "$enable_shared" = yes || 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: +{ $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 + for ac_prog in 'bison -y' byacc 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_YACC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$YACC"; then ac_cv_prog_YACC="$YACC" # 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_YACC="$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 YACC=$ac_cv_prog_YACC if test -n "$YACC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5 $as_echo "$YACC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$YACC" && break done test -n "$YACC" || YACC="yacc" am__api_version='1.12' { $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 case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " 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}" != 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; } { $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 DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # 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 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=OpenBSM - VERSION=1.2-alpha3 + VERSION=1.2-alpha4 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. 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}' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' 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 library containing dlsym" >&5 $as_echo_n "checking for library containing dlsym... " >&6; } if ${ac_cv_search_dlsym+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$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 dlsym (); int main () { return dlsym (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlsym=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlsym+:} false; then : break fi done if ${ac_cv_search_dlsym+:} false; then : else ac_cv_search_dlsym=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlsym" >&5 $as_echo "$ac_cv_search_dlsym" >&6; } ac_res=$ac_cv_search_dlsym if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5 $as_echo_n "checking for library containing pthread_create... " >&6; } if ${ac_cv_search_pthread_create+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$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 pthread_create (); int main () { return pthread_create (); ; return 0; } _ACEOF for ac_lib in '' pthread; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_pthread_create=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_pthread_create+:} false; then : break fi done if ${ac_cv_search_pthread_create+:} false; then : else ac_cv_search_pthread_create=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_create" >&5 $as_echo "$ac_cv_search_pthread_create" >&6; } ac_res=$ac_cv_search_pthread_create if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 $as_echo_n "checking for library containing clock_gettime... " >&6; } if ${ac_cv_search_clock_gettime+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$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 clock_gettime (); int main () { return clock_gettime (); ; return 0; } _ACEOF for ac_lib in '' rt; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_clock_gettime=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_clock_gettime+:} false; then : break fi done if ${ac_cv_search_clock_gettime+:} false; then : else ac_cv_search_clock_gettime=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 $as_echo "$ac_cv_search_clock_gettime" >&6; } ac_res=$ac_cv_search_clock_gettime if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing SSL_connect" >&5 $as_echo_n "checking for library containing SSL_connect... " >&6; } if ${ac_cv_search_SSL_connect+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$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 SSL_connect (); int main () { return SSL_connect (); ; return 0; } _ACEOF for ac_lib in '' ssl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_SSL_connect=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_SSL_connect+:} false; then : break fi done if ${ac_cv_search_SSL_connect+:} false; then : else ac_cv_search_SSL_connect=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_SSL_connect" >&5 $as_echo "$ac_cv_search_SSL_connect" >&6; } ac_res=$ac_cv_search_SSL_connect if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing humanize_number" >&5 $as_echo_n "checking for library containing humanize_number... " >&6; } if ${ac_cv_search_humanize_number+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$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 humanize_number (); int main () { return humanize_number (); ; return 0; } _ACEOF for ac_lib in '' util; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_humanize_number=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_humanize_number+:} false; then : break fi done if ${ac_cv_search_humanize_number+:} false; then : else ac_cv_search_humanize_number=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_humanize_number" >&5 $as_echo "$ac_cv_search_humanize_number" >&6; } ac_res=$ac_cv_search_humanize_number if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pidfile_open" >&5 $as_echo_n "checking for library containing pidfile_open... " >&6; } if ${ac_cv_search_pidfile_open+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$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 pidfile_open (); int main () { return pidfile_open (); ; return 0; } _ACEOF for ac_lib in '' util; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_pidfile_open=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_pidfile_open+:} false; then : break fi done if ${ac_cv_search_pidfile_open+:} false; then : else ac_cv_search_pidfile_open=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pidfile_open" >&5 $as_echo "$ac_cv_search_pidfile_open" >&6; } ac_res=$ac_cv_search_pidfile_open if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi # Checks for header files. { $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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5 $as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; } if ${ac_cv_header_sys_wait_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifndef WEXITSTATUS # define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif int main () { int s; wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_sys_wait_h=yes else ac_cv_header_sys_wait_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5 $as_echo "$ac_cv_header_sys_wait_h" >&6; } if test $ac_cv_header_sys_wait_h = yes; then $as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h fi for ac_header in mach/mach.h stdint.h pthread_np.h printf.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 $as_echo "#define _GNU_SOURCE /**/" >>confdefs.h # Checks for typedefs, structures, and compiler characteristics. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 $as_echo_n "checking for uid_t in sys/types.h... " >&6; } if ${ac_cv_type_uid_t+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "uid_t" >/dev/null 2>&1; then : ac_cv_type_uid_t=yes else ac_cv_type_uid_t=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 $as_echo "$ac_cv_type_uid_t" >&6; } if test $ac_cv_type_uid_t = no; then $as_echo "#define uid_t int" >>confdefs.h $as_echo "#define gid_t int" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" if test "x$ac_cv_type_pid_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi ac_fn_c_check_member "$LINENO" "struct stat" "st_rdev" "ac_cv_member_struct_stat_st_rdev" "$ac_includes_default" if test "x$ac_cv_member_struct_stat_st_rdev" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_STAT_ST_RDEV 1 _ACEOF fi ac_fn_c_check_member "$LINENO" "struct ipc_perm" "__key" "ac_cv_member_struct_ipc_perm___key" " #include #include " if test "x$ac_cv_member_struct_ipc_perm___key" = xyes; then : $as_echo "#define HAVE_IPC_PERM___KEY /**/" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct ipc_perm" "_key" "ac_cv_member_struct_ipc_perm__key" " #include #include " if test "x$ac_cv_member_struct_ipc_perm__key" = xyes; then : $as_echo "#define HAVE_IPC_PERM__KEY /**/" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct ipc_perm" "__seq" "ac_cv_member_struct_ipc_perm___seq" " #include #include " if test "x$ac_cv_member_struct_ipc_perm___seq" = xyes; then : $as_echo "#define HAVE_IPC_PERM___SEQ /**/" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct ipc_perm" "_seq" "ac_cv_member_struct_ipc_perm__seq" " #include #include " if test "x$ac_cv_member_struct_ipc_perm__seq" = xyes; then : $as_echo "#define HAVE_IPC_PERM__SEQ /**/" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct sockaddr_storage" "ss_len" "ac_cv_member_struct_sockaddr_storage_ss_len" " #include #include " if test "x$ac_cv_member_struct_sockaddr_storage_ss_len" = xyes; then : $as_echo "#define HAVE_SOCKADDR_STORAGE_SS_LEN /**/" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if ${ac_cv_header_time+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 $as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } if ${ac_cv_struct_tm+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct tm tm; int *p = &tm.tm_sec; return !p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_struct_tm=time.h else ac_cv_struct_tm=sys/time.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 $as_echo "$ac_cv_struct_tm" >&6; } if test $ac_cv_struct_tm = sys/time.h; then $as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h fi # Checks for library functions. for ac_header in unistd.h do : ac_fn_c_check_header_mongrel "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" if test "x$ac_cv_header_unistd_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UNISTD_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working chown" >&5 $as_echo_n "checking for working chown... " >&6; } if ${ac_cv_func_chown_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_chown_works=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default #include int main () { char *f = "conftest.chown"; struct stat before, after; if (creat (f, 0600) < 0) return 1; if (stat (f, &before) < 0) return 1; if (chown (f, (uid_t) -1, (gid_t) -1) == -1) return 1; if (stat (f, &after) < 0) return 1; return ! (before.st_uid == after.st_uid && before.st_gid == after.st_gid); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_chown_works=yes else ac_cv_func_chown_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f conftest.chown fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_chown_works" >&5 $as_echo "$ac_cv_func_chown_works" >&6; } if test $ac_cv_func_chown_works = yes; then $as_echo "#define HAVE_CHOWN 1" >>confdefs.h fi for ac_header in vfork.h do : ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default" if test "x$ac_cv_header_vfork_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VFORK_H 1 _ACEOF fi done for ac_func in fork 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 if test "x$ac_cv_func_fork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5 $as_echo_n "checking for working fork... " >&6; } if ${ac_cv_func_fork_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_fork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* By Ruediger Kuhlmann. */ return fork () < 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_fork_works=yes else ac_cv_func_fork_works=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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5 $as_echo "$ac_cv_func_fork_works" >&6; } else ac_cv_func_fork_works=$ac_cv_func_fork fi if test "x$ac_cv_func_fork_works" = xcross; then case $host in *-*-amigaos* | *-*-msdosdjgpp*) # Override, as these systems have only a dummy fork() stub ac_cv_func_fork_works=no ;; *) ac_cv_func_fork_works=yes ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} fi ac_cv_func_vfork_works=$ac_cv_func_vfork if test "x$ac_cv_func_vfork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5 $as_echo_n "checking for working vfork... " >&6; } if ${ac_cv_func_vfork_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_vfork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Thanks to Paul Eggert for this test. */ $ac_includes_default #include #ifdef HAVE_VFORK_H # include #endif /* On some sparc systems, changes by the child to local and incoming argument registers are propagated back to the parent. The compiler is told about this with #include , but some compilers (e.g. gcc -O) don't grok . Test for this by using a static variable whose address is put into a register that is clobbered by the vfork. */ static void #ifdef __cplusplus sparc_address_test (int arg) # else sparc_address_test (arg) int arg; #endif { static pid_t child; if (!child) { child = vfork (); if (child < 0) { perror ("vfork"); _exit(2); } if (!child) { arg = getpid(); write(-1, "", 0); _exit (arg); } } } int main () { pid_t parent = getpid (); pid_t child; sparc_address_test (0); child = vfork (); if (child == 0) { /* Here is another test for sparc vfork register problems. This test uses lots of local variables, at least as many local variables as main has allocated so far including compiler temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should reuse the register of parent for one of the local variables, since it will think that parent can't possibly be used any more in this routine. Assigning to the local variable will thus munge parent in the parent process. */ pid_t p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); /* Convince the compiler that p..p7 are live; otherwise, it might use the same hardware register for all 8 local variables. */ if (p != p1 || p != p2 || p != p3 || p != p4 || p != p5 || p != p6 || p != p7) _exit(1); /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent from child file descriptors. If the child closes a descriptor before it execs or exits, this munges the parent's descriptor as well. Test for this by closing stdout in the child. */ _exit(close(fileno(stdout)) != 0); } else { int status; struct stat st; while (wait(&status) != child) ; return ( /* Was there some problem with vforking? */ child < 0 /* Did the child fail? (This shouldn't happen.) */ || status /* Did the vfork/compiler bug occur? */ || parent != getpid() /* Did the file descriptor bug occur? */ || fstat(fileno(stdout), &st) != 0 ); } } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_vfork_works=yes else ac_cv_func_vfork_works=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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5 $as_echo "$ac_cv_func_vfork_works" >&6; } fi; if test "x$ac_cv_func_fork_works" = xcross; then ac_cv_func_vfork_works=$ac_cv_func_vfork { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} fi if test "x$ac_cv_func_vfork_works" = xyes; then $as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h else $as_echo "#define vfork fork" >>confdefs.h fi if test "x$ac_cv_func_fork_works" = xyes; then $as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h fi for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 $as_echo_n "checking for GNU libc compatible malloc... " >&6; } if ${ac_cv_func_malloc_0_nonnull+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_malloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *malloc (); #endif int main () { return ! malloc (0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_malloc_0_nonnull=yes else ac_cv_func_malloc_0_nonnull=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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 $as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } if test $ac_cv_func_malloc_0_nonnull = yes; then : $as_echo "#define HAVE_MALLOC 1" >>confdefs.h else $as_echo "#define HAVE_MALLOC 0" >>confdefs.h case " $LIBOBJS " in *" malloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS malloc.$ac_objext" ;; esac $as_echo "#define malloc rpl_malloc" >>confdefs.h fi for ac_header in $ac_header_list 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_func in $ac_func_list 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working mktime" >&5 $as_echo_n "checking for working mktime... " >&6; } if ${ac_cv_func_working_mktime+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_working_mktime=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Test program from Paul Eggert and Tony Leneis. */ #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include #include #ifdef HAVE_UNISTD_H # include #endif #ifndef HAVE_ALARM # define alarm(X) /* empty */ #endif /* Work around redefinition to rpl_putenv by other config tests. */ #undef putenv static time_t time_t_max; static time_t time_t_min; /* Values we'll use to set the TZ environment variable. */ static const char *tz_strings[] = { (const char *) 0, "TZ=GMT0", "TZ=JST-9", "TZ=EST+3EDT+2,M10.1.0/00:00:00,M2.3.0/00:00:00" }; #define N_STRINGS (sizeof (tz_strings) / sizeof (tz_strings[0])) /* Return 0 if mktime fails to convert a date in the spring-forward gap. Based on a problem report from Andreas Jaeger. */ static int spring_forward_gap () { /* glibc (up to about 1998-10-07) failed this test. */ struct tm tm; /* Use the portable POSIX.1 specification "TZ=PST8PDT,M4.1.0,M10.5.0" instead of "TZ=America/Vancouver" in order to detect the bug even on systems that don't support the Olson extension, or don't have the full zoneinfo tables installed. */ putenv ((char*) "TZ=PST8PDT,M4.1.0,M10.5.0"); tm.tm_year = 98; tm.tm_mon = 3; tm.tm_mday = 5; tm.tm_hour = 2; tm.tm_min = 0; tm.tm_sec = 0; tm.tm_isdst = -1; return mktime (&tm) != (time_t) -1; } static int mktime_test1 (time_t now) { struct tm *lt; return ! (lt = localtime (&now)) || mktime (lt) == now; } static int mktime_test (time_t now) { return (mktime_test1 (now) && mktime_test1 ((time_t) (time_t_max - now)) && mktime_test1 ((time_t) (time_t_min + now))); } static int irix_6_4_bug () { /* Based on code from Ariel Faigon. */ struct tm tm; tm.tm_year = 96; tm.tm_mon = 3; tm.tm_mday = 0; tm.tm_hour = 0; tm.tm_min = 0; tm.tm_sec = 0; tm.tm_isdst = -1; mktime (&tm); return tm.tm_mon == 2 && tm.tm_mday == 31; } static int bigtime_test (int j) { struct tm tm; time_t now; tm.tm_year = tm.tm_mon = tm.tm_mday = tm.tm_hour = tm.tm_min = tm.tm_sec = j; now = mktime (&tm); if (now != (time_t) -1) { struct tm *lt = localtime (&now); if (! (lt && lt->tm_year == tm.tm_year && lt->tm_mon == tm.tm_mon && lt->tm_mday == tm.tm_mday && lt->tm_hour == tm.tm_hour && lt->tm_min == tm.tm_min && lt->tm_sec == tm.tm_sec && lt->tm_yday == tm.tm_yday && lt->tm_wday == tm.tm_wday && ((lt->tm_isdst < 0 ? -1 : 0 < lt->tm_isdst) == (tm.tm_isdst < 0 ? -1 : 0 < tm.tm_isdst)))) return 0; } return 1; } static int year_2050_test () { /* The correct answer for 2050-02-01 00:00:00 in Pacific time, ignoring leap seconds. */ unsigned long int answer = 2527315200UL; struct tm tm; time_t t; tm.tm_year = 2050 - 1900; tm.tm_mon = 2 - 1; tm.tm_mday = 1; tm.tm_hour = tm.tm_min = tm.tm_sec = 0; tm.tm_isdst = -1; /* Use the portable POSIX.1 specification "TZ=PST8PDT,M4.1.0,M10.5.0" instead of "TZ=America/Vancouver" in order to detect the bug even on systems that don't support the Olson extension, or don't have the full zoneinfo tables installed. */ putenv ((char*) "TZ=PST8PDT,M4.1.0,M10.5.0"); t = mktime (&tm); /* Check that the result is either a failure, or close enough to the correct answer that we can assume the discrepancy is due to leap seconds. */ return (t == (time_t) -1 || (0 < t && answer - 120 <= t && t <= answer + 120)); } int main () { time_t t, delta; int i, j; /* This test makes some buggy mktime implementations loop. Give up after 60 seconds; a mktime slower than that isn't worth using anyway. */ alarm (60); for (;;) { t = (time_t_max << 1) + 1; if (t <= time_t_max) break; time_t_max = t; } time_t_min = - ((time_t) ~ (time_t) 0 == (time_t) -1) - time_t_max; delta = time_t_max / 997; /* a suitable prime number */ for (i = 0; i < N_STRINGS; i++) { if (tz_strings[i]) putenv ((char*) tz_strings[i]); for (t = 0; t <= time_t_max - delta; t += delta) if (! mktime_test (t)) return 1; if (! (mktime_test ((time_t) 1) && mktime_test ((time_t) (60 * 60)) && mktime_test ((time_t) (60 * 60 * 24)))) return 1; for (j = 1; ; j <<= 1) if (! bigtime_test (j)) return 1; else if (INT_MAX / 2 < j) break; if (! bigtime_test (INT_MAX)) return 1; } return ! (irix_6_4_bug () && spring_forward_gap () && year_2050_test ()); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_working_mktime=yes else ac_cv_func_working_mktime=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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_working_mktime" >&5 $as_echo "$ac_cv_func_working_mktime" >&6; } if test $ac_cv_func_working_mktime = no; then case " $LIBOBJS " in *" mktime.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS mktime.$ac_objext" ;; esac 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether lstat correctly handles trailing slash" >&5 $as_echo_n "checking whether lstat correctly handles trailing slash... " >&6; } if ${ac_cv_func_lstat_dereferences_slashed_symlink+:} false; then : $as_echo_n "(cached) " >&6 else rm -f conftest.sym conftest.file echo >conftest.file if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then if test "$cross_compiling" = yes; then : ac_cv_func_lstat_dereferences_slashed_symlink=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { struct stat sbuf; /* Linux will dereference the symlink and fail, as required by POSIX. That is better in the sense that it means we will not have to compile and use the lstat wrapper. */ return lstat ("conftest.sym/", &sbuf) == 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_lstat_dereferences_slashed_symlink=yes else ac_cv_func_lstat_dereferences_slashed_symlink=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi else # If the `ln -s' command failed, then we probably don't even # have an lstat function. ac_cv_func_lstat_dereferences_slashed_symlink=no fi rm -f conftest.sym conftest.file fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5 $as_echo "$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; } test $ac_cv_func_lstat_dereferences_slashed_symlink = yes && cat >>confdefs.h <<_ACEOF #define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 _ACEOF if test "x$ac_cv_func_lstat_dereferences_slashed_symlink" = xno; then case " $LIBOBJS " in *" lstat.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS lstat.$ac_objext" ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat accepts an empty string" >&5 $as_echo_n "checking whether stat accepts an empty string... " >&6; } if ${ac_cv_func_stat_empty_string_bug+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_stat_empty_string_bug=yes else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { struct stat sbuf; return stat ("", &sbuf) == 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_stat_empty_string_bug=no else ac_cv_func_stat_empty_string_bug=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_stat_empty_string_bug" >&5 $as_echo "$ac_cv_func_stat_empty_string_bug" >&6; } if test $ac_cv_func_stat_empty_string_bug = yes; then case " $LIBOBJS " in *" stat.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS stat.$ac_objext" ;; esac cat >>confdefs.h <<_ACEOF #define HAVE_STAT_EMPTY_STRING_BUG 1 _ACEOF fi for ac_func in strftime do : ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime" if test "x$ac_cv_func_strftime" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRFTIME 1 _ACEOF else # strftime is in -lintl on SCO UNIX. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5 $as_echo_n "checking for strftime in -lintl... " >&6; } if ${ac_cv_lib_intl_strftime+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lintl $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 strftime (); int main () { return strftime (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_intl_strftime=yes else ac_cv_lib_intl_strftime=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_intl_strftime" >&5 $as_echo "$ac_cv_lib_intl_strftime" >&6; } if test "x$ac_cv_lib_intl_strftime" = xyes; then : $as_echo "#define HAVE_STRFTIME 1" >>confdefs.h LIBS="-lintl $LIBS" fi fi done for ac_func in arc4random arc4random_buf bzero cap_enter clock_gettime closefrom faccessat fdopendir fstatat ftruncate getresgid getresuid gettimeofday inet_ntoa jail kqueue memset openat pthread_cond_timedwait_relative_np pthread_condattr_setclock pthread_mutex_lock renameat setproctitle sigtimedwait strchr strerror strlcat strlcpy strndup strrchr strstr strtol strtoul unlinkat vis 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 # sys/queue.h exists on most systems, but its capabilities vary a great deal. # test for LIST_FIRST and TAILQ_FOREACH_SAFE, which appears to not exist in # all of them, and are necessary for OpenBSM. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #ifndef LIST_FIRST #error LIST_FIRST missing #endif #ifndef TAILQ_FOREACH_SAFE #error TAILQ_FOREACH_SAFE #endif ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : $as_echo "#define HAVE_FULL_QUEUE_H /**/" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext # Systems may not define key audit system calls, in which case libbsm cannot # depend on them or it will generate link-time or run-time errors. Test for # just one. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include extern int auditon(int, void *, int); int main () { int err; err = auditon(0, NULL, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : $as_echo "#define HAVE_AUDIT_SYSCALLS /**/" >>confdefs.h have_audit_syscalls=true else have_audit_syscalls=false fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if $have_audit_syscalls; then HAVE_AUDIT_SYSCALLS_TRUE= HAVE_AUDIT_SYSCALLS_FALSE='#' else HAVE_AUDIT_SYSCALLS_TRUE='#' HAVE_AUDIT_SYSCALLS_FALSE= fi # # We rely on the BSD be32toh() and be32enc()-style endian macros to perform # byte order conversions. Availability of these varies considerably -- in # general, a system might have neither, be32toh(), or be32toh() and be32enc(). # There is also variation in which headers are even present, and whether they # are macros or functions. Try to organise the world into some simpler cases. # The following macros may be set at the end: # # USE_ENDIAN_H # USE_SYS_ENDIAN_H # USE_MACHINE_ENDIAN_H # USE_COMPAT_ENDIAN_H # USE_COMPAT_ENDIAN_ENC_H # # First, decide which system endian.h to use. # for ac_header in endian.h do : ac_fn_c_check_header_mongrel "$LINENO" "endian.h" "ac_cv_header_endian_h" "$ac_includes_default" if test "x$ac_cv_header_endian_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ENDIAN_H 1 _ACEOF have_endian_h=yes else have_endian_h=no fi done for ac_header in sys/endian.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/endian.h" "ac_cv_header_sys_endian_h" "$ac_includes_default" if test "x$ac_cv_header_sys_endian_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_ENDIAN_H 1 _ACEOF have_sys_endian_h=yes else have_sys_endian_h=no fi done for ac_header in machine/endian.h do : ac_fn_c_check_header_mongrel "$LINENO" "machine/endian.h" "ac_cv_header_machine_endian_h" "$ac_includes_default" if test "x$ac_cv_header_machine_endian_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MACHINE_ENDIAN_H 1 _ACEOF have_machine_endian_h=yes else have_machine_endian_h=no fi done if test $have_endian_h = yes; then $as_echo "#define USE_ENDIAN_H /**/" >>confdefs.h elif test $have_sys_endian_h = yes; then $as_echo "#define USE_SYS_ENDIAN_H /**/" >>confdefs.h elif test $have_machine_endian_h = yes; then $as_echo "#define USE_MACHINE_ENDIAN_H /**/" >>confdefs.h else as_fn_error $? "no endian.h" "$LINENO" 5 fi # # Next, decide if we need to supplement with compat headers. # cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef USE_ENDIAN_H #include #endif #ifdef USE_SYS_ENDIAN_H #include #endif #ifdef USE_MACHINE_ENDIAN_H #include #endif int main () { (void)be32toh(0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : else $as_echo "#define USE_COMPAT_ENDIAN_H /**/" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: using compat/endian.h" >&5 $as_echo "using compat/endian.h" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef USE_ENDIAN_H #include #endif #ifdef USE_SYS_ENDIAN_H #include #endif #ifdef USE_MACHINE_ENDIAN_H #include #endif #ifdef USE_COMPAT_ENDIAN_H #include "compat/endian.h" #endif #include int main () { int i; i = bswap16(0); i = bswap32(0); i = bswap64(0); be32enc(NULL, 0); i = htole64(0); i = le64toh(0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : else $as_echo "#define USE_COMPAT_ENDIAN_ENC_H /**/" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: using compat/endian_enc.h" >&5 $as_echo "using compat/endian_enc.h" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext # Check to see if Mach IPC is used for trigger messages. If so, use Mach IPC # instead of the default for sending trigger messages to the audit components. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /usr/include/mach/audit_triggers.defs" >&5 $as_echo_n "checking for /usr/include/mach/audit_triggers.defs... " >&6; } if ${ac_cv_file__usr_include_mach_audit_triggers_defs+:} false; then : $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "/usr/include/mach/audit_triggers.defs"; then ac_cv_file__usr_include_mach_audit_triggers_defs=yes else ac_cv_file__usr_include_mach_audit_triggers_defs=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file__usr_include_mach_audit_triggers_defs" >&5 $as_echo "$ac_cv_file__usr_include_mach_audit_triggers_defs" >&6; } if test "x$ac_cv_file__usr_include_mach_audit_triggers_defs" = xyes; then : $as_echo "#define USE_MACH_IPC /**/" >>confdefs.h use_mach_ipc=true else use_mach_ipc=false fi if $use_mach_ipc; then USE_MACH_IPC_TRUE= USE_MACH_IPC_FALSE='#' else USE_MACH_IPC_TRUE='#' USE_MACH_IPC_FALSE= fi ac_config_files="$ac_config_files Makefile bin/Makefile bin/audit/Makefile bin/auditd/Makefile bin/auditdistd/Makefile bin/auditfilterd/Makefile bin/auditreduce/Makefile bin/praudit/Makefile bsm/Makefile libauditd/Makefile libbsm/Makefile modules/Makefile modules/auditfilter_noop/Makefile man/Makefile sys/Makefile sys/bsm/Makefile test/Makefile test/bsm/Makefile tools/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}' DEFS=-DHAVE_CONFIG_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 if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_NATIVE_INCLUDES_TRUE}" && test -z "${USE_NATIVE_INCLUDES_FALSE}"; then as_fn_error $? "conditional \"USE_NATIVE_INCLUDES\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi { $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 -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 -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${HAVE_AUDIT_SYSCALLS_TRUE}" && test -z "${HAVE_AUDIT_SYSCALLS_FALSE}"; then as_fn_error $? "conditional \"HAVE_AUDIT_SYSCALLS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_MACH_IPC_TRUE}" && test -z "${USE_MACH_IPC_FALSE}"; then as_fn_error $? "conditional \"USE_MACH_IPC\" 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 OpenBSM $as_me 1.2-alpha3, which was +This file was extended by OpenBSM $as_me 1.2-alpha4, 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 case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" 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 --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands -Report bugs to ." +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="\\ -OpenBSM config.status 1.2-alpha3 +OpenBSM config.status 1.2-alpha4 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;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --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 # # 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"`' 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_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"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $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"`' sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $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"`' 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_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ nm_file_list_spec \ 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; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) 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 \ sys_lib_dlsearch_path_spec; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which 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' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" _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 "config/config.h") CONFIG_HEADERS="$CONFIG_HEADERS config/config.h" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "bin/Makefile") CONFIG_FILES="$CONFIG_FILES bin/Makefile" ;; "bin/audit/Makefile") CONFIG_FILES="$CONFIG_FILES bin/audit/Makefile" ;; "bin/auditd/Makefile") CONFIG_FILES="$CONFIG_FILES bin/auditd/Makefile" ;; "bin/auditdistd/Makefile") CONFIG_FILES="$CONFIG_FILES bin/auditdistd/Makefile" ;; "bin/auditfilterd/Makefile") CONFIG_FILES="$CONFIG_FILES bin/auditfilterd/Makefile" ;; "bin/auditreduce/Makefile") CONFIG_FILES="$CONFIG_FILES bin/auditreduce/Makefile" ;; "bin/praudit/Makefile") CONFIG_FILES="$CONFIG_FILES bin/praudit/Makefile" ;; "bsm/Makefile") CONFIG_FILES="$CONFIG_FILES bsm/Makefile" ;; "libauditd/Makefile") CONFIG_FILES="$CONFIG_FILES libauditd/Makefile" ;; "libbsm/Makefile") CONFIG_FILES="$CONFIG_FILES libbsm/Makefile" ;; "modules/Makefile") CONFIG_FILES="$CONFIG_FILES modules/Makefile" ;; "modules/auditfilter_noop/Makefile") CONFIG_FILES="$CONFIG_FILES modules/auditfilter_noop/Makefile" ;; "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; "sys/Makefile") CONFIG_FILES="$CONFIG_FILES sys/Makefile" ;; "sys/bsm/Makefile") CONFIG_FILES="$CONFIG_FILES sys/bsm/Makefile" ;; "test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;; "test/bsm/Makefile") CONFIG_FILES="$CONFIG_FILES test/bsm/Makefile" ;; "tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/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_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers 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" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :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 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _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" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :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 "libtool":C) # See if we are running on zsh, and set the options which 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 # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="" # ### 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 # 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 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 # 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 in which our libraries should be installed. lt_sysroot=$lt_sysroot # 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 # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # 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 # ### END LIBTOOL CONFIG _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 "X${COLLECT_NAMES+set}" != Xset; 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) if test x"$xsi_shell" = xyes; then sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ func_dirname ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ } # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_basename ()$/,/^} # func_basename /c\ func_basename ()\ {\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ func_dirname_and_basename ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ func_stripname ()\ {\ \ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ \ # positional parameters, so assign one to ordinary parameter first.\ \ func_stripname_result=${3}\ \ func_stripname_result=${func_stripname_result#"${1}"}\ \ func_stripname_result=${func_stripname_result%"${2}"}\ } # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ func_split_long_opt ()\ {\ \ func_split_long_opt_name=${1%%=*}\ \ func_split_long_opt_arg=${1#*=}\ } # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ func_split_short_opt ()\ {\ \ func_split_short_opt_arg=${1#??}\ \ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ } # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ func_lo2o ()\ {\ \ case ${1} in\ \ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ \ *) func_lo2o_result=${1} ;;\ \ esac\ } # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_xform ()$/,/^} # func_xform /c\ func_xform ()\ {\ func_xform_result=${1%.*}.lo\ } # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_arith ()$/,/^} # func_arith /c\ func_arith ()\ {\ func_arith_result=$(( $* ))\ } # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_len ()$/,/^} # func_len /c\ func_len ()\ {\ func_len_result=${#1}\ } # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$lt_shell_append" = xyes; then sed -e '/^func_append ()$/,/^} # func_append /c\ func_append ()\ {\ eval "${1}+=\\${2}"\ } # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ func_append_quoted ()\ {\ \ func_quote_for_eval "${2}"\ \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ } # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 $as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} fi mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ;; "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Autoconf 2.62 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. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; 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 Index: user/alc/PQ_LAUNDRY/contrib/openbsm/configure.ac =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/configure.ac (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/configure.ac (revision 292449) @@ -1,263 +1,263 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) -AC_INIT([OpenBSM], [1.2-alpha3], [trustedbsd-audit@TrustesdBSD.org],[openbsm]) -AC_REVISION([$P4: //depot/projects/trustedbsd/openbsm/configure.ac#66 $]) +AC_INIT([OpenBSM], [1.2-alpha4], [trustedbsd-audit@TrustedBSD.org],[openbsm]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([bin/auditreduce/auditreduce.c]) AC_CONFIG_AUX_DIR(config) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADER([config/config.h]) AM_MAINTAINER_MODE # --with-native-includes forces the use of the system bsm headers. AC_ARG_WITH([native-includes], [AS_HELP_STRING([--with-native-includes], [Use the system native include files instead of those included with openbsm.])], [ AC_DEFINE(USE_NATIVE_INCLUDES,, Define to use native include files) use_native_includes=true ], [use_native_includes=false]) AM_CONDITIONAL(USE_NATIVE_INCLUDES, $use_native_includes) AC_PATH_PROGS(MIG, mig) # Checks for programs. AC_PROG_CC AC_PROG_INSTALL AC_PROG_LEX AC_PROG_LIBTOOL +AC_PROG_LN_S AC_PROG_YACC AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION) AC_SEARCH_LIBS(dlsym, dl) AC_SEARCH_LIBS(pthread_create, pthread) AC_SEARCH_LIBS(clock_gettime, rt) AC_SEARCH_LIBS(SSL_connect, ssl) AC_SEARCH_LIBS(humanize_number, util) AC_SEARCH_LIBS(pidfile_open, util) # Checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT AC_CHECK_HEADERS([mach/mach.h stdint.h pthread_np.h printf.h]) AC_DEFINE([_GNU_SOURCE],,[Use extended API on platforms that require it]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_UID_T AC_TYPE_PID_T AC_TYPE_SIZE_T AC_CHECK_MEMBERS([struct stat.st_rdev]) AC_CHECK_MEMBER([struct ipc_perm.__key], [AC_DEFINE(HAVE_IPC_PERM___KEY,, Define if ipc_perm.__key instead of key)], [],[ #include #include ]) AC_CHECK_MEMBER([struct ipc_perm._key], [AC_DEFINE(HAVE_IPC_PERM__KEY,, Define if ipc_perm._key instead of key)], [],[ #include #include ]) AC_CHECK_MEMBER([struct ipc_perm.__seq], [AC_DEFINE(HAVE_IPC_PERM___SEQ,, Define if ipc_perm.__seq instead of seq)], [],[ #include #include ]) AC_CHECK_MEMBER([struct ipc_perm._seq], [AC_DEFINE(HAVE_IPC_PERM__SEQ,, Define if ipc_perm._seq instead of seq)], [],[ #include #include ]) AC_CHECK_MEMBER([struct sockaddr_storage.ss_len], [AC_DEFINE(HAVE_SOCKADDR_STORAGE_SS_LEN,, Define if sockaddr_storage.ss_len field exists)], [],[ #include #include ]) AC_HEADER_TIME AC_STRUCT_TM # Checks for library functions. AC_FUNC_CHOWN AC_FUNC_FORK AC_FUNC_MALLOC AC_FUNC_MKTIME AC_TYPE_SIGNAL AC_FUNC_STAT AC_FUNC_STRFTIME AC_CHECK_FUNCS([arc4random arc4random_buf bzero cap_enter clock_gettime closefrom faccessat fdopendir fstatat ftruncate getresgid getresuid gettimeofday inet_ntoa jail kqueue memset openat pthread_cond_timedwait_relative_np pthread_condattr_setclock pthread_mutex_lock renameat setproctitle sigtimedwait strchr strerror strlcat strlcpy strndup strrchr strstr strtol strtoul unlinkat vis]) # sys/queue.h exists on most systems, but its capabilities vary a great deal. # test for LIST_FIRST and TAILQ_FOREACH_SAFE, which appears to not exist in # all of them, and are necessary for OpenBSM. AC_TRY_LINK([ #include ], [ #ifndef LIST_FIRST #error LIST_FIRST missing #endif #ifndef TAILQ_FOREACH_SAFE #error TAILQ_FOREACH_SAFE #endif ], [ AC_DEFINE(HAVE_FULL_QUEUE_H,, Define if queue.h includes LIST_FIRST) ]) # Systems may not define key audit system calls, in which case libbsm cannot # depend on them or it will generate link-time or run-time errors. Test for # just one. AC_TRY_LINK([ #include extern int auditon(int, void *, int); ], [ int err; err = auditon(0, NULL, 0); ], [ AC_DEFINE(HAVE_AUDIT_SYSCALLS,, Define if audit system calls present) have_audit_syscalls=true ], [ have_audit_syscalls=false ]) AM_CONDITIONAL(HAVE_AUDIT_SYSCALLS, $have_audit_syscalls) # # We rely on the BSD be32toh() and be32enc()-style endian macros to perform # byte order conversions. Availability of these varies considerably -- in # general, a system might have neither, be32toh(), or be32toh() and be32enc(). # There is also variation in which headers are even present, and whether they # are macros or functions. Try to organise the world into some simpler cases. # The following macros may be set at the end: # # USE_ENDIAN_H # USE_SYS_ENDIAN_H # USE_MACHINE_ENDIAN_H # USE_COMPAT_ENDIAN_H # USE_COMPAT_ENDIAN_ENC_H # # First, decide which system endian.h to use. # AC_CHECK_HEADERS([endian.h], [ have_endian_h=yes ], [ have_endian_h=no ]) AC_CHECK_HEADERS([sys/endian.h], [ have_sys_endian_h=yes ], [ have_sys_endian_h=no ]) AC_CHECK_HEADERS([machine/endian.h], [ have_machine_endian_h=yes ], [ have_machine_endian_h=no ]) if test $have_endian_h = yes; then AC_DEFINE(USE_ENDIAN_H,, Define if endian.h should be included) elif test $have_sys_endian_h = yes; then AC_DEFINE(USE_SYS_ENDIAN_H,, Define if sys/endian.h should be included) elif test $have_machine_endian_h = yes; then AC_DEFINE(USE_MACHINE_ENDIAN_H,, Define if machine/endian.h should be included) else AC_MSG_ERROR([no endian.h]) fi # # Next, decide if we need to supplement with compat headers. # AC_TRY_LINK([ #ifdef USE_ENDIAN_H #include #endif #ifdef USE_SYS_ENDIAN_H #include #endif #ifdef USE_MACHINE_ENDIAN_H #include #endif ], [ (void)be32toh(0); ], [], [ AC_DEFINE(USE_COMPAT_ENDIAN_H,, Define if compat/endian.h is required) AC_MSG_RESULT([using compat/endian.h]) ]) AC_TRY_LINK([ #ifdef USE_ENDIAN_H #include #endif #ifdef USE_SYS_ENDIAN_H #include #endif #ifdef USE_MACHINE_ENDIAN_H #include #endif #ifdef USE_COMPAT_ENDIAN_H #include "compat/endian.h" #endif #include ], [ int i; i = bswap16(0); i = bswap32(0); i = bswap64(0); be32enc(NULL, 0); i = htole64(0); i = le64toh(0); ], [], [ AC_DEFINE(USE_COMPAT_ENDIAN_ENC_H,, Define if compat/endian_enc.h is required) AC_MSG_RESULT([using compat/endian_enc.h]) ]) # Check to see if Mach IPC is used for trigger messages. If so, use Mach IPC # instead of the default for sending trigger messages to the audit components. AC_CHECK_FILE([/usr/include/mach/audit_triggers.defs], [ AC_DEFINE(USE_MACH_IPC,, Define if uses Mach IPC for Triggers messages) use_mach_ipc=true ], [ use_mach_ipc=false ]) AM_CONDITIONAL(USE_MACH_IPC, $use_mach_ipc) AC_CONFIG_FILES([Makefile bin/Makefile bin/audit/Makefile bin/auditd/Makefile bin/auditdistd/Makefile bin/auditfilterd/Makefile bin/auditreduce/Makefile bin/praudit/Makefile bsm/Makefile libauditd/Makefile libbsm/Makefile modules/Makefile modules/auditfilter_noop/Makefile man/Makefile sys/Makefile sys/bsm/Makefile test/Makefile test/bsm/Makefile tools/Makefile]) AC_OUTPUT Index: user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_class =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_class (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_class (revision 292449) @@ -1,24 +1,23 @@ # -# $P4: //depot/projects/trustedbsd/openbsm/etc/audit_class#6 $ # $FreeBSD$ # 0x00000000:no:invalid class 0x00000001:fr:file read 0x00000002:fw:file write 0x00000004:fa:file attribute access 0x00000008:fm:file attribute modify 0x00000010:fc:file create 0x00000020:fd:file delete 0x00000040:cl:file close 0x00000080:pc:process 0x00000100:nt:network 0x00000200:ip:ipc 0x00000400:na:non attributable 0x00000800:ad:administrative 0x00001000:lo:login_logout 0x00002000:aa:authentication and authorization 0x00004000:ap:application 0x20000000:io:ioctl 0x40000000:ex:exec 0x80000000:ot:miscellaneous 0xffffffff:all:all flags set Index: user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_control =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_control (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_control (revision 292449) @@ -1,12 +1,11 @@ # -# $P4: //depot/projects/trustedbsd/openbsm/etc/audit_control#9 $ # $FreeBSD$ # dir:/var/audit dist:off flags:lo,aa minfree:5 naflags:lo,aa policy:cnt,argv filesz:2M expire-after:10M Index: user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_event =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_event (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_event (revision 292449) @@ -1,676 +1,675 @@ # -# $P4: //depot/projects/trustedbsd/openbsm/etc/audit_event#43 $ # $FreeBSD$ # # The mapping between event identifiers and values is also hard-coded in # audit_kevents.h and audit_uevents.h, so changes must occur in both places, # and programs, such as the kernel, may need to be recompiled to recognize # those changes. It is advisable not to change the numbering or naming of # kernel audit events. # # Allocation of BSM event identifier ranges: # # 0 Reserved and invalid # 1 - 2047 Reserved for Solaris kernel events # 2048 - 5999 Reserved and unallocated # 6000 - 9999 Reserved for Solaris user events # 10000 - 32767 Reserved and unallocated # 32768 - 65535 Available for third party applications # # Of the third party range, OpenBSM allocates from the following ranges: # # 43000 - 44999 Reserved for OpenBSM kernel events # 45000 - 46999 Reserved for OpenBSM application events # 0:AUE_NULL:indir system call:no 1:AUE_EXIT:exit(2):pc 2:AUE_FORK:fork(2):pc 3:AUE_OPEN:open(2) - attr only:fa 4:AUE_CREAT:creat(2):fc 5:AUE_LINK:link(2):fc 6:AUE_UNLINK:unlink(2):fd 7:AUE_EXEC:exec(2):pc,ex 8:AUE_CHDIR:chdir(2):pc 9:AUE_MKNOD:mknod(2):fc 10:AUE_CHMOD:chmod(2):fm 11:AUE_CHOWN:chown(2):fm 12:AUE_UMOUNT:umount(2) - old version:ad 13:AUE_JUNK:junk:no 14:AUE_ACCESS:access(2):fa 15:AUE_KILL:kill(2):pc 16:AUE_STAT:stat(2):fa 17:AUE_LSTAT:lstat(2):fa 18:AUE_ACCT:acct(2):ad 19:AUE_MCTL:mctl(2):no 20:AUE_REBOOT:reboot(2):ad 21:AUE_SYMLINK:symlink(2):fc 22:AUE_READLINK:readlink(2):fr 23:AUE_EXECVE:execve(2):pc,ex 24:AUE_CHROOT:chroot(2):pc 25:AUE_VFORK:vfork(2):pc 26:AUE_SETGROUPS:setgroups(2):pc 27:AUE_SETPGRP:setpgrp(2):pc 28:AUE_SWAPON:swapon(2):ad 29:AUE_SETHOSTNAME:sethostname(2):ad 30:AUE_FCNTL:fcntl(2):fm 31:AUE_SETPRIORITY:setpriority(2):pc 32:AUE_CONNECT:connect(2):nt 33:AUE_ACCEPT:accept(2):nt 34:AUE_BIND:bind(2):nt 35:AUE_SETSOCKOPT:setsockopt(2):nt 36:AUE_VTRACE:vtrace(2):pc 37:AUE_SETTIMEOFDAY:settimeofday(2):ad 38:AUE_FCHOWN:fchown(2):fm 39:AUE_FCHMOD:fchmod(2):fm 40:AUE_SETREUID:setreuid(2):pc 41:AUE_SETREGID:setregid(2):pc 42:AUE_RENAME:rename(2):fc,fd 43:AUE_TRUNCATE:truncate(2):fw 44:AUE_FTRUNCATE:ftruncate(2):fw 45:AUE_FLOCK:flock(2):fm 46:AUE_SHUTDOWN:shutdown(2):nt 47:AUE_MKDIR:mkdir(2):fc 48:AUE_RMDIR:rmdir(2):fd 49:AUE_UTIMES:utimes(2):fm 50:AUE_ADJTIME:adjtime(2):ad 51:AUE_SETRLIMIT:setrlimit(2):pc 52:AUE_KILLPG:killpg(2):pc 53:AUE_NFS_SVC:nfs_svc(2):ad 54:AUE_STATFS:statfs(2):fa 55:AUE_FSTATFS:fstatfs(2):fa 56:AUE_UNMOUNT:unmount(2):ad 57:AUE_ASYNC_DAEMON:async_daemon(2):ad 58:AUE_NFS_GETFH:nfs_getfh(2):ad 59:AUE_SETDOMAINNAME:setdomainname(2):ad 60:AUE_QUOTACTL:quotactl(2):ad 61:AUE_EXPORTFS:exportfs(2):ad 62:AUE_MOUNT:mount(2):ad 63:AUE_SEMSYS:semsys(2):ip 64:AUE_MSGSYS:msgsys(2):ip 65:AUE_SHMSYS:shmsys(2):ip 66:AUE_BSMSYS:bsmsys(2):ad 67:AUE_RFSSYS:rfssys(2):ad 68:AUE_FCHDIR:fchdir(2):pc 69:AUE_FCHROOT:fchroot(2):pc 70:AUE_VPIXSYS:vpixsys(2):no 71:AUE_PATHCONF:pathconf(2):fa 72:AUE_OPEN_R:open(2) - read:fr 73:AUE_OPEN_RC:open(2) - read,creat:fc,fr,fa,fm 74:AUE_OPEN_RT:open(2) - read,trunc:fd,fr,fa,fm 75:AUE_OPEN_RTC:open(2) - read,creat,trunc:fc,fd,fr,fa,fm 76:AUE_OPEN_W:open(2) - write:fw 77:AUE_OPEN_WC:open(2) - write,creat:fc,fw,fa,fm 78:AUE_OPEN_WT:open(2) - write,trunc:fd,fw,fa,fm 79:AUE_OPEN_WTC:open(2) - write,creat,trunc:fc,fd,fw,fa,fm 80:AUE_OPEN_RW:open(2) - read,write:fr,fw 81:AUE_OPEN_RWC:open(2) - read,write,creat:fc,fw,fr,fa,fm 82:AUE_OPEN_RWT:open(2) - read,write,trunc:fd,fr,fw,fa,fm 83:AUE_OPEN_RWTC:open(2) - read,write,creat,trunc:fc,fd,fw,fr,fa,fm 84:AUE_MSGCTL:msgctl(2) - illegal command:ip 85:AUE_MSGCTL_RMID:msgctl(2) - IPC_RMID command:ip 86:AUE_MSGCTL_SET:msgctl(2) - IPC_SET command:ip 87:AUE_MSGCTL_STAT:msgctl(2) - IPC_STAT command:ip 88:AUE_MSGGET:msgget(2):ip 89:AUE_MSGRCV:msgrcv(2):ip 90:AUE_MSGSND:msgsnd(2):ip 91:AUE_SHMCTL:shmctl(2) - illegal command:ip 92:AUE_SHMCTL_RMID:shmctl(2) - IPC_RMID command:ip 93:AUE_SHMCTL_SET:shmctl(2) - IPC_SET command:ip 94:AUE_SHMCTL_STAT:shmctl(2) - IPC_STAT command:ip 95:AUE_SHMGET:shmget(2):ip 96:AUE_SHMAT:shmat(2):ip 97:AUE_SHMDT:shmdt(2):ip 98:AUE_SEMCTL:semctl(2) - illegal command:ip 99:AUE_SEMCTL_RMID:semctl(2) - IPC_RMID command:ip 100:AUE_SEMCTL_SET:semctl(2) - IPC_SET command:ip 101:AUE_SEMCTL_STAT:semctl(2) - IPC_STAT command:ip 102:AUE_SEMCTL_GETNCNT:semctl(2) - GETNCNT command:ip 103:AUE_SEMCTL_GETPID:semctl(2) - GETPID command:ip 104:AUE_SEMCTL_GETVAL:semctl(2) - GETVAL command:ip 105:AUE_SEMCTL_GETALL:semctl(2) - GETALL command:ip 106:AUE_SEMCTL_GETZCNT:semctl(2) - GETZCNT command:ip 107:AUE_SEMCTL_SETVAL:semctl(2) - SETVAL command:ip 108:AUE_SEMCTL_SETALL:semctl(2) - SETALL command:ip 109:AUE_SEMGET:semget(2):ip 110:AUE_SEMOP:semop(2):ip 111:AUE_CORE:process dumped core:fc 112:AUE_CLOSE:close(2):cl 113:AUE_SYSTEMBOOT:system booted:na 114:AUE_ASYNC_DAEMON_EXIT:async_daemon(2) exited:ad 115:AUE_NFSSVC_EXIT:nfssvc(2) exited:ad 128:AUE_WRITEL:writel(2):no 129:AUE_WRITEVL:writevl(2):no 130:AUE_GETAUID:getauid(2):ad 131:AUE_SETAUID:setauid(2):ad 132:AUE_GETAUDIT:getaudit(2):ad 133:AUE_SETAUDIT:setaudit(2):ad 134:AUE_GETUSERAUDIT:getuseraudit(2):ad 135:AUE_SETUSERAUDIT:setuseraudit(2):ad 136:AUE_AUDITSVC:auditsvc(2):ad 137:AUE_AUDITUSER:audituser(2):ad 138:AUE_AUDITON:auditon(2):ad 139:AUE_AUDITON_GTERMID:auditon(2) - GETTERMID command:ad 140:AUE_AUDITON_STERMID:auditon(2) - SETTERMID command:ad 141:AUE_AUDITON_GPOLICY:auditon(2) - GPOLICY command:ad 142:AUE_AUDITON_SPOLICY:auditon(2) - SPOLICY command:ad 143:AUE_AUDITON_GESTATE:auditon(2) - GESTATE command:ad 144:AUE_AUDITON_SESTATE:auditon(2) - SESTATE command:ad 145:AUE_AUDITON_GQCTRL:auditon(2) - GQCTRL command:ad 146:AUE_AUDITON_SQCTRL:auditon(2) - SQCTRL command:ad 147:AUE_GETKERNSTATE:getkernstate(2):ad 148:AUE_SETKERNSTATE:setkernstate(2):ad 149:AUE_GETPORTAUDIT:getportaudit(2):ad 150:AUE_AUDITSTAT:auditstat(2):ad 151:AUE_REVOKE:revoke(2):cl 152:AUE_MAC:Solaris AUE_MAC:no 153:AUE_ENTERPROM:enter prom:ad 154:AUE_EXITPROM:exit prom:ad 155:AUE_IFLOAT:Solaris AUE_IFLOAT:no 156:AUE_PFLOAT:Solaris AUE_PFLOAT:no 157:AUE_UPRIV:Solaris AUE_UPRIV:no 158:AUE_IOCTL:ioctl(2):io 173:AUE_ONESIDE:one-sided session record:nt 174:AUE_MSGGETL:msggetl(2):ip 175:AUE_MSGRCVL:msgrcvl(2):ip 176:AUE_MSGSNDL:msgsndl(2):ip 177:AUE_SEMGETL:semgetl(2):ip 178:AUE_SHMGETL:shmgetl(2):ip 183:AUE_SOCKET:socket(2):nt 184:AUE_SENDTO:sendto(2):nt 185:AUE_PIPE:pipe(2):ip 186:AUE_SOCKETPAIR:socketpair(2):nt 187:AUE_SEND:send(2):nt 188:AUE_SENDMSG:sendmsg(2):nt 189:AUE_RECV:recv(2):nt 190:AUE_RECVMSG:recvmsg(2):nt 191:AUE_RECVFROM:recvfrom(2):nt 192:AUE_READ:read(2):no 193:AUE_GETDENTS:getdents(2):no 194:AUE_LSEEK:lseek(2):no 195:AUE_WRITE:write(2):no 196:AUE_WRITEV:writev(2):no 197:AUE_NFS:nfs server:ad 198:AUE_READV:readv(2):no 199:AUE_OSTAT:Solaris old stat(2):fa 200:AUE_SETUID:setuid(2):pc 201:AUE_STIME:old stime(2):ad 202:AUE_UTIME:old utime(2):fm 203:AUE_NICE:old nice(2):pc 204:AUE_OSETPGRP:Solaris old setpgrp(2):pc 205:AUE_SETGID:setgid(2):pc 206:AUE_READL:readl(2):no 207:AUE_READVL:readvl(2):no 208:AUE_FSTAT:fstat(2):fa 209:AUE_DUP2:dup2(2):no 210:AUE_MMAP:mmap(2):no 211:AUE_AUDIT:audit(2):ot 212:AUE_PRIOCNTLSYS:Solaris priocntlsys(2):pc 213:AUE_MUNMAP:munmap(2):cl 214:AUE_SETEGID:setegid(2):pc 215:AUE_SETEUID:seteuid(2):pc 216:AUE_PUTMSG:putmsg(2):nt 217:AUE_GETMSG:getmsg(2):nt 218:AUE_PUTPMSG:putpmsg(2):nt 219:AUE_GETPMSG:getpmsg(2):nt 220:AUE_AUDITSYS:audit system calls place holder:no 221:AUE_AUDITON_GETKMASK:auditon(2) - get kernel mask:ad 222:AUE_AUDITON_SETKMASK:auditon(2) - set kernel mask:ad 223:AUE_AUDITON_GETCWD:auditon(2) - get cwd:ad 224:AUE_AUDITON_GETCAR:auditon(2) - get car:ad 225:AUE_AUDITON_GETSTAT:auditon(2) - get audit statistics:ad 226:AUE_AUDITON_SETSTAT:auditon(2) - reset audit statistics:ad 227:AUE_AUDITON_SETUMASK:auditon(2) - set mask per uid:ad 228:AUE_AUDITON_SETSMASK:auditon(2) - set mask per session ID:ad 229:AUE_AUDITON_GETCOND:auditon(2) - get audit state:ad 230:AUE_AUDITON_SETCOND:auditon(2) - set audit state:ad 231:AUE_AUDITON_GETCLASS:auditon(2) - get event class:ad 232:AUE_AUDITON_SETCLASS:auditon(2) - set event class:ad 233:AUE_UTSSYS:utssys(2) - fusers:ad 234:AUE_STATVFS:statvfs(2):fa 235:AUE_XSTAT:xstat(2):fa 236:AUE_LXSTAT:lxstat(2):fa 237:AUE_LCHOWN:lchown(2):fm 238:AUE_MEMCNTL:memcntl(2):ot 239:AUE_SYSINFO:sysinfo(2):ad 240:AUE_XMKNOD:xmknod(2):fc 241:AUE_FORK1:fork1(2):pc 242:AUE_MODCTL:modctl(2) system call place holder:no 243:AUE_MODLOAD:modctl(2) - load module:ad 244:AUE_MODUNLOAD:modctl(2) - unload module:ad 245:AUE_MODCONFIG:modctl(2) - configure module:ad 246:AUE_MODADDMAJ:modctl(2) - bind module:ad 247:AUE_SOCKACCEPT:getmsg-accept:nt 248:AUE_SOCKCONNECT:putmsg-connect:nt 249:AUE_SOCKSEND:putmsg-send:nt 250:AUE_SOCKRECEIVE:getmsg-receive:nt 251:AUE_ACLSET:acl(2) - SETACL comand:fm 252:AUE_FACLSET:facl(2) - SETACL command:fm 253:AUE_DOORFS:doorfs(2) - system call place holder:no 254:AUE_DOORFS_DOOR_CALL:doorfs(2) - DOOR_CALL:ip 255:AUE_DOORFS_DOOR_RETURN:doorfs(2) - DOOR_RETURN:ip 256:AUE_DOORFS_DOOR_CREATE:doorfs(2) - DOOR_CREATE:ip 257:AUE_DOORFS_DOOR_REVOKE:doorfs(2) - DOOR_REVOKE:ip 258:AUE_DOORFS_DOOR_INFO:doorfs(2) - DOOR_INFO:ip 259:AUE_DOORFS_DOOR_CRED:doorfs(2) - DOOR_CRED:ip 260:AUE_DOORFS_DOOR_BIND:doorfs(2) - DOOR_BIND:ip 261:AUE_DOORFS_DOOR_UNBIND:doorfs(2) - DOOR_UNBIND:ip 262:AUE_P_ONLINE:p_online(2):ad 263:AUE_PROCESSOR_BIND:processor_bind(2):ad 264:AUE_INST_SYNC:inst_sync(2):ad 265:AUE_SOCKCONFIG:configure socket:nt 266:AUE_SETAUDIT_ADDR:setaudit_addr(2):ad 267:AUE_GETAUDIT_ADDR:getaudit_addr(2):ad 268:AUE_UMOUNT2:Solaris umount(2):ad 269:AUE_FSAT:fsat(2) - place holder:no 270:AUE_OPENAT_R:openat(2) - read:fr 271:AUE_OPENAT_RC:openat(2) - read,creat:fc,fr,fa,fm 272:AUE_OPENAT_RT:openat(2) - read,trunc:fd,fr,fa,fm 273:AUE_OPENAT_RTC:openat(2) - read,creat,trunc:fc,fd,fr,fa,fm 274:AUE_OPENAT_W:openat(2) - write:fw 275:AUE_OPENAT_WC:openat(2) - write,creat:fc,fw,fa,fm 276:AUE_OPENAT_WT:openat(2) - write,trunc:fd,fw,fa,fm 277:AUE_OPENAT_WTC:openat(2) - write,creat,trunc:fc,fd,fw,fa,fm 278:AUE_OPENAT_RW:openat(2) - read,write:fr,fw 279:AUE_OPENAT_RWC:openat(2) - read,write,create:fc,fw,fr,fa,fm 280:AUE_OPENAT_RWT:openat(2) - read,write,trunc:fd,fw,fr,fa,fm 281:AUE_OPENAT_RWTC:openat(2) - read,write,creat,trunc:fc,fd,fw,fr,fa,fm 282:AUE_RENAMEAT:renameat(2):fc,fd 283:AUE_FSTATAT:fstatat(2):fa 284:AUE_FCHOWNAT:fchownat(2):fm 285:AUE_FUTIMESAT:futimesat(2):fm 286:AUE_UNLINKAT:unlinkat(2):fd 287:AUE_CLOCK_SETTIME:clock_settime(2):ad 288:AUE_NTP_ADJTIME:ntp_adjtime(2):ad 289:AUE_SETPPRIV:setppriv(2):pc 290:AUE_MODDEVPLCY:modctl(2) - configure device policy:ad 291:AUE_MODADDPRIV:modctl(2) - configure additional privilege:ad 292:AUE_CRYPTOADM:kernel cryptographic framework:ad 293:AUE_CONFIGKSSL:configure kernel SSL:ad 294:AUE_BRANDSYS:brandsys(2):ot 295:AUE_PF_POLICY_ADDRULE:Add IPsec policy rule:ad 296:AUE_PF_POLICY_DELRULE:Delete IPsec policy rule:ad 297:AUE_PF_POLICY_CLONE:Clone IPsec policy:ad 298:AUE_PF_POLICY_FLIP:Flip IPsec policy:ad 299:AUE_PF_POLICY_FLUSH:Flush IPsec policy rules:ad 300:AUE_PF_POLICY_ALGS:Update IPsec algorithms:ad 301:AUE_PORTFS:portfs:fa # # What follows are deprecated Darwin event numbers that may soon^H^H^H^Hnow # conflict with Solaris events. # 301:AUE_DARWIN_GETFSSTAT:getfsstat(2):fa 302:AUE_DARWIN_PTRACE:ptrace(2):pc 303:AUE_DARWIN_CHFLAGS:chflags(2):fm 304:AUE_DARWIN_FCHFLAGS:fchflags(2):fm 305:AUE_DARWIN_PROFILE:profil(2):pc 306:AUE_DARWIN_KTRACE:ktrace(2):pc 307:AUE_DARWIN_SETLOGIN:setlogin(2):pc 308:AUE_DARWIN_REBOOT:reboot(2):ad 309:AUE_DARWIN_REVOKE:revoke(2):cl 310:AUE_DARWIN_UMASK:umask(2):pc 311:AUE_DARWIN_MPROTECT:mprotect(2):fm 312:AUE_DARWIN_SETPRIORITY:setpriority(2):pc,ot 313:AUE_DARWIN_SETTIMEOFDAY:settimeofday(2):ad 314:AUE_DARWIN_FLOCK:flock(2):fm 315:AUE_DARWIN_MKFIFO:mkfifo(2):fc 316:AUE_DARWIN_POLL:poll(2):no 317:AUE_DARWIN_SOCKETPAIR:socketpair(2):nt 318:AUE_DARWIN_FUTIMES:futimes(2):fm 319:AUE_DARWIN_SETSID:setsid(2):pc 320:AUE_DARWIN_SETPRIVEXEC:setprivexec(2):pc 321:AUE_DARWIN_NFSSVC:nfssvc(2):ad 322:AUE_DARWIN_GETFH:getfh(2):fa 323:AUE_DARWIN_QUOTACTL:quotactl(2):ad 324:AUE_DARWIN_ADDPROFILE:add_profil():pc 325:AUE_DARWIN_KDEBUGTRACE:kdebug_trace():pc 326:AUE_DARWIN_FSTAT:fstat(2):fa 327:AUE_DARWIN_FPATHCONF:fpathconf(2):fa 328:AUE_DARWIN_GETDIRENTRIES:getdirentries(2):no 329:AUE_DARWIN_TRUNCATE:truncate(2):fw 330:AUE_DARWIN_FTRUNCATE:ftruncate(2):fw 331:AUE_DARWIN_SYSCTL:sysctl(3):ad 332:AUE_DARWIN_MLOCK:mlock(2):pc 333:AUE_DARWIN_MUNLOCK:munlock(2):pc 334:AUE_DARWIN_UNDELETE:undelete(2):fm 335:AUE_DARWIN_GETATTRLIST:getattrlist():fa 336:AUE_DARWIN_SETATTRLIST:setattrlist():fm 337:AUE_DARWIN_GETDIRENTRIESATTR:getdirentriesattr():fa 338:AUE_DARWIN_EXCHANGEDATA:exchangedata():fw 339:AUE_DARWIN_SEARCHFS:searchfs():fa 340:AUE_DARWIN_MINHERIT:minherit(2):pc 341:AUE_DARWIN_SEMCONFIG:semconfig():ip 342:AUE_DARWIN_SEMOPEN:sem_open(2):ip 343:AUE_DARWIN_SEMCLOSE:sem_close(2):ip 344:AUE_DARWIN_SEMUNLINK:sem_unlink(2):ip 345:AUE_DARWIN_SHMOPEN:shm_open(2):ip 346:AUE_DARWIN_SHMUNLINK:shm_unlink(2):ip 347:AUE_DARWIN_LOADSHFILE:load_shared_file():fr 348:AUE_DARWIN_RESETSHFILE:reset_shared_file():ot 349:AUE_DARWIN_NEWSYSTEMSHREG:new_system_share_regions():ot 350:AUE_DARWIN_PTHREADKILL:pthread_kill(2):pc 351:AUE_DARWIN_PTHREADSIGMASK:pthread_sigmask(2):pc 352:AUE_DARWIN_AUDITCTL:auditctl(2):ad 353:AUE_DARWIN_RFORK:rfork(2):pc 354:AUE_DARWIN_LCHMOD:lchmod(2):fm 355:AUE_DARWIN_SWAPOFF:swapoff(2):ad 356:AUE_DARWIN_INITPROCESS:init_process():pc 357:AUE_DARWIN_MAPFD:map_fd():fa 358:AUE_DARWIN_TASKFORPID:task_for_pid():pc 359:AUE_DARWIN_PIDFORTASK:pid_for_task():pc 360:AUE_DARWIN_SYSCTL_NONADMIN:sysctl() - non-admin:ot 361:AUE_DARWIN_COPYFILE:copyfile():fr,fw # # OpenBSM-specific kernel events. # 43001:AUE_GETFSSTAT:getfsstat(2):fa 43002:AUE_PTRACE:ptrace(2):pc 43003:AUE_CHFLAGS:chflags(2):fm 43004:AUE_FCHFLAGS:fchflags(2):fm 43005:AUE_PROFILE:profil(2):pc 43006:AUE_KTRACE:ktrace(2):pc 43007:AUE_SETLOGIN:setlogin(2):pc 43008:AUE_OPENBSM_REVOKE:revoke(2):cl 43009:AUE_UMASK:umask(2):pc 43010:AUE_MPROTECT:mprotect(2):fm 43011:AUE_MKFIFO:mkfifo(2):fc 43012:AUE_POLL:poll(2):no 43013:AUE_FUTIMES:futimes(2):fm 43014:AUE_SETSID:setsid(2):pc 43015:AUE_SETPRIVEXEC:setprivexec(2):pc 43016:AUE_ADDPROFILE:add_profil():pc 43017:AUE_KDEBUGTRACE:kdebug_trace():pc 43018:AUE_OPENBSM_FSTAT:fstat(2):fa 43019:AUE_FPATHCONF:fpathconf(2):fa 43020:AUE_GETDIRENTRIES:getdirentries(2):no 43021:AUE_SYSCTL:sysctl(3):ot 43022:AUE_MLOCK:mlock(2):pc 43023:AUE_MUNLOCK:munlock(2):pc 43024:AUE_UNDELETE:undelete(2):fm 43025:AUE_GETATTRLIST:getattrlist():fa 43026:AUE_SETATTRLIST:setattrlist():fm 43027:AUE_GETDIRENTRIESATTR:getdirentriesattr():fa 43028:AUE_EXCHANGEDATA:exchangedata():fw 43029:AUE_SEARCHFS:searchfs():fa 43030:AUE_MINHERIT:minherit(2):pc 43031:AUE_SEMCONFIG:semconfig():ip 43032:AUE_SEMOPEN:sem_open(2):ip 43033:AUE_SEMCLOSE:sem_close(2):ip 43034:AUE_SEMUNLINK:sem_unlink(2):ip 43035:AUE_SHMOPEN:shm_open(2):ip 43036:AUE_SHMUNLINK:shm_unlink(2):ip 43037:AUE_LOADSHFILE:load_shared_file():fr 43038:AUE_RESETSHFILE:reset_shared_file():ot 43039:AUE_NEWSYSTEMSHREG:new_system_share_regions():ot 43040:AUE_PTHREADKILL:pthread_kill(2):pc 43041:AUE_PTHREADSIGMASK:pthread_sigmask(2):pc 43042:AUE_AUDITCTL:auditctl(2):ad 43043:AUE_RFORK:rfork(2):pc 43044:AUE_LCHMOD:lchmod(2):fm 43045:AUE_SWAPOFF:swapoff(2):ad 43046:AUE_INITPROCESS:init_process():pc 43047:AUE_MAPFD:map_fd():fa 43048:AUE_TASKFORPID:task_for_pid():pc 43049:AUE_PIDFORTASK:pid_for_task():pc 43050:AUE_SYSCTL_NONADMIN:sysctl() - non-admin:ot 43051:AUE_COPYFILE:copyfile(2):fr,fw 43052:AUE_LUTIMES:lutimes(2):fm 43053:AUE_LCHFLAGS:lchflags(2):fm 43054:AUE_SENDFILE:sendfile(2):nt 43055:AUE_USELIB:uselib(2):fa 43056:AUE_GETRESUID:getresuid(2):pc 43057:AUE_SETRESUID:setresuid(2):pc 43058:AUE_GETRESGID:getresgid(2):pc 43059:AUE_SETRESGID:setresgid(2):pc 43060:AUE_WAIT4:wait4(2):pc 43061:AUE_LGETFH:lgetfh(2):fa 43062:AUE_FHSTATFS:fhstatfs(2):fa 43063:AUE_FHOPEN:fhopen(2):fa 43064:AUE_FHSTAT:fhstat(2):fa 43065:AUE_JAIL:jail(2):pc 43066:AUE_EACCESS:eaccess(2):fa 43067:AUE_KQUEUE:kqueue(2):no 43068:AUE_KEVENT:kevent(2):no 43069:AUE_FSYNC:fsync(2):fm 43070:AUE_NMOUNT:nmount(2):ad 43071:AUE_BDFLUSH:bdflush(2):ad 43072:AUE_SETFSUID:setfsuid(2):ot 43073:AUE_SETFSGID:setfsgid(2):ot 43074:AUE_PERSONALITY:personality(2):pc 43075:AUE_SCHED_GETSCHEDULER:getscheduler(2):ad 43076:AUE_SCHED_SETSCHEDULER:setscheduler(2):ad 43077:AUE_PRCTL:prctl(2):pc 43078:AUE_GETCWD:getcwd(2):pc 43079:AUE_CAPGET:capget(2):pc 43080:AUE_CAPSET:capset(2):pc 43081:AUE_PIVOT_ROOT:pivot_root(2):pc 43082:AUE_RTPRIO::rtprio(2):pc 43083:AUE_SCHED_GETPARAM:sched_getparam(2):ad 43084:AUE_SCHED_SETPARAM:sched_setparam(2):ad 43085:AUE_SCHED_GET_PRIORITY_MAX:sched_get_priority_max(2):ad 43086:AUE_SCHED_GET_PRIORITY_MIN:sched_get_priority_min(2):ad 43087:AUE_SCHED_RR_GET_INTERVAL:sched_rr_get_interval(2):ad 43088:AUE_ACL_GET_FILE:acl_get_file(2):fa 43089:AUE_ACL_SET_FILE:acl_set_file(2):fm 43090:AUE_ACL_GET_FD:acl_get_fd(2):fa 43091:AUE_ACL_SET_FD:acl_set_fd(2):fm 43092:AUE_ACL_DELETE_FILE:acl_delete_file(2):fm 43093:AUE_ACL_DELETE_FD:acl_delete_fd(2):fm 43094:AUE_ACL_CHECK_FILE:acl_aclcheck_file(2):fa 43095:AUE_ACL_CHECK_FD:acl_aclcheck_fd(2):fa 43096:AUE_ACL_GET_LINK:acl_get_link(2):fa 43097:AUE_ACL_SET_LINK:acl_set_link(2):fm 43098:AUE_ACL_DELETE_LINK:acl_delete_link(2):fm 43099:AUE_ACL_CHECK_LINK:acl_aclcheck_link(2):fa 43100:AUE_SYSARCH:sysarch(2):ot 43101:AUE_EXTATTRCTL:extattrctl(2):fm 43102:AUE_EXTATTR_GET_FILE:extattr_get_file(2):fa 43103:AUE_EXTATTR_SET_FILE:extattr_set_file(2):fm 43104:AUE_EXTATTR_LIST_FILE:extattr_list_file(2):fa 43105:AUE_EXTATTR_DELETE_FILE:extattr_delete_file(2):fm 43106:AUE_EXTATTR_GET_FD:extattr_get_fd(2):fa 43107:AUE_EXTATTR_SET_FD:extattr_set_fd(2):fm 43108:AUE_EXTATTR_LIST_FD:extattr_list_fd(2):fa 43109:AUE_EXTATTR_DELETE_FD:extattr_delete_fd(2):fm 43110:AUE_EXTATTR_GET_LINK:extattr_get_link(2):fa 43111:AUE_EXTATTR_SET_LINK:extattr_set_link(2):fm 43112:AUE_EXTATTR_LIST_LINK:extattr_list_link(2):fa 43113:AUE_EXTATTR_DELETE_LINK:extattr_delete_link(2):fm 43114:AUE_KENV:kenv(8):ad 43115:AUE_JAIL_ATTACH:jail_attach(2):ad 43116:AUE_SYSCTL_WRITE:sysctl(3):ad 43117:AUE_IOPERM:linux ioperm:ad 43118:AUE_READDIR:readdir(3):no 43119:AUE_IOPL:linux iopl:ad 43120:AUE_VM86:linux vm86:pc 43121:AUE_MAC_GET_PROC:mac_get_proc(2):pc 43122:AUE_MAC_SET_PROC:mac_set_proc(2):pc 43123:AUE_MAC_GET_FD:mac_get_fd(2):fa 43124:AUE_MAC_GET_FILE:mac_get_file(2):fa 43125:AUE_MAC_SET_FD:mac_set_fd(2):fm 43126:AUE_MAC_SET_FILE:mac_set_file(2):fm 43127:AUE_MAC_SYSCALL:mac_syscall(2):ad 43128:AUE_MAC_GET_PID:mac_get_pid(2):pc 43129:AUE_MAC_GET_LINK:mac_get_link(2):fa 43130:AUE_MAC_SET_LINK:mac_set_link(2):fm 43131:AUE_MAC_EXECVE:mac_execve(2):ex,pc 43132:AUE_GETPATH_FROMFD:getpath_fromfd(2):fa 43133:AUE_GETPATH_FROMADDR:getpath_fromaddr(2):fa 43134:AUE_MQ_OPEN:mq_open(2):ip 43135:AUE_MQ_SETATTR:mq_setattr(2):ip 43136:AUE_MQ_TIMEDRECEIVE:mq_timedreceive(2):ip 43137:AUE_MQ_TIMEDSEND:mq_timedsend(2):ip 43138:AUE_MQ_NOTIFY:mq_notify(2):ip 43139:AUE_MQ_UNLINK:mq_unlink(2):ip 43140:AUE_LISTEN:listen(2):nt 43141:AUE_MLOCKALL:mlockall(2):pc 43142:AUE_MUNLOCKALL:munlockall(2):pc 43143:AUE_CLOSEFROM:closefrom(2):cl 43144:AUE_FEXECVE:fexecve(2):pc,ex 43145:AUE_FACCESSAT:faccessat(2):fa 43146:AUE_FCHMODAT:fchmodat(2):fm 43147:AUE_LINKAT:linkat(2):fc 43148:AUE_MKDIRAT:mkdirat(2):fc 43149:AUE_MKFIFOAT:mkfifoat(2):fc 43150:AUE_MKNODAT:mknodat(2):fc 43151:AUE_READLINKAT:readlinkat(2):fr 43152:AUE_SYMLINKAT:symlinkat(2):fc 43153:AUE_MAC_GETFSSTAT:mac_getfsstat(2):fa 43154:AUE_MAC_GET_MOUNT:mac_get_mount(2):fa 43155:AUE_MAC_GET_LCID:mac_get_lcid(2):pc 43156:AUE_MAC_GET_LCTX:mac_get_lctx(2):pc 43157:AUE_MAC_SET_LCTX:mac_set_lctx(2):pc 43158:AUE_MAC_MOUNT:mac_mount(2):ad 43159:AUE_GETLCID:getlcid(2):pc 43160:AUE_SETLCID:setlcid(2):pc 43161:AUE_TASKNAMEFORPID:taskname_for_pid():pc 43162:AUE_ACCESS_EXTENDED:access_extended(2):fa 43163:AUE_CHMOD_EXTENDED:chmod_extended(2):fm 43164:AUE_FCHMOD_EXTENDED:fchmod_extended(2):fm 43165:AUE_FSTAT_EXTENDED:fstat_extended(2):fa 43166:AUE_LSTAT_EXTENDED:lstat_extended(2):fa 43167:AUE_MKDIR_EXTENDED:mkdir_extended(2):fc 43168:AUE_MKFIFO_EXTENDED:mkfifo_extended(2):fc 43169:AUE_OPEN_EXTENDED:open_extended(2) - attr only:fa 43170:AUE_OPEN_EXTENDED_R:open_extended(2) - read:fr 43171:AUE_OPEN_EXTENDED_RC:open_extended(2) - read,creat:fc,fr,fa,fm 43172:AUE_OPEN_EXTENDED_RT:open_extended(2) - read,trunc:fd,fr,fa,fm 43173:AUE_OPEN_EXTENDED_RTC:open_extended(2) - read,creat,trunc:fc,fd,fr,fa,fm 43174:AUE_OPEN_EXTENDED_W:open_extended(2) - write:fw 43175:AUE_OPEN_EXTENDED_WC:open_extended(2) - write,creat:fc,fw,fa,fm 43176:AUE_OPEN_EXTENDED_WT:open_extended(2) - write,trunc:fd,fw,fa,fm 43177:AUE_OPEN_EXTENDED_WTC:open_extended(2) - write,creat,trunc:fc,fd,fw,fa,fm 43178:AUE_OPEN_EXTENDED_RW:open_extended(2) - read,write:fr,fw 43179:AUE_OPEN_EXTENDED_RWC:open_extended(2) - read,write,creat:fc,fw,fr,fa,fm 43180:AUE_OPEN_EXTENDED_RWT:open_extended(2) - read,write,trunc:fd,fr,fw,fa,fm 43181:AUE_OPEN_EXTENDED_RWTC:open_extended(2) - read,write,creat,trunc:fc,fd,fw,fr,fa,fm 43182:AUE_STAT_EXTENDED:stat_extended(2):fa 43183:AUE_UMASK_EXTENDED:umask_extended(2):pc 43184:AUE_OPENAT:openat(2) - attr only:fa 43185:AUE_POSIX_OPENPT:posix_openpt(2):ip 43186:AUE_CAP_NEW:cap_new(2):fm 43187:AUE_CAP_RIGHTS_GET:cap_rights_get(2):fm 43188:AUE_CAP_ENTER:cap_enter(2):pc 43189:AUE_CAP_GETMODE:cap_getmode(2):pc 43190:AUE_POSIX_SPAWN:posix_spawn(2):pc 43191:AUE_FSGETPATH:fsgetpath(2):ot 43192:AUE_PREAD:pread(2):no 43193:AUE_PWRITE:pwrite(2):no 43194:AUE_FSCTL:fsctl():fm 43195:AUE_FFSCTL:ffsctl():fm 43196:AUE_LPATHCONF:lpathconf(2):fa 43197:AUE_PDFORK:pdfork(2):pc 43198:AUE_PDKILL:pdkill(2):pc 43199:AUE_PDGETPID:pdgetpid(2):pc 43200:AUE_PDWAIT:pdwait(2):pc 43201:AUE_WAIT6:wait6(2):pc 43202:AUE_CAP_RIGHTS_LIMIT:cap_rights_limit(2):fm 43203:AUE_CAP_IOCTLS_LIMIT:cap_ioctls_limit(2):fm 43204:AUE_CAP_IOCTLS_GET:cap_ioctls_get(2):fm 43205:AUE_CAP_FCNTLS_LIMIT:cap_fcntls_limit(2):fm 43206:AUE_CAP_FCNTLS_GET:cap_fcntls_get(2):fm 43207:AUE_BINDAT:bindat(2):nt 43208:AUE_CONNECTAT:connectat(2):nt 43209:AUE_CHFLAGSAT:chflagsat(2):fm # # Solaris userspace events. # 6144:AUE_at_create:at-create atjob:ad 6145:AUE_at_delete:at-delete atjob (at or atrm):ad 6146:AUE_at_perm:at-permission:no 6147:AUE_cron_invoke:cron-invoke:ad 6148:AUE_crontab_create:crontab-crontab created:ad 6149:AUE_crontab_delete:crontab-crontab deleted:ad 6150:AUE_crontab_perm:crontab-permission:no 6151:AUE_inetd_connect:inetd connection:na 6152:AUE_login:login - local:lo 6153:AUE_logout:logout - local:lo 6154:AUE_telnet:login - telnet:lo 6155:AUE_rlogin:login - rlogin:lo 6156:AUE_mountd_mount:mount:na 6157:AUE_mountd_umount:unmount:na 6158:AUE_rshd:rsh access:lo 6159:AUE_su:su(1):lo 6160:AUE_halt:system halt:ad 6161:AUE_reboot:system reboot:ad 6162:AUE_rexecd:rexecd:lo 6163:AUE_passwd:passwd:lo 6164:AUE_rexd:rexd:lo 6165:AUE_ftpd:ftp access:lo 6166:AUE_init:init:lo 6167:AUE_uadmin:uadmin:no 6168:AUE_shutdown:system shutdown:ad 6168:AUE_poweroff:system poweroff:ad 6170:AUE_crontab_mod:crontab-modify:ad 6171:AUE_ftpd_logout:ftp logout:lo 6172:AUE_ssh:login - ssh:lo 6173:AUE_role_login:role login:lo 6180:AUE_prof_cmd: profile command:ad 6181:AUE_filesystem_add:add filesystem:ad 6182:AUE_filesystem_delete:delete filesystem:ad 6183:AUE_filesystem_modify:modify filesystem:ad 6200:AUE_allocate_succ:allocate-device success:ot 6201:AUE_allocate_fail:allocate-device failure:ot 6202:AUE_deallocate_succ:deallocate-device success:ot 6203:AUE_deallocate_fail:deallocate-device failure:ot 6204:AUE_listdevice_succ:allocate-list devices success:ot 6205:AUE_listdevice_fail:allocate-list devices failure:ot 6207:AUE_create_user:create user:ad 6208:AUE_modify_user:modify user:ad 6209:AUE_delete_user:delete user:ad 6210:AUE_disable_user:disable user:ad 6211:AUE_enable_user:enable users:ad 6212:AUE_newgrp_login:newgrp login:lo 6213:AUE_admin_authenticate:admin login:lo 6214:AUE_kadmind_auth:authenticated kadmind request:ua 6215:AUE_kadmind_unauth:unauthenticated kadmind req:ua 6216:AUE_krb5kdc_as_req:kdc authentication svc request:ap 6217:AUE_krb5kdc_tgs_req:kdc tkt-grant svc request:ap 6218:AUE_krb5kdc_tgs_req_2ndtktmm:kdc tgs 2ndtkt mismtch:ap 6219:AUE_krb5kdc_tgs_req_alt_tgt:kdc tgs issue alt tgt:ap # # Historic Darwin use of low event numbering space, which collided with the # Solaris event space. Now obsoleted and new, higher, event numbers assigned # to make it easier to interpret Solaris events using the OpenBSM tools. # 6171:AUE_DARWIN_audit_startup:audit startup:ad 6172:AUE_DARWIN_audit_shutdown:audit shutdown:ad 6300:AUE_DARWIN_sudo:sudo(1):ad 6501:AUE_DARWIN_modify_password:modify password:ad 6511:AUE_DARWIN_create_group:create group:ad 6512:AUE_DARWIN_delete_group:delete group:ad 6513:AUE_DARWIN_modify_group:modify group:ad 6514:AUE_DARWIN_add_to_group:add to group:ad 6515:AUE_DARWIN_remove_from_group:remove from group:ad 6521:AUE_DARWIN_revoke_obj:revoke object priv:fm 6600:AUE_DARWIN_lw_login:loginwindow login:lo 6601:AUE_DARWIN_lw_logout:loginwindow logout:lo 7000:AUE_DARWIN_auth_user:user authentication:aa 7001:AUE_DARWIN_ssconn:SecSrvr connection setup:aa 7002:AUE_DARWIN_ssauthorize:SecSrvr AuthEngine:aa 7003:AUE_DARWIN_ssauthint:SecSrvr authinternal mech:aa # # Historic/third-party application allocations of event identifiers. # 32800:AUE_openssh:OpenSSH login:lo # # OpenBSM-managed application event space. # 45000:AUE_audit_startup:audit startup:ad 45001:AUE_audit_shutdown:audit shutdown:ad 45014:AUE_modify_password:modify password:ad 45015:AUE_create_group:create group:ad 45016:AUE_delete_group:delete group:ad 45017:AUE_modify_group:modify group:ad 45018:AUE_add_to_group:add to group:ad 45019:AUE_remove_from_group:remove from group:ad 45020:AUE_revoke_obj:revoke object priv:fm 45021:AUE_lw_login:loginwindow login:lo 45022:AUE_lw_logout:loginwindow logout:lo 45023:AUE_auth_user:user authentication:aa 45024:AUE_ssconn:SecSrvr connection setup:aa 45025:AUE_ssauthorize:SecSrvr AuthEngine:aa 45026:AUE_ssauthint:SecSrvr authinternal mech:aa 45027:AUE_calife:Calife:ad 45028:AUE_sudo:sudo(1):aa 45029:AUE_audit_recovery:audit crash recovery:ad 45030:AUE_ssauthmech:SecSrvr AuthMechanism:aa Index: user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_filter =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_filter (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_filter (revision 292449) @@ -1,5 +1,5 @@ # -# $P4: //depot/projects/trustedbsd/openbsm/etc/audit_filter#1 $ +# $FreeBSD$ # # modulename:various arguments here # Index: user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_user =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_user (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_user (revision 292449) @@ -1,5 +1,4 @@ # -# $P4: //depot/projects/trustedbsd/openbsm/etc/audit_user#3 $ # $FreeBSD$ # root:lo:no Index: user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_warn =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_warn (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/etc/audit_warn (revision 292449) @@ -1,6 +1,6 @@ #!/bin/sh # -# $P4: //depot/projects/trustedbsd/openbsm/etc/audit_warn#3 $ # $FreeBSD$ # + logger -p security.warning "audit warning: $@" Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libauditd/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libauditd/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libauditd/Makefile.am (revision 292449) @@ -1,17 +1,13 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/libauditd/Makefile.am#3 $ -## - if USE_NATIVE_INCLUDES INCLUDES = -I$(top_builddir) -I$(top_srcdir) else INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys endif lib_LTLIBRARIES = libauditd.la libauditd_la_SOURCES = \ auditd_lib.c man3_MANS = \ libauditd.3 Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libauditd/auditd_lib.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libauditd/auditd_lib.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libauditd/auditd_lib.c (revision 292449) @@ -1,1239 +1,1240 @@ /*- * Copyright (c) 2008-2009 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/libauditd/auditd_lib.c#18 $ */ #include #include #include #ifdef HAVE_FULL_QUEUE_H #include #else /* !HAVE_FULL_QUEUE_H */ #include #endif /* !HAVE_FULL_QUEUE_H */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __APPLE__ #include #ifndef __BSM_INTERNAL_NOTIFY_KEY #define __BSM_INTERNAL_NOTIFY_KEY "com.apple.audit.change" #endif /* __BSM_INTERNAL_NOTIFY_KEY */ #endif /* __APPLE__ */ /* * XXX This is temporary until this is moved to and shared with * the kernel. */ #ifndef AUDIT_HARD_LIMIT_FREE_BLOCKS #define AUDIT_HARD_LIMIT_FREE_BLOCKS 4 #endif /* * Number of seconds to January 1, 2000 */ #define JAN_01_2000 946598400 struct dir_ent { char *dirname; uint8_t softlim; uint8_t hardlim; TAILQ_ENTRY(dir_ent) dirs; }; static TAILQ_HEAD(, dir_ent) dir_q; struct audit_trail { time_t at_time; char *at_path; off_t at_size; TAILQ_ENTRY(audit_trail) at_trls; }; static int auditd_minval = -1; static int auditd_dist = 0; static char auditd_host[MAXHOSTNAMELEN]; static int auditd_hostlen = -1; static char *auditd_errmsg[] = { "no error", /* ADE_NOERR ( 0) */ "could not parse audit_control(5) file", /* ADE_PARSE ( 1) */ "auditon(2) failed", /* ADE_AUDITON ( 2) */ "malloc(3) failed", /* ADE_NOMEM ( 3) */ "all audit log directories over soft limit", /* ADE_SOFTLIM ( 4) */ "all audit log directories over hard limit", /* ADE_HARDLIM ( 5) */ "could not create file name string", /* ADE_STRERR ( 6) */ "could not open audit record", /* ADE_AU_OPEN ( 7) */ "could not close audit record", /* ADE_AU_CLOSE ( 8) */ "could not set active audit session state", /* ADE_SETAUDIT ( 9) */ "auditctl(2) failed (trail still swapped)", /* ADE_ACTL (10) */ "auditctl(2) failed (trail not swapped)", /* ADE_ACTLERR (11) */ "could not swap audit trail file", /* ADE_SWAPERR (12) */ "could not rename crash recovery file", /* ADE_RENAME (13) */ "could not read 'current' link file", /* ADE_READLINK (14) */ "could not create 'current' link file", /* ADE_SYMLINK (15) */ "invalid argument", /* ADE_INVAL (16) */ "could not resolve hostname to address", /* ADE_GETADDR (17) */ "address family not supported", /* ADE_ADDRFAM (18) */ "error expiring audit trail files", /* ADE_EXPIRE (19) */ }; #define MAXERRCODE (sizeof(auditd_errmsg) / sizeof(auditd_errmsg[0])) #define NA_EVENT_STR_SIZE 128 #define POL_STR_SIZE 128 /* * Look up and return the error string for the given audit error code. */ const char * auditd_strerror(int errcode) { int idx = -errcode; if (idx < 0 || idx > (int)MAXERRCODE) return ("Invalid auditd error code"); return (auditd_errmsg[idx]); } /* * Free our local list of directory names and init list. */ static void free_dir_q(void) { struct dir_ent *d1, *d2; d1 = TAILQ_FIRST(&dir_q); while (d1 != NULL) { d2 = TAILQ_NEXT(d1, dirs); free(d1->dirname); free(d1); d1 = d2; } TAILQ_INIT(&dir_q); } /* * Concat the directory name to the given file name. * XXX We should affix the hostname also */ static char * affixdir(char *name, struct dir_ent *dirent) { char *fn = NULL; /* * Sanity check on file name. */ if (strlen(name) != FILENAME_LEN) { errno = EINVAL; return (NULL); } /* * If the host is set then also add the hostname to the filename. */ if (auditd_hostlen != -1) asprintf(&fn, "%s/%s.%s", dirent->dirname, name, auditd_host); else asprintf(&fn, "%s/%s", dirent->dirname, name); return (fn); } /* * Insert the directory entry in the list by the way they are ordered in * audit_control(5). Move the entries that are over the soft and hard limits * toward the tail. */ static void insert_orderly(struct dir_ent *denew) { struct dir_ent *dep; TAILQ_FOREACH(dep, &dir_q, dirs) { if (dep->softlim == 1 && denew->softlim == 0) { TAILQ_INSERT_BEFORE(dep, denew, dirs); return; } if (dep->hardlim == 1 && denew->hardlim == 0) { TAILQ_INSERT_BEFORE(dep, denew, dirs); return; } } TAILQ_INSERT_TAIL(&dir_q, denew, dirs); } /* * Get the min percentage of free blocks from audit_control(5) and that * value in the kernel. Return: * ADE_NOERR on success, * ADE_PARSE error parsing audit_control(5), */ int auditd_set_dist(void) { int ret; ret = getacdist(); if (ret < 0) return (ADE_PARSE); auditd_dist = ret; return (ADE_NOERR); } /* * Get the host from audit_control(5) and set it in the audit kernel * information. Return: * ADE_NOERR on success. * ADE_PARSE error parsing audit_control(5). * ADE_AUDITON error getting/setting auditon(2) value. * ADE_GETADDR error getting address info for host. * ADE_ADDRFAM un-supported address family. */ int auditd_set_host(void) { struct sockaddr_in6 *sin6; struct sockaddr_in *sin; struct addrinfo *res; struct auditinfo_addr aia; int error, ret = ADE_NOERR; if (getachost(auditd_host, sizeof(auditd_host)) != 0) { ret = ADE_PARSE; /* * To maintain reverse compatability with older audit_control * files, simply drop a warning if the host parameter has not * been set. However, we will explicitly disable the * generation of extended audit header by passing in a zeroed * termid structure. */ bzero(&aia, sizeof(aia)); aia.ai_termid.at_type = AU_IPv4; error = audit_set_kaudit(&aia, sizeof(aia)); if (error < 0 && errno != ENOSYS) ret = ADE_AUDITON; return (ret); } auditd_hostlen = strlen(auditd_host); error = getaddrinfo(auditd_host, NULL, NULL, &res); if (error) return (ADE_GETADDR); switch (res->ai_family) { case PF_INET6: sin6 = (struct sockaddr_in6 *) res->ai_addr; bcopy(&sin6->sin6_addr.s6_addr, &aia.ai_termid.at_addr[0], sizeof(struct in6_addr)); aia.ai_termid.at_type = AU_IPv6; break; case PF_INET: sin = (struct sockaddr_in *) res->ai_addr; bcopy(&sin->sin_addr.s_addr, &aia.ai_termid.at_addr[0], sizeof(struct in_addr)); aia.ai_termid.at_type = AU_IPv4; break; default: /* Un-supported address family in host parameter. */ errno = EAFNOSUPPORT; return (ADE_ADDRFAM); } if (audit_set_kaudit(&aia, sizeof(aia)) < 0) ret = ADE_AUDITON; return (ret); } /* * Get the min percentage of free blocks from audit_control(5) and that * value in the kernel. Return: * ADE_NOERR on success, * ADE_PARSE error parsing audit_control(5), * ADE_AUDITON error getting/setting auditon(2) value. */ int auditd_set_minfree(void) { au_qctrl_t qctrl; if (getacmin(&auditd_minval) != 0) return (ADE_PARSE); if (audit_get_qctrl(&qctrl, sizeof(qctrl)) != 0) return (ADE_AUDITON); if (qctrl.aq_minfree != auditd_minval) { qctrl.aq_minfree = auditd_minval; if (audit_set_qctrl(&qctrl, sizeof(qctrl)) != 0) return (ADE_AUDITON); } return (0); } /* * Convert a trailname into a timestamp (seconds). Return 0 if the conversion * was successful. */ static int trailname_to_tstamp(char *fn, time_t *tstamp) { struct tm tm; char ts[TIMESTAMP_LEN + 1]; char *p; *tstamp = 0; /* * Get the ending time stamp. */ if ((p = strchr(fn, '.')) == NULL) return (1); strlcpy(ts, ++p, sizeof(ts)); if (strlen(ts) != POSTFIX_LEN) return (1); bzero(&tm, sizeof(tm)); /* seconds (0-60) */ p = ts + POSTFIX_LEN - 2; tm.tm_sec = atol(p); if (tm.tm_sec < 0 || tm.tm_sec > 60) return (1); /* minutes (0-59) */ *p = '\0'; p -= 2; tm.tm_min = atol(p); if (tm.tm_min < 0 || tm.tm_min > 59) return (1); /* hours (0 - 23) */ *p = '\0'; p -= 2; tm.tm_hour = atol(p); if (tm.tm_hour < 0 || tm.tm_hour > 23) return (1); /* day of month (1-31) */ *p = '\0'; p -= 2; tm.tm_mday = atol(p); if (tm.tm_mday < 1 || tm.tm_mday > 31) return (1); /* month (0 - 11) */ *p = '\0'; p -= 2; tm.tm_mon = atol(p) - 1; if (tm.tm_mon < 0 || tm.tm_mon > 11) return (1); /* year (year - 1900) */ *p = '\0'; p -= 4; tm.tm_year = atol(p) - 1900; if (tm.tm_year < 0) return (1); *tstamp = timegm(&tm); return (0); } /* * Remove audit trails files according to the expiration conditions. Returns: * ADE_NOERR on success or there is nothing to do. * ADE_PARSE if error parsing audit_control(5). * ADE_NOMEM if could not allocate memory. - * ADE_EXPIRE if there was an unespected error. + * ADE_READLINK if could not read link file. + * ADE_EXPIRE if there was an unexpected error. */ int auditd_expire_trails(int (*warn_expired)(char *)) { - int andflg, ret = ADE_NOERR; + int andflg, len, ret = ADE_NOERR; size_t expire_size, total_size = 0L; time_t expire_age, oldest_time, current_time = time(NULL); struct dir_ent *traildir; struct audit_trail *at; char *afnp, *pn; TAILQ_HEAD(au_trls_head, audit_trail) head = TAILQ_HEAD_INITIALIZER(head); struct stat stbuf; char activefn[MAXPATHLEN]; /* * Read the expiration conditions. If no conditions then return no * error. */ if (getacexpire(&andflg, &expire_age, &expire_size) < 0) return (ADE_PARSE); if (!expire_age && !expire_size) return (ADE_NOERR); /* * Read the 'current' trail file name. Trim off directory path. */ activefn[0] = '\0'; - readlink(AUDIT_CURRENT_LINK, activefn, MAXPATHLEN - 1); + len = readlink(AUDIT_CURRENT_LINK, activefn, MAXPATHLEN - 1); + if (len < 0) + return (ADE_READLINK); if ((afnp = strrchr(activefn, '/')) != NULL) afnp++; /* * Build tail queue of the trail files. */ TAILQ_FOREACH(traildir, &dir_q, dirs) { DIR *dirp; struct dirent *dp; dirp = opendir(traildir->dirname); while ((dp = readdir(dirp)) != NULL) { time_t tstamp = 0; struct audit_trail *new; /* * Quickly filter non-trail files. */ if (dp->d_namlen < FILENAME_LEN || dp->d_name[POSTFIX_LEN] != '.') continue; if (asprintf(&pn, "%s/%s", traildir->dirname, dp->d_name) < 0) { ret = ADE_NOMEM; break; } if (stat(pn, &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) { free(pn); continue; } total_size += stbuf.st_size; /* * If this is the 'current' audit trail then * don't add it to the tail queue. */ if (NULL != afnp && strcmp(dp->d_name, afnp) == 0) { free(pn); continue; } /* * Get the ending time stamp encoded in the trail * name. If we can't read it or if it is older * than Jan 1, 2000 then use the mtime. */ if (trailname_to_tstamp(dp->d_name, &tstamp) != 0 || tstamp < JAN_01_2000) tstamp = stbuf.st_mtime; /* * If the time stamp is older than Jan 1, 2000 then * update the mtime of the trail file to the current * time. This is so we don't prematurely remove a trail * file that was created while the system clock reset * to the * "beginning of time" but later the system * clock is set to the correct current time. */ if (current_time >= JAN_01_2000 && tstamp < JAN_01_2000) { struct timeval tv[2]; tstamp = stbuf.st_mtime = current_time; TIMESPEC_TO_TIMEVAL(&tv[0], &stbuf.st_atimespec); TIMESPEC_TO_TIMEVAL(&tv[1], &stbuf.st_mtimespec); utimes(pn, tv); } /* * Allocate and populate the new entry. */ new = malloc(sizeof(*new)); if (NULL == new) { free(pn); ret = ADE_NOMEM; break; } new->at_time = tstamp; new->at_size = stbuf.st_size; new->at_path = pn; /* * Check to see if we have a new head. Otherwise, * walk the tailq from the tail first and do a simple * insertion sort. */ if (TAILQ_EMPTY(&head) || new->at_time <= TAILQ_FIRST(&head)->at_time) { TAILQ_INSERT_HEAD(&head, new, at_trls); continue; } TAILQ_FOREACH_REVERSE(at, &head, au_trls_head, at_trls) if (new->at_time >= at->at_time) { TAILQ_INSERT_AFTER(&head, at, new, at_trls); break; } } closedir(dirp); } oldest_time = current_time - expire_age; /* * Expire trail files, oldest (mtime) first, if the given * conditions are met. */ at = TAILQ_FIRST(&head); while (NULL != at) { struct audit_trail *at_next = TAILQ_NEXT(at, at_trls); if (andflg) { if ((expire_size && total_size > expire_size) && (expire_age && at->at_time < oldest_time)) { if (warn_expired) (*warn_expired)(at->at_path); if (unlink(at->at_path) < 0) ret = ADE_EXPIRE; total_size -= at->at_size; } } else { if ((expire_size && total_size > expire_size) || (expire_age && at->at_time < oldest_time)) { if (warn_expired) (*warn_expired)(at->at_path); if (unlink(at->at_path) < 0) ret = ADE_EXPIRE; total_size -= at->at_size; } } free(at->at_path); free(at); at = at_next; } return (ret); } /* * Parses the "dir" entry in audit_control(5) into an ordered list. Also, will * set the minfree and host values if not already set. Arguments include * function pointers to audit_warn functions for soft and hard limits. Returns: * ADE_NOERR on success, * ADE_PARSE error parsing audit_control(5), * ADE_AUDITON error getting/setting auditon(2) value, * ADE_NOMEM error allocating memory, * ADE_SOFTLIM if all the directories are over the soft limit, * ADE_HARDLIM if all the directories are over the hard limit, */ int auditd_read_dirs(int (*warn_soft)(char *), int (*warn_hard)(char *)) { char cur_dir[MAXNAMLEN]; struct dir_ent *dirent; struct statfs sfs; int err; char soft, hard; int tcnt = 0; int scnt = 0; int hcnt = 0; if (auditd_minval == -1 && (err = auditd_set_minfree()) != 0) return (err); if (auditd_hostlen == -1) auditd_set_host(); /* * Init directory q. Force a re-read of the file the next time. */ free_dir_q(); endac(); /* * Read the list of directories into an ordered linked list * admin's preference, then those over soft limit and, finally, * those over the hard limit. * * XXX We should use the reentrant interfaces once they are * available. */ while (getacdir(cur_dir, MAXNAMLEN) >= 0) { if (statfs(cur_dir, &sfs) < 0) continue; /* XXX should warn */ soft = (sfs.f_bfree < (sfs.f_blocks * auditd_minval / 100 )) ? 1 : 0; hard = (sfs.f_bfree < AUDIT_HARD_LIMIT_FREE_BLOCKS) ? 1 : 0; if (soft) { if (warn_soft) (*warn_soft)(cur_dir); scnt++; } if (hard) { if (warn_hard) (*warn_hard)(cur_dir); hcnt++; } dirent = (struct dir_ent *) malloc(sizeof(struct dir_ent)); if (dirent == NULL) return (ADE_NOMEM); dirent->softlim = soft; dirent->hardlim = hard; dirent->dirname = (char *) malloc(MAXNAMLEN); if (dirent->dirname == NULL) { free(dirent); return (ADE_NOMEM); } strlcpy(dirent->dirname, cur_dir, MAXNAMLEN); insert_orderly(dirent); tcnt++; } if (hcnt == tcnt) return (ADE_HARDLIM); if (scnt == tcnt) return (ADE_SOFTLIM); return (0); } void auditd_close_dirs(void) { free_dir_q(); auditd_minval = -1; auditd_hostlen = -1; } /* * Process the audit event file, obtaining a class mapping for each event, and * set that mapping into the kernel. Return: * n number of event mappings that were successfully processed, * ADE_NOMEM if there was an error allocating memory. */ int auditd_set_evcmap(void) { au_event_ent_t ev, *evp; au_evclass_map_t evc_map; int ctr = 0; /* * XXX There's a risk here that the BSM library will return NULL * for an event when it can't properly map it to a class. In that * case, we will not process any events beyond the one that failed, * but should. We need a way to get a count of the events. */ ev.ae_name = (char *)malloc(AU_EVENT_NAME_MAX); ev.ae_desc = (char *)malloc(AU_EVENT_DESC_MAX); if (ev.ae_name == NULL || ev.ae_desc == NULL) { if (ev.ae_name != NULL) free(ev.ae_name); return (ADE_NOMEM); } /* * XXXRW: Currently we have no way to remove mappings from the kernel * when they are removed from the file-based mappings. */ evp = &ev; setauevent(); while ((evp = getauevent_r(evp)) != NULL) { evc_map.ec_number = evp->ae_number; evc_map.ec_class = evp->ae_class; if (audit_set_class(&evc_map, sizeof(evc_map)) == 0) ctr++; } endauevent(); free(ev.ae_name); free(ev.ae_desc); return (ctr); } /* * Get the non-attributable event string and set the kernel mask. Return: * ADE_NOERR on success, * ADE_PARSE error parsing audit_control(5), * ADE_AUDITON error setting the mask using auditon(2). */ int auditd_set_namask(void) { au_mask_t aumask; char naeventstr[NA_EVENT_STR_SIZE]; if (getacna(naeventstr, NA_EVENT_STR_SIZE) != 0 || getauditflagsbin(naeventstr, &aumask) != 0) return (ADE_PARSE); if (audit_set_kmask(&aumask, sizeof(aumask)) != 0) return (ADE_AUDITON); return (ADE_NOERR); } /* * Set the audit control policy if a policy is configured in audit_control(5), * implement the policy. However, if one isn't defined or if there is an error * parsing the control file, set AUDIT_CNT to avoid leaving the system in a * fragile state. Return: * ADE_NOERR on success, * ADE_PARSE error parsing audit_control(5), * ADE_AUDITON error setting policy using auditon(2). */ int auditd_set_policy(void) { int policy; char polstr[POL_STR_SIZE]; if (getacpol(polstr, POL_STR_SIZE) != 0 || au_strtopol(polstr, &policy) != 0) { policy = AUDIT_CNT; if (audit_set_policy(&policy) != 0) return (ADE_AUDITON); return (ADE_PARSE); } if (audit_set_policy(&policy) != 0) return (ADE_AUDITON); return (ADE_NOERR); } /* * Set trail rotation size. Return: * ADE_NOERR on success, * ADE_PARSE error parsing audit_control(5), * ADE_AUDITON error setting file size using auditon(2). */ int auditd_set_fsize(void) { size_t filesz; au_fstat_t au_fstat; /* * Set trail rotation size. */ if (getacfilesz(&filesz) != 0) return (ADE_PARSE); bzero(&au_fstat, sizeof(au_fstat)); au_fstat.af_filesz = filesz; if (audit_set_fsize(&au_fstat, sizeof(au_fstat)) != 0) return (ADE_AUDITON); return (ADE_NOERR); } static void inject_dist(const char *fromname, char *toname, size_t tonamesize) { char *ptr; ptr = strrchr(fromname, '/'); assert(ptr != NULL); assert(ptr - fromname < (ssize_t)tonamesize); strlcpy(toname, fromname, ptr - fromname + 1); strlcat(toname, "/dist/", tonamesize); strlcat(toname, ptr + 1, tonamesize); } static int auditdist_link(const char *filename) { char fname[MAXPATHLEN]; if (auditd_dist) { inject_dist(filename, fname, sizeof(fname)); /* Ignore errors. */ (void) link(filename, fname); } return (0); } int auditd_rename(const char *fromname, const char *toname) { char fname[MAXPATHLEN], tname[MAXPATHLEN]; if (auditd_dist) { inject_dist(fromname, fname, sizeof(fname)); inject_dist(toname, tname, sizeof(tname)); /* Ignore errors. */ (void) rename(fname, tname); } return (rename(fromname, toname)); } /* * Create the new audit file with appropriate permissions and ownership. * Call auditctl(2) for this file. * Try to clean up if something goes wrong. * *errorp is modified only on auditctl(2) failure. */ static int open_trail(char *fname, gid_t gid, int *errorp) { int fd; /* XXXPJD: What should we do if the file already exists? */ fd = open(fname, O_RDONLY | O_CREAT, S_IRUSR); if (fd < 0) return (-1); if (fchown(fd, -1, gid) < 0 || fchmod(fd, S_IRUSR | S_IRGRP) < 0) { (void) close(fd); (void) unlink(fname); return (-1); } (void) close(fd); if (auditctl(fname) < 0) { *errorp = errno; (void) unlink(fname); return (-1); } (void) auditdist_link(fname); return (0); } /* * Create the new audit trail file, swap with existing audit file. Arguments * include timestamp for the filename, a pointer to a string for returning the * new file name, GID for trail file, and audit_warn function pointer for * 'getacdir()' errors. Returns: * ADE_NOERR on success, * ADE_STRERR if the file name string could not be created, * ADE_SWAPERR if the audit trail file could not be swapped, * ADE_ACTL if the auditctl(2) call failed but file swap still * successful. * ADE_ACTLERR if the auditctl(2) call failed and file swap failed. * ADE_SYMLINK if symlink(2) failed updating the current link. */ int auditd_swap_trail(char *TS, char **newfile, gid_t gid, int (*warn_getacdir)(char *)) { char timestr[FILENAME_LEN + 1]; char *fn; struct dir_ent *dirent; int saverrno = 0; if (strlen(TS) != TIMESTAMP_LEN || snprintf(timestr, sizeof(timestr), "%s.%s", TS, NOT_TERMINATED) < 0) { errno = EINVAL; return (ADE_STRERR); } /* Try until we succeed. */ TAILQ_FOREACH(dirent, &dir_q, dirs) { if (dirent->hardlim) continue; if ((fn = affixdir(timestr, dirent)) == NULL) return (ADE_STRERR); /* * Create the file and pass to the kernel if all went well. */ if (open_trail(fn, gid, &saverrno) == 0) { /* Success. */ *newfile = fn; if (saverrno) { /* * auditctl() failed but still * successful. Return errno and "soft" * error. */ errno = saverrno; return (ADE_ACTL); } return (ADE_NOERR); } /* * auditctl failed setting log file. Try again. */ /* * Tell the administrator about lack of permissions for dir. */ if (warn_getacdir != NULL) (*warn_getacdir)(dirent->dirname); } if (saverrno) { errno = saverrno; return (ADE_ACTLERR); } else return (ADE_SWAPERR); } /* * Mask calling process from being audited. Returns: * ADE_NOERR on success, * ADE_SETAUDIT if setaudit(2) fails. */ #ifdef __APPLE__ int auditd_prevent_audit(void) { auditinfo_addr_t aia; /* * To prevent event feedback cycles and avoid audit becoming stalled if * auditing is suspended we mask this processes events from being * audited. We allow the uid, tid, and mask fields to be implicitly * set to zero, but do set the audit session ID to the PID. * * XXXRW: Is there more to it than this? */ bzero(&aia, sizeof(aia)); aia.ai_asid = AU_ASSIGN_ASID; aia.ai_termid.at_type = AU_IPv4; if (setaudit_addr(&aia, sizeof(aia)) != 0) return (ADE_SETAUDIT); return (ADE_NOERR); } #else int auditd_prevent_audit(void) { auditinfo_t ai; /* * To prevent event feedback cycles and avoid audit becoming stalled if * auditing is suspended we mask this processes events from being * audited. We allow the uid, tid, and mask fields to be implicitly * set to zero, but do set the audit session ID to the PID. * * XXXRW: Is there more to it than this? */ bzero(&ai, sizeof(ai)); ai.ai_asid = getpid(); if (setaudit(&ai) != 0) return (ADE_SETAUDIT); return (ADE_NOERR); } #endif /* !__APPLE__ */ /* * Generate and submit audit record for audit startup or shutdown. The event * argument can be AUE_audit_recovery, AUE_audit_startup or * AUE_audit_shutdown. The path argument will add a path token, if not NULL. * Returns: * AUE_NOERR on success, * ADE_NOMEM if memory allocation fails, * ADE_AU_OPEN if au_open(3) fails, * ADE_AU_CLOSE if au_close(3) fails. */ int auditd_gen_record(int event, char *path) { int aufd; uid_t uid; pid_t pid; char *autext = NULL; token_t *tok; struct auditinfo_addr aia; if (event == AUE_audit_startup) asprintf(&autext, "%s::Audit startup", getprogname()); else if (event == AUE_audit_shutdown) asprintf(&autext, "%s::Audit shutdown", getprogname()); else if (event == AUE_audit_recovery) asprintf(&autext, "%s::Audit recovery", getprogname()); else return (ADE_INVAL); if (autext == NULL) return (ADE_NOMEM); if ((aufd = au_open()) == -1) { free(autext); return (ADE_AU_OPEN); } bzero(&aia, sizeof(aia)); uid = getuid(); pid = getpid(); if ((tok = au_to_subject32_ex(uid, geteuid(), getegid(), uid, getgid(), pid, pid, &aia.ai_termid)) != NULL) au_write(aufd, tok); if ((tok = au_to_text(autext)) != NULL) au_write(aufd, tok); free(autext); if (path != NULL && (tok = au_to_path(path)) != NULL) au_write(aufd, tok); if ((tok = au_to_return32(0, 0)) != NULL) au_write(aufd, tok); if (au_close(aufd, 1, event) == -1) return (ADE_AU_CLOSE); return (ADE_NOERR); } /* * Check for a 'current' symlink and do crash recovery, if needed. Create a new * 'current' symlink. The argument 'curfile' is the file the 'current' symlink * should point to. Returns: * ADE_NOERR on success, * ADE_AU_OPEN if au_open(3) fails, * ADE_AU_CLOSE if au_close(3) fails. * ADE_RENAME if error renaming audit trail file, * ADE_READLINK if error reading the 'current' link, * ADE_SYMLINK if error creating 'current' link. */ int auditd_new_curlink(char *curfile) { int len, err; char *ptr; char *path = NULL; struct stat sb; char recoveredname[MAXPATHLEN]; char newname[MAXPATHLEN]; /* * Check to see if audit was shutdown properly. If not, clean up, * recover previous audit trail file, and generate audit record. */ len = readlink(AUDIT_CURRENT_LINK, recoveredname, sizeof(recoveredname) - 1); if (len > 0) { /* 'current' exist but is it pointing at a valid file? */ recoveredname[len++] = '\0'; if (stat(recoveredname, &sb) == 0) { /* Yes, rename it to a crash recovery file. */ strlcpy(newname, recoveredname, sizeof(newname)); if ((ptr = strstr(newname, NOT_TERMINATED)) != NULL) { memcpy(ptr, CRASH_RECOVERY, POSTFIX_LEN); if (auditd_rename(recoveredname, newname) != 0) return (ADE_RENAME); } else return (ADE_STRERR); path = newname; } /* 'current' symlink is (now) invalid so remove it. */ (void) unlink(AUDIT_CURRENT_LINK); /* Note the crash recovery in current audit trail */ err = auditd_gen_record(AUE_audit_recovery, path); if (err) return (err); } if (len < 0 && errno != ENOENT) return (ADE_READLINK); if (symlink(curfile, AUDIT_CURRENT_LINK) != 0) return (ADE_SYMLINK); return (0); } /* * Do just what we need to quickly start auditing. Assume no system logging or * notify. Return: * 0 on success, * -1 on failure. */ int audit_quick_start(void) { int err; char *newfile = NULL; time_t tt; char TS[TIMESTAMP_LEN + 1]; int ret = 0; /* * Mask auditing of this process. */ if (auditd_prevent_audit() != 0) return (-1); /* * Read audit_control and get log directories. */ err = auditd_read_dirs(NULL, NULL); if (err != ADE_NOERR && err != ADE_SOFTLIM) return (-1); /* * Setup trail file distribution. */ (void) auditd_set_dist(); /* * Create a new audit trail log. */ if (getTSstr(tt, TS, sizeof(TS)) != 0) return (-1); err = auditd_swap_trail(TS, &newfile, getgid(), NULL); if (err != ADE_NOERR && err != ADE_ACTL) { ret = -1; goto out; } /* * Add the current symlink and recover from crash, if needed. */ if (auditd_new_curlink(newfile) != 0) { ret = -1; goto out; } /* * At this point auditing has started so generate audit start-up record. */ if (auditd_gen_record(AUE_audit_startup, NULL) != 0) { ret = -1; goto out; } /* * Configure the audit controls. */ (void) auditd_set_evcmap(); (void) auditd_set_namask(); (void) auditd_set_policy(); (void) auditd_set_fsize(); (void) auditd_set_minfree(); (void) auditd_set_host(); out: if (newfile != NULL) free(newfile); return (ret); } /* * Shut down auditing quickly. Assumes that is only called on system shutdown. * Returns: * 0 on success, * -1 on failure. */ int audit_quick_stop(void) { int len; int cond; char *ptr; time_t tt; char oldname[MAXPATHLEN]; char newname[MAXPATHLEN]; char TS[TIMESTAMP_LEN + 1]; /* * Auditing already disabled? */ if (audit_get_cond(&cond) != 0) return (-1); if (cond == AUC_NOAUDIT) return (0); /* * Generate audit shutdown record. */ (void) auditd_gen_record(AUE_audit_shutdown, NULL); /* * Shutdown auditing in the kernel. */ cond = AUC_DISABLED; if (audit_set_cond(&cond) != 0) return (-1); #ifdef __BSM_INTERNAL_NOTIFY_KEY notify_post(__BSM_INTERNAL_NOTIFY_KEY); #endif /* * Rename last audit trail and remove 'current' link. */ len = readlink(AUDIT_CURRENT_LINK, oldname, sizeof(oldname) - 1); if (len < 0) return (-1); oldname[len++] = '\0'; if (getTSstr(tt, TS, sizeof(TS)) != 0) return (-1); strlcpy(newname, oldname, sizeof(newname)); if ((ptr = strstr(newname, NOT_TERMINATED)) != NULL) { memcpy(ptr, TS, POSTFIX_LEN); if (auditd_rename(oldname, newname) != 0) return (-1); } else return (-1); (void) unlink(AUDIT_CURRENT_LINK); return (0); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libauditd/libauditd.3 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libauditd/libauditd.3 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libauditd/libauditd.3 (revision 292449) @@ -1,60 +1,58 @@ .\"- .\" Copyright (c) 2008 Apple Inc. .\" 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR .\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/libauditd/libauditd.3#1 $ -.\" .Dd December 27, 2008 .Dt LIBAUDITD 3 .Os .Sh NAME .Nm libauditd .Nd "auditd support library" .Sh LIBRARY .Lb libauditd .Sh DESCRIPTION The .Nm library provides the internal implementation of .Xr auditd 8 . .Sh INTERFACES There are no public interfaces in .Nm . .Sh SEE ALSO -.Xr auditd 8 . +.Xr auditd 8 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer, Inc., in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by .An Stacey Son . .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/Makefile.am (revision 292449) @@ -1,49 +1,157 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/libbsm/Makefile.am#10 $ -## - if USE_NATIVE_INCLUDES INCLUDES = -I$(top_builddir) -I$(top_srcdir) else INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys endif lib_LTLIBRARIES = libbsm.la libbsm_la_SOURCES = \ bsm_audit.c \ bsm_class.c \ bsm_control.c \ bsm_domain.c \ bsm_errno.c \ bsm_event.c \ bsm_fcntl.c \ bsm_flags.c \ bsm_io.c \ bsm_mask.c \ bsm_socket_type.c \ bsm_token.c \ bsm_user.c if HAVE_AUDIT_SYSCALLS libbsm_la_SOURCES += \ bsm_notify.c \ bsm_wrappers.c endif man3_MANS = \ au_class.3 \ au_control.3 \ au_domain.3 \ au_errno.3 \ au_event.3 \ au_fcntl_cmd.3 \ au_free_token.3 \ au_io.3 \ au_mask.3 \ + au_notify.3 \ au_open.3 \ au_socket_type.3 \ au_token.3 \ au_user.3 \ libbsm.3 +install-exec-hook: + cd $(DESTDIR)$(mandir) && \ + $(LN_S) -f au_class.3 getauclassent.3 && \ + $(LN_S) -f au_class.3 getauclassent_r.3 && \ + $(LN_S) -f au_class.3 getauclassnam.3 && \ + $(LN_S) -f au_class.3 getauclassnam_r.3 && \ + $(LN_S) -f au_class.3 setauclass.3 && \ + $(LN_S) -f au_class.3 endauclass.3 && \ + $(LN_S) -f au_control.3 setac.3 && \ + $(LN_S) -f au_control.3 endac.3 && \ + $(LN_S) -f au_control.3 getacdir.3 && \ + $(LN_S) -f au_control.3 getacdist.3 && \ + $(LN_S) -f au_control.3 getacexpire.3 && \ + $(LN_S) -f au_control.3 getacfilesz.3 && \ + $(LN_S) -f au_control.3 getacflg.3 && \ + $(LN_S) -f au_control.3 getachost.3 && \ + $(LN_S) -f au_control.3 getacmin.3 && \ + $(LN_S) -f au_control.3 getacna.3 && \ + $(LN_S) -f au_control.3 getacpol.3 && \ + $(LN_S) -f au_control.3 au_poltostr.3 && \ + $(LN_S) -f au_control.3 ac_strtopol.3 && \ + $(LN_S) -f au_domain.3 au_bsm_to_domain.3 && \ + $(LN_S) -f au_domain.3 au_domain_to_bsm.3 && \ + $(LN_S) -f au_errno.3 au_bsm_to_errno.3 && \ + $(LN_S) -f au_errno.3 au_errno_to_bsm.3 && \ + $(LN_S) -f au_errno.3 au_strerror.3 && \ + $(LN_S) -f au_event.3 setauevent.3 && \ + $(LN_S) -f au_event.3 endauevent.3 && \ + $(LN_S) -f au_event.3 getauevent.3 && \ + $(LN_S) -f au_event.3 getauevent_r.3 && \ + $(LN_S) -f au_event.3 getauevnam.3 && \ + $(LN_S) -f au_event.3 getauevnam_r.3 && \ + $(LN_S) -f au_event.3 getauevnum.3 && \ + $(LN_S) -f au_event.3 getauevnum_r.3 && \ + $(LN_S) -f au_event.3 getauevnonam.3 && \ + $(LN_S) -f au_event.3 getauevnonam_r.3 && \ + $(LN_S) -f au_fcntl.3 au_bsm_to_fcntl_cmd.3 && \ + $(LN_S) -f au_fcntl.3 au_fcntl_cmd_to_bsm.3 && \ + $(LN_S) -f au_io.3 au_fetch_tok.3 && \ + $(LN_S) -f au_io.3 au_print_tok.3 && \ + $(LN_S) -f au_io.3 au_print_flags_tok.3 && \ + $(LN_S) -f au_io.3 au_read_rec.3 && \ + $(LN_S) -f au_mask.3 au_preselect.3 && \ + $(LN_S) -f au_mask.3 getauditflagsbin.3 && \ + $(LN_S) -f au_mask.3 getauditflagschar.3 && \ + $(LN_S) -f au_notify.3 au_get_state.3 && \ + $(LN_S) -f au_notify.3 au_notify_initialize.3 && \ + $(LN_S) -f au_notify.3 au_notify_terminate.3 && \ + $(LN_S) -f au_open.3 au_open.3 && \ + $(LN_S) -f au_open.3 au_write.3 && \ + $(LN_S) -f au_open.3 au_close.3 && \ + $(LN_S) -f au_open.3 au_close_buffer.3 && \ + $(LN_S) -f au_open.3 au_close_token.3 && \ + $(LN_S) -f au_socket_type.3 au_bsm_to_socket_type.3 && \ + $(LN_S) -f au_socket_type.3 au_socket_type_to_bsm.3 && \ + $(LN_S) -f au_token.3 au_to_arg32.3 && \ + $(LN_S) -f au_token.3 au_to_arg64.3 && \ + $(LN_S) -f au_token.3 au_to_arg.3 && \ + $(LN_S) -f au_token.3 au_to_attr64.3 && \ + $(LN_S) -f au_token.3 au_to_data.3 && \ + $(LN_S) -f au_token.3 au_to_exit.3 && \ + $(LN_S) -f au_token.3 au_to_groups.3 && \ + $(LN_S) -f au_token.3 au_to_newgroups.3 && \ + $(LN_S) -f au_token.3 au_to_in_addr.3 && \ + $(LN_S) -f au_token.3 au_to_in_addr_ex.3 && \ + $(LN_S) -f au_token.3 au_to_ip.3 && \ + $(LN_S) -f au_token.3 au_to_ipc.3 && \ + $(LN_S) -f au_token.3 au_to_ipc_perm.3 && \ + $(LN_S) -f au_token.3 au_to_iport.3 && \ + $(LN_S) -f au_token.3 au_to_opaque.3 && \ + $(LN_S) -f au_token.3 au_to_file.3 && \ + $(LN_S) -f au_token.3 au_to_text.3 && \ + $(LN_S) -f au_token.3 au_to_path.3 && \ + $(LN_S) -f au_token.3 au_to_process32.3 && \ + $(LN_S) -f au_token.3 au_to_process64.3 && \ + $(LN_S) -f au_token.3 au_to_process.3 && \ + $(LN_S) -f au_token.3 au_to_process32_ex.3 && \ + $(LN_S) -f au_token.3 au_to_process64_ex.3 && \ + $(LN_S) -f au_token.3 au_to_process_ex.3 && \ + $(LN_S) -f au_token.3 au_to_return32.3 && \ + $(LN_S) -f au_token.3 au_to_return64.3 && \ + $(LN_S) -f au_token.3 au_to_return.3 && \ + $(LN_S) -f au_token.3 au_to_seq.3 && \ + $(LN_S) -f au_token.3 au_to_sock_inet32.3 && \ + $(LN_S) -f au_token.3 au_to_sock_inet128.3 && \ + $(LN_S) -f au_token.3 au_to_sock_inet.3 && \ + $(LN_S) -f au_token.3 au_to_socket_ex.3 && \ + $(LN_S) -f au_token.3 au_to_subject32.3 && \ + $(LN_S) -f au_token.3 au_to_subject64.3 && \ + $(LN_S) -f au_token.3 au_to_subject.3 && \ + $(LN_S) -f au_token.3 au_to_subject32_ex.3 && \ + $(LN_S) -f au_token.3 au_to_subject64_ex.3 && \ + $(LN_S) -f au_token.3 au_to_subject_ex.3 && \ + $(LN_S) -f au_token.3 au_to_me.3 && \ + $(LN_S) -f au_token.3 au_to_exec_args.3 && \ + $(LN_S) -f au_token.3 au_to_exec_env.3 && \ + $(LN_S) -f au_token.3 au_to_header.3 && \ + $(LN_S) -f au_token.3 au_to_header32.3 && \ + $(LN_S) -f au_token.3 au_to_header64.3 && \ + $(LN_S) -f au_token.3 au_to_header_ex.3 && \ + $(LN_S) -f au_token.3 au_to_header32_ex.3 && \ + $(LN_S) -f au_token.3 au_to_trailer.3 && \ + $(LN_S) -f au_token.3 au_to_zonename.3 && \ + $(LN_S) -f au_user.3 setauuser.3 && \ + $(LN_S) -f au_user.3 endauuser.3 && \ + $(LN_S) -f au_user.3 getauuserent.3 && \ + $(LN_S) -f au_user.3 getauuserent_r.3 && \ + $(LN_S) -f au_user.3 getauusernam.3 && \ + $(LN_S) -f au_user.3 getauusernam_r.3 && \ + $(LN_S) -f au_user.3 au_user_mask.3 && \ + $(LN_S) -f au_user.3 getfauditflags.3 Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/Makefile.in =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/Makefile.in (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/Makefile.in (revision 292449) @@ -1,678 +1,792 @@ # Makefile.in generated by automake 1.12.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 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__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } 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@ @HAVE_AUDIT_SYSCALLS_TRUE@am__append_1 = \ @HAVE_AUDIT_SYSCALLS_TRUE@ bsm_notify.c \ @HAVE_AUDIT_SYSCALLS_TRUE@ bsm_wrappers.c subdir = libbsm DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/config/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config/config.h 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)" "$(DESTDIR)$(man3dir)" LTLIBRARIES = $(lib_LTLIBRARIES) libbsm_la_LIBADD = am__libbsm_la_SOURCES_DIST = bsm_audit.c bsm_class.c bsm_control.c \ bsm_domain.c bsm_errno.c bsm_event.c bsm_fcntl.c bsm_flags.c \ bsm_io.c bsm_mask.c bsm_socket_type.c bsm_token.c bsm_user.c \ bsm_notify.c bsm_wrappers.c @HAVE_AUDIT_SYSCALLS_TRUE@am__objects_1 = bsm_notify.lo \ @HAVE_AUDIT_SYSCALLS_TRUE@ bsm_wrappers.lo am_libbsm_la_OBJECTS = bsm_audit.lo bsm_class.lo bsm_control.lo \ bsm_domain.lo bsm_errno.lo bsm_event.lo bsm_fcntl.lo \ bsm_flags.lo bsm_io.lo bsm_mask.lo bsm_socket_type.lo \ bsm_token.lo bsm_user.lo $(am__objects_1) libbsm_la_OBJECTS = $(am_libbsm_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libbsm_la_SOURCES) DIST_SOURCES = $(am__libbsm_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac man3dir = $(mandir)/man3 NROFF = nroff MANS = $(man3_MANS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ 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@ 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@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MIG = @MIG@ 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@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ 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_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@ 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@ 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@ @USE_NATIVE_INCLUDES_FALSE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys @USE_NATIVE_INCLUDES_TRUE@INCLUDES = -I$(top_builddir) -I$(top_srcdir) lib_LTLIBRARIES = libbsm.la libbsm_la_SOURCES = bsm_audit.c bsm_class.c bsm_control.c bsm_domain.c \ bsm_errno.c bsm_event.c bsm_fcntl.c bsm_flags.c bsm_io.c \ bsm_mask.c bsm_socket_type.c bsm_token.c bsm_user.c \ $(am__append_1) man3_MANS = \ au_class.3 \ au_control.3 \ au_domain.3 \ au_errno.3 \ au_event.3 \ au_fcntl_cmd.3 \ au_free_token.3 \ au_io.3 \ au_mask.3 \ + au_notify.3 \ au_open.3 \ au_socket_type.3 \ au_token.3 \ au_user.3 \ libbsm.3 all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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 libbsm/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign libbsm/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(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}; \ } libbsm.la: $(libbsm_la_OBJECTS) $(libbsm_la_DEPENDENCIES) $(EXTRA_libbsm_la_DEPENDENCIES) $(LINK) -rpath $(libdir) $(libbsm_la_OBJECTS) $(libbsm_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_audit.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_class.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_control.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_domain.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_errno.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_event.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_fcntl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_flags.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_io.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_mask.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_notify.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_socket_type.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_token.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_user.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsm_wrappers.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man3: $(man3_MANS) @$(NORMAL_INSTALL) @list1='$(man3_MANS)'; \ list2=''; \ test -n "$(man3dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man3dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man3dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.3[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ done; } uninstall-man3: @$(NORMAL_UNINSTALL) @list='$(man3_MANS)'; test -n "$(man3dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man3dir)'; $(am__uninstall_files_from_dir) ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ 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 CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ 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: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ 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: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically 'make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @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) $(MANS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(man3dir)"; 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." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -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-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES - + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man3 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -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 uninstall-man uninstall-man: uninstall-man3 -.MAKE: install-am install-strip +.MAKE: install-am install-exec-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist ctags 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-dvi-am install-exec install-exec-am install-exec-hook \ + install-html install-html-am install-info install-info-am \ install-libLTLIBRARIES install-man install-man3 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 uninstall uninstall-am uninstall-libLTLIBRARIES \ uninstall-man uninstall-man3 + +install-exec-hook: + cd $(DESTDIR)$(mandir) && \ + $(LN_S) -f au_class.3 getauclassent.3 && \ + $(LN_S) -f au_class.3 getauclassent_r.3 && \ + $(LN_S) -f au_class.3 getauclassnam.3 && \ + $(LN_S) -f au_class.3 getauclassnam_r.3 && \ + $(LN_S) -f au_class.3 setauclass.3 && \ + $(LN_S) -f au_class.3 endauclass.3 && \ + $(LN_S) -f au_control.3 setac.3 && \ + $(LN_S) -f au_control.3 endac.3 && \ + $(LN_S) -f au_control.3 getacdir.3 && \ + $(LN_S) -f au_control.3 getacdist.3 && \ + $(LN_S) -f au_control.3 getacexpire.3 && \ + $(LN_S) -f au_control.3 getacfilesz.3 && \ + $(LN_S) -f au_control.3 getacflg.3 && \ + $(LN_S) -f au_control.3 getachost.3 && \ + $(LN_S) -f au_control.3 getacmin.3 && \ + $(LN_S) -f au_control.3 getacna.3 && \ + $(LN_S) -f au_control.3 getacpol.3 && \ + $(LN_S) -f au_control.3 au_poltostr.3 && \ + $(LN_S) -f au_control.3 ac_strtopol.3 && \ + $(LN_S) -f au_domain.3 au_bsm_to_domain.3 && \ + $(LN_S) -f au_domain.3 au_domain_to_bsm.3 && \ + $(LN_S) -f au_errno.3 au_bsm_to_errno.3 && \ + $(LN_S) -f au_errno.3 au_errno_to_bsm.3 && \ + $(LN_S) -f au_errno.3 au_strerror.3 && \ + $(LN_S) -f au_event.3 setauevent.3 && \ + $(LN_S) -f au_event.3 endauevent.3 && \ + $(LN_S) -f au_event.3 getauevent.3 && \ + $(LN_S) -f au_event.3 getauevent_r.3 && \ + $(LN_S) -f au_event.3 getauevnam.3 && \ + $(LN_S) -f au_event.3 getauevnam_r.3 && \ + $(LN_S) -f au_event.3 getauevnum.3 && \ + $(LN_S) -f au_event.3 getauevnum_r.3 && \ + $(LN_S) -f au_event.3 getauevnonam.3 && \ + $(LN_S) -f au_event.3 getauevnonam_r.3 && \ + $(LN_S) -f au_fcntl.3 au_bsm_to_fcntl_cmd.3 && \ + $(LN_S) -f au_fcntl.3 au_fcntl_cmd_to_bsm.3 && \ + $(LN_S) -f au_io.3 au_fetch_tok.3 && \ + $(LN_S) -f au_io.3 au_print_tok.3 && \ + $(LN_S) -f au_io.3 au_print_flags_tok.3 && \ + $(LN_S) -f au_io.3 au_read_rec.3 && \ + $(LN_S) -f au_mask.3 au_preselect.3 && \ + $(LN_S) -f au_mask.3 getauditflagsbin.3 && \ + $(LN_S) -f au_mask.3 getauditflagschar.3 && \ + $(LN_S) -f au_notify.3 au_get_state.3 && \ + $(LN_S) -f au_notify.3 au_notify_initialize.3 && \ + $(LN_S) -f au_notify.3 au_notify_terminate.3 && \ + $(LN_S) -f au_open.3 au_open.3 && \ + $(LN_S) -f au_open.3 au_write.3 && \ + $(LN_S) -f au_open.3 au_close.3 && \ + $(LN_S) -f au_open.3 au_close_buffer.3 && \ + $(LN_S) -f au_open.3 au_close_token.3 && \ + $(LN_S) -f au_socket_type.3 au_bsm_to_socket_type.3 && \ + $(LN_S) -f au_socket_type.3 au_socket_type_to_bsm.3 && \ + $(LN_S) -f au_token.3 au_to_arg32.3 && \ + $(LN_S) -f au_token.3 au_to_arg64.3 && \ + $(LN_S) -f au_token.3 au_to_arg.3 && \ + $(LN_S) -f au_token.3 au_to_attr64.3 && \ + $(LN_S) -f au_token.3 au_to_data.3 && \ + $(LN_S) -f au_token.3 au_to_exit.3 && \ + $(LN_S) -f au_token.3 au_to_groups.3 && \ + $(LN_S) -f au_token.3 au_to_newgroups.3 && \ + $(LN_S) -f au_token.3 au_to_in_addr.3 && \ + $(LN_S) -f au_token.3 au_to_in_addr_ex.3 && \ + $(LN_S) -f au_token.3 au_to_ip.3 && \ + $(LN_S) -f au_token.3 au_to_ipc.3 && \ + $(LN_S) -f au_token.3 au_to_ipc_perm.3 && \ + $(LN_S) -f au_token.3 au_to_iport.3 && \ + $(LN_S) -f au_token.3 au_to_opaque.3 && \ + $(LN_S) -f au_token.3 au_to_file.3 && \ + $(LN_S) -f au_token.3 au_to_text.3 && \ + $(LN_S) -f au_token.3 au_to_path.3 && \ + $(LN_S) -f au_token.3 au_to_process32.3 && \ + $(LN_S) -f au_token.3 au_to_process64.3 && \ + $(LN_S) -f au_token.3 au_to_process.3 && \ + $(LN_S) -f au_token.3 au_to_process32_ex.3 && \ + $(LN_S) -f au_token.3 au_to_process64_ex.3 && \ + $(LN_S) -f au_token.3 au_to_process_ex.3 && \ + $(LN_S) -f au_token.3 au_to_return32.3 && \ + $(LN_S) -f au_token.3 au_to_return64.3 && \ + $(LN_S) -f au_token.3 au_to_return.3 && \ + $(LN_S) -f au_token.3 au_to_seq.3 && \ + $(LN_S) -f au_token.3 au_to_sock_inet32.3 && \ + $(LN_S) -f au_token.3 au_to_sock_inet128.3 && \ + $(LN_S) -f au_token.3 au_to_sock_inet.3 && \ + $(LN_S) -f au_token.3 au_to_socket_ex.3 && \ + $(LN_S) -f au_token.3 au_to_subject32.3 && \ + $(LN_S) -f au_token.3 au_to_subject64.3 && \ + $(LN_S) -f au_token.3 au_to_subject.3 && \ + $(LN_S) -f au_token.3 au_to_subject32_ex.3 && \ + $(LN_S) -f au_token.3 au_to_subject64_ex.3 && \ + $(LN_S) -f au_token.3 au_to_subject_ex.3 && \ + $(LN_S) -f au_token.3 au_to_me.3 && \ + $(LN_S) -f au_token.3 au_to_exec_args.3 && \ + $(LN_S) -f au_token.3 au_to_exec_env.3 && \ + $(LN_S) -f au_token.3 au_to_header.3 && \ + $(LN_S) -f au_token.3 au_to_header32.3 && \ + $(LN_S) -f au_token.3 au_to_header64.3 && \ + $(LN_S) -f au_token.3 au_to_header_ex.3 && \ + $(LN_S) -f au_token.3 au_to_header32_ex.3 && \ + $(LN_S) -f au_token.3 au_to_trailer.3 && \ + $(LN_S) -f au_token.3 au_to_zonename.3 && \ + $(LN_S) -f au_user.3 setauuser.3 && \ + $(LN_S) -f au_user.3 endauuser.3 && \ + $(LN_S) -f au_user.3 getauuserent.3 && \ + $(LN_S) -f au_user.3 getauuserent_r.3 && \ + $(LN_S) -f au_user.3 getauusernam.3 && \ + $(LN_S) -f au_user.3 getauusernam_r.3 && \ + $(LN_S) -f au_user.3 au_user_mask.3 && \ + $(LN_S) -f au_user.3 getfauditflags.3 # 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: Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_class.3 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_class.3 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_class.3 (revision 292449) @@ -1,120 +1,118 @@ .\"- .\" Copyright (c) 2005-2006 Robert N. M. Watson .\" 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_class.3#7 $ -.\" .Dd April 19, 2005 .Dt AU_CLASS 3 .Os .Sh NAME .Nm getauclassent , .Nm getauclassent_r , .Nm getauclassnam , .Nm getauclassnam_r , .Nm setauclass , .Nm endauclass .Nd "look up information from the audit_class database" .Sh LIBRARY .Lb libbsm .Sh SYNOPSIS .In bsm/libbsm.h .Ft "struct au_class_ent *" .Fn getauclassent void .Ft "struct au_class_ent *" .Fn getauclassent_r "struct au_class_ent *e" .Ft "struct au_class_ent *" .Fn getauclassnam "const char *name" .Ft "struct au_class_ent *" .Fn getauclassnam_r "struct au_class_ent *e" "const char *name" .Ft void .Fn setauclass void .Ft void .Fn endauclass void .Sh DESCRIPTION These interfaces may be used to look up information from the .Xr audit_class 5 database, which describes audit event classes. Audit event classes are described by .Vt "struct au_class_ent" . .Pp The .Fn getauclassent function will return the next class found in the .Xr audit_class 5 database, or the first if the function has not yet been called. .Dv NULL will be returned if no further records are available. .Pp The .Fn getauclassnam function looks up a class by name. .Dv NULL will be returned if no matching class can be found. .Pp The .Fn setauclass function resets the iterator through the .Xr audit_class 5 database, causing the next call to .Fn getauclassent to start again from the beginning of the file. .Pp The .Fn endauclass function closes the .Xr audit_class 5 database, if open. .Sh SEE ALSO .Xr libbsm 3 , .Xr audit_class 5 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer, Inc., in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by .An Robert Watson , .An Wayne Salamon , and .An Suresh Krishnaswamy for McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer, Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. .Sh BUGS These routines cannot currently distinguish between an entry not being found and an error accessing the database. The implementation should be changed to return an error via .Va errno when .Dv NULL is returned. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_control.3 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_control.3 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_control.3 (revision 292449) @@ -1,260 +1,258 @@ .\"- .\" Copyright (c) 2005-2006 Robert N. M. Watson .\" 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_control.3#17 $ -.\" .Dd April 19, 2005 .Dt AU_CONTROL 3 .Os .Sh NAME .Nm setac , .Nm endac , .Nm getacdir , .Nm getacdist , .Nm getacexpire , .Nm getacfilesz , .Nm getacflg , .Nm getachost , .Nm getacmin , .Nm getacna , .Nm getacpol , .Nm au_poltostr , .Nm au_strtopol .Nd "look up information from the audit_control database" .Sh LIBRARY .Lb libbsm .Sh SYNOPSIS .In bsm/libbsm.h .Ft void .Fn setac void .Ft void .Fn endac void .Ft int .Fn getacdir "char *name" "int len" .Ft int .Fn getacdist "void" .Ft int -.Fn getacexpire "int *andflg, time_t *age, size_t *size" +.Fn getacexpire "int *andflg" "time_t *age" "size_t *size" .Ft int .Fn getacfilesz "size_t *size_val" .Ft int .Fn getacflg "char *auditstr" "int len" .Ft int .Fn getachost "char *auditstr" "int len" .Ft int .Fn getacmin "int *min_val" .Ft int .Fn getacna "char *auditstr" "int len" .Ft int .Fn getacpol "char *auditstr" "size_t len" .Ft ssize_t .Fn au_poltostr "int policy" "size_t maxsize" "char *buf" .Ft int .Fn au_strtopol "const char *polstr" "int *policy" .Sh DESCRIPTION These interfaces may be used to look up information from the .Xr audit_control 5 database, which contains various audit-related administrative parameters. .Pp The .Fn setac function resets the database iterator to the beginning of the database; see the .Sx BUGS section for more information. .Pp The .Fn endac function closes the .Xr audit_control 5 database. .Pp The .Fn getacdir function returns the name of the directory where log data is stored via the passed character buffer .Fa name of length .Fa len . .Pp The .Fn getacdist function returns a value that allows to decide if trail files distribution is turned on or off. .Pp The .Fn getacexpire function returns the audit trail file expiration parameters in the passed .Vt int buffer .Fa andflg , .Vt time_t buffer .Fa age and .Vt size_t buffer .Fa size . If the parameter is not specified in the .Xr audit_control 5 file it is set to zero. .Pp The .Fn getacfilesz function returns the audit trail rotation size in the passed .Vt size_t buffer .Fa size_val . .Pp The .Fn getacflg function returns the audit system flags via the the passed character buffer .Fa auditstr of length .Fa len . .Pp The .Fn getachost function returns the local systems's audit host information via the the passed character buffer .Fa auditstr of length .Fa len . .Pp The .Fn getacmin function returns the minimum free disk space for the audit log target file system via the passed .Fa min_val variable. .Pp The .Fn getacna function returns the non-attributable flags via the passed character buffer .Fa auditstr of length .Fa len . .Pp The .Fn getacpol function returns the audit policy flags via the passed character buffer .Fa auditstr of length .Fa len . .Pp The .Fn au_poltostr function converts a numeric audit policy mask, .Fa policy , to a string in the passed character buffer .Fa buf of lenth .Fa maxsize . .Pp The .Fn au_strtopol function converts an audit policy flags string, .Fa polstr , to a numeric audit policy mask returned via .Fa policy . .Sh RETURN VALULES The .Fn getacfilesz , .Fn getacdir , .Fn getacexpire , .Fn getacflg , .Fn getachost , .Fn getacmin , .Fn getacna , .Fn getacpol , and .Fn au_strtopol functions return 0 on success, or a negative value on failure, along with error information in .Va errno . .Pp The .Fn au_poltostr function returns a string length of 0 or more on success, or a negative value on if there is a failure. .Pp The .Fn getacdist function returns 1 if trail files distribution is turned on, 0 if it is turned off or negative value on failure. .Pp Functions that return a string value will return a failure if there is insufficient room in the passed character buffer for the full string. .Sh SEE ALSO .Xr libbsm 3 , .Xr audit_control 5 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer, Inc., in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by .An Robert Watson , .An Wayne Salamon , and .An Suresh Krishnaswamy for McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer, Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. .Sh BUGS These routines cannot currently distinguish between an entry not being found and an error accessing the database. The implementation should be changed to return an error via .Va errno when .Dv NULL is returned. .Pp There is no reason for the .Fn setac interface to be exposed as part of the public API, as it is called implicitly by other access functions and iteration is not supported. .Pp These interfaces inconsistently return various negative values depending on the failure mode, and do not always set .Va errno on failure. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_domain.3 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_domain.3 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_domain.3 (revision 292449) @@ -1,88 +1,86 @@ .\"- .\" Copyright (c) 2008 Apple Inc. .\" 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR .\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_domain.3#2 $ -.\" .Dd December 28, 2008 .Dt AU_BSM_TO_DOMAIN 3 .Os .Sh NAME .Nm au_bsm_to_domain , .Nm au_domain_to_bsm .Nd "convert between BSM and local protocol domains" .Sh LIBRARY .Lb libbsm .Sh SYNOPSIS .In bsm/libbsm.h .Ft int .Fn au_bsm_to_domain "u_short bsm_domain" "int *local_domainp" .Ft u_short .Fn au_domain_to_bsm "int local_domain" .Sh DESCRIPTION These interfaces may be used to convert between the local and BSM protocol domains. The .Fn au_bsm_to_domain function accepts a BSM domain, .Fa bsm_domain , and converts it to a local domain, such as those passed to .Xr socket 2 , that will be stored in the integer pointed to by .Fa local_domainp if successful. This call will fail if the BSM domain cannot be mapped into a local domain, which may occur if the socket token was generated on another operating system. .Pp The .Fn au_domain_to_bsm function accepts a local domain, and returns the BSM domain for it. This call cannot fail, and instead returns a BSM domain indicating to a later decoder that the domain could not be encoded. .Sh RETURN VALULES On success, .Fn au_bsm_to_domain returns 0 and a converted domain; on failure, it returns -1 but does not set .Xr errno 2 . .Sh SEE ALSO .Xr au_bsm_to_socket_type 3 , .Xr au_socket_type_to_bsm 3 , .Xr au_to_socket_ex 3 , .Xr libbsm 3 .Sh HISTORY .Fn au_bsm_to_domain and .Fn au_domain_to_bsm were introduced in OpenBSM 1.1. .Sh AUTHORS These functions were implemented by .An Robert Watson under contract to Apple Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_errno.3 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_errno.3 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_errno.3 (revision 292449) @@ -1,112 +1,110 @@ .\"- .\" Copyright (c) 2008 Apple Inc. .\" 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR .\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_errno.3#4 $ -.\" .Dd December 8, 2008 .Dt AU_BSM_TO_ERRNO 3 .Os .Sh NAME .Nm au_bsm_to_errno , .Nm au_errno_to_bsm , .Nm au_strerror .Nd "convert between BSM and local error numbers" .Sh LIBRARY .Lb libbsm .Sh SYNOPSIS .In bsm/libbsm.h .Ft int .Fn au_bsm_to_errno "u_char bsm_error" "int *errorp" .Ft u_char .Fn au_errno_to_bsm "int error" .Ft const char * .Fn au_strerror "int bsm_error" .Sh DESCRIPTION These interfaces may be used to convert between the local ( .Xr errno 2 ) and BSM error number spaces found in BSM return tokens. .Pp The .Fn au_bsm_to_errno function accepts a BSM error value, -.Fa bsm_error, +.Fa bsm_error , and converts it to an .Xr errno 2 that will be stored in the integer pointed to by .Fa errorp if successful. This call will fail if the BSM error cannot be mapped into a local error number, which may occur if the return token was generated on another operating system. .Pp The .Fn au_errno_to_bsm function accepts a local .Xr errno 2 value, and returns the BSM error number for it. This call cannot fail, and instead returns a BSM error number indicating to a later decoder that the error could not be encoded. .Pp The .Fn au_strerror function converts a BSM error value to a string, generally by converting first to a local error number and using the local .Xr strerror 3 function, but will also work for errors that are not locally defined. .Sh RETURN VALULES On success, .Fn au_bsm_to_errno returns 0 and a converted error value; on failure, it returns -1 but does not set .Xr errno 2 . .Pp On success, .Fn au_strerror returns a pointer to an error string; on failure it will return .Dv NULL . .Sh SEE ALSO .Xr au_to_return 3 , .Xr au_to_return32 3 , .Xr au_to_return64 3 , .Xr libbsm 3 .Sh HISTORY .Fn au_bsm_to_errno and .Fn au_errno_to_bsm were introduced in OpenBSM 1.1. .Sh AUTHORS These functions were implemented by .An Robert Watson under contract to Apple Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. .Sh BUGS .Nm au_strerror is unable to provide localized strings for errors not available in the local operating system. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_event.3 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_event.3 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_event.3 (revision 292449) @@ -1,171 +1,169 @@ .\"- .\" Copyright (c) 2005-2006 Robert N. M. Watson .\" 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_event.3#8 $ -.\" .Dd April 19, 2005 .Dt AU_EVENT 3 .Os .Sh NAME .Nm free_au_event_ent , .Nm setauevent , .Nm endauevent , .Nm getauevent , .Nm getauevent_r , .Nm getauevnam , .Nm getauevnam_r , .Nm getauevnum , .Nm getauevnum_r , .Nm getauevnonam , .Nm getauevnonam_r .Nd "look up information from the audit_event database" .Sh LIBRARY .Lb libbsm .Sh SYNOPSIS .In bsm/libbsm.h .Ft void .Fn setauevent void .Ft void .Fn endauevent void .Ft "struct au_event_ent *" .Fn getauevent void .Ft "struct au_event_ent *" .Fn getauevent_r "struct au_event_ent *e" .Ft "struct au_event_ent *" .Fn getauevnam "const char *name" .Ft "struct au_event_ent *" .Fn getauevnam_r "struct au_event_ent *e" "const char *name" .Ft "struct au_event_ent *" .Fn getauevnum "au_event_t event_number" .Ft "struct au_event_ent *" .Fn getauevnum_r "struct au_event_ent *e" "au_event_t event_number" .Ft "au_event_t *" .Fn getauevnonam "const char *event_name" .Ft "au_event_t *" .Fn getauevnonam_r "au_event_t *ev" "const char *event_name" .Sh DESCRIPTION These interfaces may be used to look up information from the .Xr audit_event 5 database, which describes audit events. Entries in the database are described by .Vt "struct au_event_ent" entries, which are returned by calls to .Fn getauevent , .Fn getauevnam , or .Fn getauevnum . It is also possible to look up an event number via a call to .Fn getauevnonam . .Pp The .Fn setauevent function resets the database access session for .Xr audit_event 5 , so that the next call to .Fn getauevent will start with the first entry in the database. .Pp The .Fn endauevent function closes the .Xr audit_event 5 database session. .Pp The .Fn getauevent function returns a reference to the next entry in the .Xr audit_event 5 database. .Pp The .Fn getauevnam function returns a reference to the entry in the .Xr audit_event 5 database with a name of .Fa name . .Pp .Fn getauevnum returns a reference to the entry in the .Xr audit_event 5 database with an event number of .Fa event_number . .Pp The .Fn getauevnonam function returns a reference to an audit event number using the .Xr audit_event 5 database. .Sh RETURN VALUES Functions .Fn getauevent , .Fn getauevent_r , .Fn getauevnam , .Fn getauevnam_r , .Fn getauevnum , .Fn getauevnum_r , and .Fn getauevnonam will return a reference to a .Vt "struct au_event_ent" or .Vt au_event_t on success, or .Dv NULL on failure, with .Va errno set to provide further error information. .Sh SEE ALSO .Xr libbsm 3 , .Xr audit_event 5 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer, Inc., in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by .An Robert Watson , .An Wayne Salamon , and .An Suresh Krishnaswamy for McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer, Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. .Sh BUGS The .Va errno variable is not always properly set following a failure. .Pp These routines are thread-safe, but not re-entrant, so simultaneous or interleaved use of these functions will affect the iterator. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_fcntl_cmd.3 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_fcntl_cmd.3 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_fcntl_cmd.3 (revision 292449) @@ -1,97 +1,95 @@ .\"- .\" Copyright (c) 2009 Apple Inc. .\" 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR .\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_fcntl_cmd.3#2 $ -.\" .Dd March 5, 2009 .Dt AU_BSM_TO_FCNTL_CMD 3 .Os .Sh NAME .Nm au_bsm_to_fcntl_cmd , .Nm au_fcntl_cmd_to_bsm .Nd "convert between BSM and local fcntl(2) command values" .Sh LIBRARY .Lb libbsm .Sh SYNOPSIS .In bsm/libbsm.h .Ft int .Fn au_bsm_to_fcntl_cmd "u_short bsm_fcntl_cmd" "int *local_fcntl_cmdp" .Ft u_short .Fn au_fcntl_cmd_to_bsm "int local_fcntl_cmd" .Sh DESCRIPTION These interfaces may be used to convert between the local and BSM .Xr fcntl 2 command values. The .Fn au_bsm_to_fcntl_cmd function accepts a BSM command value, .Fa bsm_fcntl_cmd , and converts it to a local command value passed to .Xr fcntl 2 , that will be stored in the integer pointed to by .Fa local_fcntl_cmdp if successful. This call will fail if the BSM command value cannot be mapped into a local .Xr fcntl 2 command value which may occur if the command token was generated on another operating system. .Pp The .Fn au_fcntl_cmd_to_bsm function accepts a local .Xr fcntl 2 command value, and returns the BSM .Xr fcntl 2 command value for it. This call cannot fail, and instead returns a BSM command value indicating to a later decoder that the command value could not be encoded. .Sh RETURN VALUES On success, .Fn au_bsm_to_fcntl_cmd returns 0 and a converted command value; on failure, it returns -1 but does not set .Xr errno 2 . .Sh SEE ALSO .Xr fcntl 2 , .Xr au_bsm_to_domain 3 , -.Xr au_domain_to_bsm 3 , .Xr au_bsm_to_socket_type 3 , +.Xr au_domain_to_bsm 3 , .Xr au_socket_type_to_bsm 3 , .Xr libbsm 3 .Sh HISTORY .Fn au_bsm_to_domain and .Fn au_domain_to_bsm were introduced in OpenBSM 1.1. .Sh AUTHORS These functions were implemented by .An Stacey Son under contract to Apple Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_free_token.3 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_free_token.3 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_free_token.3 (revision 292449) @@ -1,97 +1,95 @@ .\"- .\" Copyright (c) 2004 Apple Inc. .\" Copyright (c) 2005 Robert N. M. Watson .\" 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR .\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, .\" STRING 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. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_free_token.3#7 $ -.\" .Dd April 19, 2005 .Dt AU_FREE_TOKEN 3 .Os .Sh NAME .Nm au_free_token .Nd "deallocate a token_t created by any of the au_to_*() BSM API functions" .Sh LIBRARY .Lb libbsm .Sh SYNOPSIS .In bsm/libbsm.h .Ft void .Fn au_free_token "token_t *tok" .Sh DESCRIPTION The BSM API generally manages deallocation of .Vt token_t objects. However, if .Xr au_write 3 is passed a bad audit descriptor, the .Vt "token_t *" parameter will be left untouched. In that case, the caller can deallocate the .Vt token_t using .Fn au_free_token if desired. .Pp The .Fa tok argument is a .Vt "token_t *" generated by one of the .Fn au_to_* BSM API calls. For convenience, .Fa tok may be .Dv NULL , in which case .Fn au_free_token returns immediately. .Sh IMPLEMENTATION NOTES This is, in fact, what .Xr audit_write 3 does, in keeping with the existing memory management model of the BSM API. .Sh SEE ALSO -.Xr audit_write 3 , .Xr au_write 3 , +.Xr audit_write 3 , .Xr libbsm 3 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer, Inc., in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by .An Robert Watson , .An Wayne Salamon , and .An Suresh Krishnaswamy for McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer, Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_io.3 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_io.3 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_io.3 (revision 292449) @@ -1,175 +1,173 @@ .\"- .\" Copyright (c) 2009 Apple, Inc. .\" Copyright (c) 2005 Robert N. M. Watson .\" 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_io.3#9 $ -.\" .Dd August 4, 2009 .Dt AU_IO 3 .Os .Sh NAME .Nm au_fetch_tok , .Nm au_print_tok , .Nm au_print_flags_tok , .Nm au_read_rec .Nd "perform I/O involving an audit record" .Sh LIBRARY .Lb libbsm .Sh SYNOPSIS .In bsm/libbsm.h .Ft int .Fn au_fetch_tok "tokenstr_t *tok" "u_char *buf" "int len" .Ft void .Fo au_print_tok .Fa "FILE *outfp" "tokenstr_t *tok" "char *del" "char raw" "char sfrm" .Fc .Ft void .Fo au_print_flags_tok .Fa "FILE *outfp" "tokenstr_t *tok" "char *del" "int oflags" .Fc .Ft int .Fn au_read_rec "FILE *fp" "u_char **buf" .Sh DESCRIPTION These interfaces support input and output (I/O) involving audit records, internalizing an audit record from a byte stream, converting a token to either a raw or default string, and reading a single record from a file. .Pp The .Fn au_fetch_tok function reads a token from the passed buffer .Fa buf of length .Fa len bytes, and returns a pointer to the token via .Fa tok . .Pp The .Fn au_print_tok function prints a string form of the token .Fa tok to the file output stream .Fa outfp , either in default mode, or raw mode if .Fa raw is set non-zero. The delimiter .Fa del is used when printing. The .Fn au_print_flags_tok function is a replacement for .Fn au_print_tok . The .Fa oflags controls how the output should be formatted and is specified by or'ing the following flags: .Pp .Bl -tag -width AU_OFLAG_NORESOLVE -compact -offset indent .It Li AU_OFLAG_NONE Use the default form. .It Li AU_OFLAG_NORESOLVE Leave user and group IDs in their numeric form. .It Li AU_OFLAG_RAW Use the raw, numeric form. .It Li AU_OFLAG_SHORT Use the short form. .It Li AU_OFLAG_XML Use the XML form. .El .Pp The flags options AU_OFLAG_SHORT and AU_OFLAG_RAW are exclusive and should not be used together. .Pp The .Fn au_read_rec function reads an audit record from the file stream .Fa fp , and returns an allocated memory buffer containing the record via .Fa *buf , which must be freed by the caller using .Xr free 3 . .Pp A typical use of these routines might open a file with .Xr fopen 3 , then read records from the file sequentially by calling .Fn au_read_rec . Each record would be broken down into components tokens through sequential calls to .Fn au_fetch_tok on the buffer, and then invoking .Fn au_print_flags_tok to print each token to an output stream such as .Dv stdout . On completion of the processing of each record, a call to .Xr free 3 would be used to free the record buffer. Finally, the source stream would be closed by a call to .Xr fclose 3 . .Sh RETURN VALUES The .Fn au_fetch_tok and .Fn au_read_rec functions return 0 on success, or \-1 on failure along with additional error information returned via .Va errno . .Sh SEE ALSO .Xr free 3 , .Xr libbsm 3 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer, Inc., in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Pp The .Fn au_print_flags_tok function was added by Stacey Son as a replacement for the .Fn au_print_tok so new output formatting flags can be easily added without changing the API. The .Fn au_print_tok is obsolete but remains in the API to support legacy code. .Sh AUTHORS .An -nosplit This software was created by .An Robert Watson , .An Wayne Salamon , and .An Suresh Krishnaswamy for McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer, Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. .Sh BUGS The .Va errno variable may not always be properly set in the event of an error. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_mask.3 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_mask.3 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_mask.3 (revision 292449) @@ -1,156 +1,154 @@ .\"- .\" Copyright (c) 2005 Robert N. M. Watson .\" 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_mask.3#6 $ -.\" .Dd April 19, 2005 .Dt AU_MASK 3 .Os .Sh NAME .Nm au_preselect , .Nm getauditflagsbin , .Nm getauditflagschar .Nd "convert between string and numeric values of audit masks" .Sh LIBRARY .Lb libbsm .Sh SYNOPSIS .In bsm/libbsm.h .Ft int .Fn au_preselect "au_event_t event" "au_mask_t *mask_p" "int sorf" "int flag" .Ft int .Fn getauditflagsbin "char *auditstr" "au_mask_t *masks" .Ft int .Fn getauditflagschar "char *auditstr" "au_mask_t *masks" "int verbose" .Sh DESCRIPTION These interfaces support processing of an audit mask represented by type .Vt au_mask_t , including conversion between numeric and text formats, and computing whether or not an event is matched by a mask. .Pp The .Fn au_preselect function calculates whether or not the audit event passed via .Fa event is matched by the audit mask passed via .Fa mask_p . The .Fa sorf argument indicates whether or not to consider the event as a success, if the .Dv AU_PRS_SUCCESS flag is set, or failure, if the .Dv AU_PRS_FAILURE flag is set. The .Fa flag argument accepts additional arguments influencing the behavior of .Fn au_preselect , including .Dv AU_PRS_REREAD , which causes the event to be re-looked up rather than read from the cache, or .Dv AU_PRS_USECACHE which forces use of the cache. .Pp The .Fn getauditflagsbin function converts a string representation of an audit mask passed via a character string pointed to by .Fa auditstr , returning the resulting mask, if valid, via .Fa *masks . .Pp The .Fn getauditflagschar function converts the audit event mask passed via .Fa *masks and converts it to a character string in a buffer pointed to by .Fa auditstr . See the .Sx BUGS section for more information on how to provide a buffer of sufficient size. If the .Fa verbose flag is set, the class description string retrieved from .Xr audit_class 5 will be used; otherwise, the two-character class name. .Sh IMPLEMENTATION NOTES The .Fn au_preselect function makes implicit use of various audit database routines, and may influence the behavior of simultaneous or interleaved processing of those databases by other code. .Sh RETURN VALUES The .Fn au_preselect function returns 0 on success, or returns \-1 if there is a failure looking up the event type or other database access, in which case .Va errno will be set to indicate the error. It returns 1 if the event is matched; 0 if not. .Pp .Rv -std getauditflagsbin getauditflagschar .Sh SEE ALSO .Xr libbsm 3 , .Xr audit_class 5 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer, Inc., in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by .An Robert Watson , .An Wayne Salamon , and .An Suresh Krishnaswamy for McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer, Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. .Sh BUGS The .Va errno variable may not always be properly set in the event of an error. .Pp The .Fn getauditflagschar function does not provide a way to indicate how long the character buffer is, in order to detect overflow. As a result, the caller must always provide a buffer of sufficient length for any possible mask, which may be calculated as three times the number of non-zero bits in the mask argument in the event non-verbose class names are used, and is not trivially predictable for verbose class names. This API should be replaced with a more robust one. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_notify.3 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_notify.3 (nonexistent) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_notify.3 (revision 292449) @@ -0,0 +1,118 @@ +.\"- +.\" Copyright (c) 2004-2009 Apple Inc. +.\" Copyright (c) 2015 Christian Brueffer +.\" 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 author 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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd July 29, 2015 +.Dt AU_NOTIFY 3 +.Os +.Sh NAME +.Nm au_get_state , +.Nm au_notify_initialize , +.Nm au_notify_terminate +.Nd "audit event notification" +.Sh LIBRARY +.Lb libbsm +.Sh SYNOPSIS +.In bsm/libbsm.h +.Ft int +.Fn au_get_state "void" +.Ft uint32_t +.Fn au_notify_initialize "void" +.Ft int +.Fn au_notify_terminate "void" +.Sh DESCRIPTION +The +.Nm au_notify +audit notification API tracks audit state in a form permitting efficient +update, avoiding frequent system calls to check the kernel audit state. +It is implemented only for Darwin/Mac OS X. +.Pp +The +.Fn au_get_state +function provides a lightweight way to check whether or not auditing is +enabled. +If a client wants to use this function to determine whether an entire +series of audit calls should be made -- as in the common case of a caller +building a set of tokens, then writing them -- it should cache the audit +status in a local variable. +This function always returns the current state of auditing. +If audit notification has not already been initialized by calling +.Fn au_notify_initialize +it will be automatically initialized on the first call of +this function. +.Pp +The +.Fn au_notify_initialize +function initializes audit notification. +.Pp +The +.Fn au_notify_terminate +function cancels audit notification and frees the resources associated with it. +Responsible code that no longer needs to use +.Fn au_get_state +should call this function. +.Sh RETURN VALUES +If no error occurred the +.Fn au_get_state +function returns +.Dv AUC_NOAUDIT +if auditing is disabled or suspended, and +.Dv AUC_AUDITING +if auditing is enabled and active. +Otherwise, the function can return any of the errno values defined for +.Xr setaudit 2 , +or +.Dv AU_UNIMPL +if audit does not appear to be supported by the system. +.Pp +The +.Fn au_notify_initialize +function returns 0 on success, +.Dv AU_UNIMPL +if audit does not appear to be supported by the system, +or one of the status codes defined in +.In notify.h +on Mac OS X to indicate the error. +.Pp +The +.Fn au_notify_terminate +function returns 0 on success, or \-1 on failure. +.Sh SEE ALSO +.Xr libbsm 3 , +.Xr notify 3 (Mac OS X) +.Sh HISTORY +The OpenBSM implementation was created by McAfee Research, the security +division of McAfee Inc., under contract to Apple Computer, Inc., in 2004. +It was subsequently adopted by the TrustedBSD Project as the foundation for +the OpenBSM distribution. +.Sh AUTHORS +This software was created by +.An Apple Computer, Inc . +.Pp +The Basic Security Module (BSM) interface to audit records and audit event +stream format were defined by Sun Microsystems. Property changes on: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_notify.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_open.3 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_open.3 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_open.3 (revision 292449) @@ -1,158 +1,156 @@ .\"- .\" Copyright (c) 2006 Robert N. M. Watson .\" 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_open.3#8 $ -.\" .Dd March 4, 2006 .Dt AU_OPEN 3 .Os .Sh NAME .Nm au_close , .Nm au_close_buffer , .Nm au_close_token , .Nm au_open , .Nm au_write .Nd "create and commit audit records" .Sh LIBRARY .Lb libbsm .Sh SYNOPSIS .In bsm/libbsm.h .Ft int .Fn au_open void .Ft int .Fn au_write "int d" "token_t *tok" .Ft int .Fn au_close "int d" "int keep" "short event" .Ft int .Fn au_close_buffer "int d" "short event" "u_char *buffer" "size_t *buflen" .Ft int .Fn au_close_token "token_t *tok" "u_char *buffer" "size_t *buflen" .Sh DESCRIPTION These interfaces allow applications to allocate audit records, construct a record using a series of tokens, and commit the audit record to the system event log. An extension API is also provided to commit the record to an in-memory buffer rather than the system audit log. .Pp The .Fn au_open interface allocates a new audit record descriptor. .Pp The .Fn au_write interface adds a token to an allocated audit descriptor. When a token has been successfully added to a record, the caller no longer owns the token memory, and does not need to free it directly via a call to .Xr au_free_token 3 . .Pp The .Fn au_close function is used to commit an audit record to the system audit log, or abandon the record. In either cases, all resources associated with the record will be released. The .Fa keep argument determines the behavior: a value of .Dv AU_TO_WRITE causes the record to be committed; a value of .Dv AU_TO_NO_WRITE causes it to be abandoned. When the audit record is committed, a BSM header will be inserted before tokens added to the record, using the event identifier passed via .Fa event , and a trailer added to the end. Committing a record to the system audit log requires privilege. .Pp The .Fn au_close_buffer function writes the resulting record to an in-memory buffer of size .Fa *buflen ; it will write back the filled buffer length into the same variable. The argument .Fa event is the event identifier to use in the record header. .Pp The .Fn au_close_token function generates the BSM stream output for a single token, .Fa tok , in the passed buffer .Fa buffer . The initial buffer size and resulting data size are passed via .Fa *buflen . The .Fn au_close_token function will free the token before returning. .Sh RETURN VALUES The function .Fn au_open returns a non-negative audit record descriptor number on success, or a negative value on failure, along with error information in .Va errno . .Pp The functions .Fn au_write , .Fn au_close , .Fn au_close_buffer , and .Fn au_close_token return 0 on success, or a negative value on failure, along with error information in .Va errno . .Sh SEE ALSO .Xr audit_submit 3 , .Xr libbsm 3 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer, Inc., in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by .An Robert Watson , .An Wayne Salamon , and .An Suresh Krishnaswamy for McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer, Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. .Sh BUGS Currently, .Fn au_open does not reserve kernel resources necessary to commit the record to the trail; on systems supporting .Fn au_close , the call will block until resources are available to commit the record. However, this leads to the possibility of an action being permitted without the record being guaranteed to go to disk. Ideally, .Fn au_open would reserve resources necessary to commit any submitted record, releasing them on .Fn au_close . Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_socket_type.3 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_socket_type.3 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_socket_type.3 (revision 292449) @@ -1,93 +1,91 @@ .\"- .\" Copyright (c) 2008 Apple Inc. .\" 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR .\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_socket_type.3#1 $ -.\" .Dd December 28, 2008 .Dt AU_BSM_TO_SOCKET_TYPE 3 .Os .Sh NAME .Nm au_bsm_to_socket_type , .Nm au_socket_type_to_bsm .Nd "convert between BSM and local socket types" .Sh LIBRARY .Lb libbsm .Sh SYNOPSIS .In bsm/libbsm.h .Ft int .Fn au_bsm_to_socket_type "u_short bsm_socket_type" "int *local_socket_typep" .Ft u_short .Fn au_socket_type_to_bsm "int local_socket_type" .Sh DESCRIPTION These interfaces may be used to convert between the local and BSM socket types. The .Fn au_bsm_to_socket_type function accepts a BSM socket type, .Fa bsm_socket_type , and converts it to a local socket type, such as those passed to .Xr socket 2 , that will be stored in the integer pointed to by .Fa local_socket_typep if successful. This call will fail if the BSM socket type cannot be mapped into a local socket type, which may occur if the socket token was generated on another operating system. .Pp .Fn au_socket_type_to_bsm function accepts a local socket type, and returns the BSM socket type for it. This call cannot fail, and instead returns a BSM socket type indicating to a later decoder that the socket type could not be encoded. .Sh RETURN VALULES On success, .Fn au_bsm_to_socket_type returns 0 and a converted socket type; on failure, it returns -1 but does not set .Xr errno 2 . .Pp On success, .Fn au_strerror returns a pointer to an error string; on failure it will return .Dv NULL . .Sh SEE ALSO .Xr au_bsm_to_domain 3 , .Xr au_domain_to_bsm 3 , .Xr au_to_socket_ex 3 , .Xr libbsm 3 .Sh HISTORY .Fn au_bsm_to_socket_type and .Fn au_socket_type_to_bsm were introduced in OpenBSM 1.1. .Sh AUTHORS These functions were implemented by .An Robert Watson under contract to Apple Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_token.3 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_token.3 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_token.3 (revision 292449) @@ -1,254 +1,252 @@ .\"- .\" Copyright (c) 2005-2007 Robert N. M. Watson .\" 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_token.3#17 $ -.\" .Dd April 19, 2005 .Dt AU_TOKEN 3 .Os .Sh NAME .Nm au_to_arg32 , .Nm au_to_arg64 , .Nm au_to_arg , .Nm au_to_attr64 , .Nm au_to_data , .Nm au_to_exit , .Nm au_to_groups , .Nm au_to_newgroups , .Nm au_to_in_addr , .Nm au_to_in_addr_ex , .Nm au_to_ip , .Nm au_to_ipc , .Nm au_to_ipc_perm , .Nm au_to_iport , .Nm au_to_opaque , .Nm au_to_file , .Nm au_to_text , .Nm au_to_path , .Nm au_to_process32 , .Nm au_to_process64 , .Nm au_to_process , .Nm au_to_process32_ex , .Nm au_to_process64_ex , .Nm au_to_process_ex , .Nm au_to_return32 , .Nm au_to_return64 , .Nm au_to_return , .Nm au_to_seq , .Nm au_to_sock_inet32 , .Nm au_to_sock_inet128 , .Nm au_to_sock_inet , .Nm au_to_socket_ex , .Nm au_to_subject32 , .Nm au_to_subject64 , .Nm au_to_subject , .Nm au_to_subject32_ex , .Nm au_to_subject64_ex , .Nm au_to_subject_ex , .Nm au_to_me , .Nm au_to_exec_args , .Nm au_to_exec_env , .Nm au_to_header , .Nm au_to_header32 , .Nm au_to_header64 , .Nm au_to_header_ex , .Nm au_to_header32_ex , .Nm au_to_trailer , .Nm au_to_zonename .Nd "routines for generating BSM audit tokens" .Sh LIBRARY .Lb libbsm .Sh SYNOPSIS .In bsm/libbsm.h .Ft "token_t *" .Fn au_to_arg32 "char n" "const char *text" "u_int32_t v" .Ft "token_t *" .Fn au_to_arg64 "char n" "const char *text" "u_int64_t v" .Ft "token_t *" .Fn au_to_arg "char n" "const char *text" "u_int32_t v" .Ft "token_t *" .Fn au_to_attr32 "struct vattr *attr" .Ft "token_t *" .Fn au_to_attr64 "struct vattr *attr" .Ft "token_t *" .Fn au_to_attr "struct vattr *attr" .Ft "token_t *" .Fn au_to_data "char unit_print" "char unit_type" "char unit_count" "const char *p" .Ft "token_t *" .Fn au_to_exit "int retval" "int err" .Ft "token_t *" .Fn au_to_groups "int *groups" .Ft "token_t *" .Fn au_to_newgroups "u_int16_t n" "gid_t *groups" .Ft "token_t *" .Fn au_to_in_addr "struct in_addr *internet_addr" .Ft "token_t *" .Fn au_to_in_addr_ex "struct in6_addr *internet_addr" .Ft "token_t *" .Fn au_to_ip "struct ip *ip" .Ft "token_t *" .Fn au_to_ipc "char type" "int id" .Ft "token_t *" .Fn au_to_ipc_perm "struct ipc_perm *perm" .Ft "token_t *" .Fn au_to_iport "u_int16_t iport" .Ft "token_t *" .Fn au_to_opaque "const char *data" "u_int16_t bytes" .Ft "token_t *" .Fn au_to_file "const char *file" "struct timeval tm" .Ft "token_t *" .Fn au_to_text "const char *text" .Ft "token_t *" .Fn au_to_path "const char *text" .Ft "token_t *" .Fo au_to_process32 .Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" .Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_t *tid" .Fc .Ft "token_t *" .Fo au_to_process64 .Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" .Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_t *tid" .Fc .Ft "token_t *" .Fo au_to_process32_ex .Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" .Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_addr_t *tid" .Fc .Ft "token_t *" .Fo au_to_process64_ex .Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" .Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_addr_t *tid" .Fc .Ft "token_t *" .Fn au_to_return32 "char status" "u_int32_t ret" .Ft "token_t *" .Fn au_to_return64 "char status" "u_int64_t ret" .Ft "token_t *" .Fn au_to_return "char status" "u_int32_t ret" .Ft "token_t *" .Fn au_to_seq "long audit_count" .Ft "token_t *" .Fn au_to_sock_inet32 "struct sockaddr_in *so" .Ft "token_t *" .Fn au_to_sock_inet128 "struct sockaddr_in6 *so" .Ft "token_t *" .Fn au_to_sock_int "struct sockaddr_in *so" .Ft "token_t *" .Fn au_to_socket_ex "u_short so_domain" "u_short so_type" "struct sockaddr *sa_local" "struct sockaddr *sa_remote" .Ft "token_t *" .Fo au_to_subject32 .Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" .Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_t *tid" .Fc .Ft "token_t *" .Fo au_to_subject64 .Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" .Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_t *tid" .Fc .Ft "token_t *" .Fo au_to_subject .Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" .Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_t *tid" .Fc .Ft "token_t *" .Fo au_to_subject32_ex .Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" .Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_addr_t *tid" .Fc .Ft "token_t *" .Fo au_to_subject64_ex .Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" .Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_addr_t *tid" .Fc .Ft "token_t *" .Fo au_to_subject_ex .Fa "au_id_t auid" "uid_t euid" "gid_t egid" "uid_t ruid" .Fa "gid_t rgid" "pid_t pid" "au_asid_t sid" "au_tid_addr_t *tid" .Fc .Ft "token_t *" .Fn au_to_me void .Ft "token_t *" .Fn au_to_exec_args "char **argv" .Ft "token_t *" .Fn au_to_exec_env "char **envp" .Ft "token_t *" .Fn au_to_header "int rec_size" "au_event_t e_type" "au_emod_t emod" .Ft "token_t *" .Fn au_to_header32 "int rec_size" "au_event_t e_type" "au_emod_t emod" .Ft "token_t *" .Fn au_to_header64 "int rec_size" "au_event_t e_type" "au_emod_t e_mod" .Ft "token_t *" .Fn au_to_header_ex "int rec_size" "au_event_t e_type" "au_emod_t e_mod" .Ft "token_t *" .Fn au_to_header32_ex "int rec_size" "au_event_t e_type" "au_emod_t e_mod" .Ft "token_t *" .Fn au_to_trailer "int rec_size" .Ft "token_t *" .Fn au_to_zonename "const char *zonename" .Sh DESCRIPTION These interfaces support the allocation of BSM audit tokens, represented by .Vt token_t , for various data types. .Pp .Xr au_errno_to_bsm 3 must be used to convert local .Xr errno 2 errors to BSM error numbers before they are passed to .Fn au_to_return , .Fn au_to_return32 , and .Fn au_to_return64 . .Sh RETURN VALUES On success, a pointer to a .Vt token_t will be returned; the allocated .Vt token_t can be freed via a call to .Xr au_free_token 3 . On failure, .Dv NULL will be returned, and an error condition returned via .Va errno . .Sh SEE ALSO .Xr au_errno_to_bsm 3 , .Xr libbsm 3 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer, Inc., in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by .An Robert Watson , .An Wayne Salamon , and .An Suresh Krishnaswamy for McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer, Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_user.3 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_user.3 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/au_user.3 (revision 292449) @@ -1,156 +1,154 @@ .\"- .\" Copyright (c) 2005-2006 Robert N. M. Watson .\" 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/au_user.3#10 $ -.\" .Dd April 19, 2005 .Dt AU_USER 3 .Os .Sh NAME .Nm setauuser , .Nm endauuser , .Nm getauuserent , .Nm getauuserent_r , .Nm getauusernam , .Nm getauusernam_r , .Nm au_user_mask , .Nm getfauditflags .Nd "look up information from the audit_user database" .Sh LIBRARY .Lb libbsm .Sh SYNOPSIS .In bsm/libbsm.h .Ft void .Fn setauuser void .Ft void .Fn endauuser void .Ft "struct au_user_ent *" .Fn getauuserent void .Ft "struct au_user_ent *" .Fn getauuserent_r "struct au_user_ent *u" .Ft "struct au_user_ent *" .Fn getauusernam "const char *name" .Ft "struct au_user_ent *" .Fn getauusernam_r "struct au_user_ent *u" "const char *name" .Ft int .Fn au_user_mask "char *username" "au_mask_t *mask_p" .Ft int .Fo getfauditflags .Fa "au_mask_t *usremask" "au_mask_t *usrdmask" "au_mask_t *lastmask" .Fc .Sh DESCRIPTION These interfaces may be used to look up information from the .Xr audit_user 5 database, which describes per-user audit configuration. Audit user entries are described by a .Vt au_user_ent , which stores the user's name in .Va au_name , events to always audit in .Va au_always , and events never to audit .Va au_never . .Pp The .Fn getauuserent function returns the next user found in the .Xr audit_user 5 database, or the first if the function has not yet been called. .Dv NULL will be returned if no further records are available. .Pp The .Fn getauusernam function looks up a user by name. .Dv NULL will be returned if no matching class can be found. .Pp The .Fn setauuser function resets the iterator through the .Xr audit_user 5 database, causing the next call to .Fn getauuserent to start again from the beginning of the file. .Pp The .Fn endauuser function closes the .Xr audit_user 5 database, if open. .Pp The .Fn au_user_mask function calculates a new session audit mask to be returned via .Fa mask_p for the user identified by .Fa username . If the user audit configuration is not found, the default system audit properties returned by .Xr getacflg 3 are used. The resulting mask may be set via a call to .Xr setaudit 2 or related variants. .Pp The .Fn getfauditflags function generates a new process audit state by combining the audit masks passed as parameters with the system audit masks. .Sh SEE ALSO .Xr setaudit 2 , .Xr getacflg 3 , .Xr libbsm 3 , .Xr audit_user 5 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer, Inc., in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by .An Robert Watson , .An Wayne Salamon , and .An Suresh Krishnaswamy for McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer, Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. .Sh BUGS These routines cannot currently distinguish between an entry not being found and an error accessing the database. The implementation should be changed to return an error via .Va errno when .Dv NULL is returned. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/audit_submit.3 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/audit_submit.3 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/audit_submit.3 (revision 292449) @@ -1,153 +1,151 @@ .\" .\" Copyright (c) 2006 Christian S.J. Peron .\" 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR .\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/audit_submit.3#19 $ -.\" .Dd January 18, 2008 .Dt AUDIT_SUBMIT 3 .Os .Sh NAME .Nm audit_submit .Nd "general purpose audit record submission" .Sh LIBRARY .Lb libbsm .Sh SYNOPSIS .In bsm/libbsm.h .Ft int .Fo audit_submit .Fa "short au_event" "au_id_t auid" "char status" .Fa "int reterr" "const char * restrict format" ... .Fc .Sh DESCRIPTION The .Fn audit_submit function provides a generic programming interface for audit record submission. This audit record will contain a header, subject token, an optional text token, return token, and a trailer. The header will contain the event class specified by .Fa au_event . The subject token will be generated based on .Fa auid . The return token is dependent on the .Fa status and .Fa reterr arguments; unlike the argument to .Xr au_to_return , .Fa reterr should be a local rather than BSM error number. Optionally, a text token will be created as a part of this record. .Pp Text token output is under the control of a .Fa format string that specifies how subsequent arguments (or arguments accessed via the variable-length argument facilities of .Xr stdarg 3 ) are converted for output. If .Fa format is .Dv NULL , then no text token is created in the audit record. .Pp It should be noted that .Fn audit_submit assumes that .Xr setaudit 2 , or .Xr setaudit_addr 2 has already been called. As a direct result, the terminal ID for the subject will be retrieved from the kernel via .Xr getaudit 2 , or .Xr getaudit_addr 2 . .Sh RETURN VALUES If successful, .Nm will return zero. Otherwise a -1 is returned and the global variable .Va errno is set to indicate the error. .Sh EXAMPLES .Bd -literal -offset indent #include #include #include #include #include #include void audit_bad_su(char *from_login, char *to_login) { struct auditinfo_addr aia; struct auditinfo ai; au_id_t aid; int error; error = getaudit_addr(&aia, sizeof(aia)); if (error < 0 && errno == ENOSYS) { error = getaudit(&ai); if (error < 0) err(1, "getaudit"); aid = ai.ai_auid; } else if (error < 0) err(1, "getaudit_addr"); else aid = aia.ai_auid; error = audit_submit(AUE_su, aid, EPERM, 1, "bad su from %s to %s", from_login, to_login); if (error != 0) err(1, "audit_submit"); } .Ed .Pp Will generate the following audit record: .Bd -literal -offset indent header,94,1,su(1),0,Mon Apr 17 23:23:59 2006, + 271 msec subject,root,root,wheel,root,wheel,652,652,0,0.0.0.0 text,bad su from from csjp to root return,failure : Operation not permitted,1 trailer,94 .Ed .Sh SEE ALSO .Xr auditon 2 , .Xr getaudit 2 , .Xr libbsm 3 , .Xr stdarg 3 .Sh HISTORY The .Fn audit_submit function first appeared in OpenBSM version 1.0. OpenBSM 1.0 was introduced in .Fx 7.0 . .Sh AUTHORS The .Fn audit_submit function was written by .An Christian S.J. Peron Aq csjp@FreeBSD.org . Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_audit.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_audit.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_audit.c (revision 292449) @@ -1,451 +1,449 @@ /*- * Copyright (c) 2004 Apple Inc. * Copyright (c) 2005 SPARTA, Inc. * All rights reserved. * * This code was developed in part by Robert N. M. Watson, Senior Principal * Scientist, SPARTA, Inc. * * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_audit.c#37 $ */ #include #include #ifdef HAVE_FULL_QUEUE_H #include #else #include #endif #include #include #include #include #ifdef HAVE_PTHREAD_MUTEX_LOCK #include #endif #include #include /* array of used descriptors */ static au_record_t *open_desc_table[MAX_AUDIT_RECORDS]; /* The current number of active record descriptors */ static int audit_rec_count = 0; /* * Records that can be recycled are maintained in the list given below. The * maximum number of elements that can be present in this list is bounded by * MAX_AUDIT_RECORDS. Memory allocated for these records are never freed. */ static LIST_HEAD(, au_record) audit_free_q; #ifdef HAVE_PTHREAD_MUTEX_LOCK static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; #endif /* * This call frees a token_t and its internal data. */ void au_free_token(token_t *tok) { if (tok != NULL) { if (tok->t_data) free(tok->t_data); free(tok); } } /* * This call reserves memory for the audit record. Memory must be guaranteed * before any auditable event can be generated. The au_record_t structure * maintains a reference to the memory allocated above and also the list of * tokens associated with this record. Descriptors are recyled once the * records are added to the audit trail following au_close(). */ int au_open(void) { au_record_t *rec = NULL; #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif if (audit_rec_count == 0) LIST_INIT(&audit_free_q); /* * Find an unused descriptor, remove it from the free list, mark as * used. */ if (!LIST_EMPTY(&audit_free_q)) { rec = LIST_FIRST(&audit_free_q); rec->used = 1; LIST_REMOVE(rec, au_rec_q); } #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif if (rec == NULL) { /* * Create a new au_record_t if no descriptors are available. */ rec = malloc (sizeof(au_record_t)); if (rec == NULL) return (-1); rec->data = malloc (MAX_AUDIT_RECORD_SIZE * sizeof(u_char)); if (rec->data == NULL) { free(rec); errno = ENOMEM; return (-1); } #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif if (audit_rec_count == MAX_AUDIT_RECORDS) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif free(rec->data); free(rec); /* XXX We need to increase size of MAX_AUDIT_RECORDS */ errno = ENOMEM; return (-1); } rec->desc = audit_rec_count; open_desc_table[audit_rec_count] = rec; audit_rec_count++; #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif } memset(rec->data, 0, MAX_AUDIT_RECORD_SIZE); TAILQ_INIT(&rec->token_q); rec->len = 0; rec->used = 1; return (rec->desc); } /* * Store the token with the record descriptor. * * Don't permit writing more to the buffer than would let the trailer be * appended later. */ int au_write(int d, token_t *tok) { au_record_t *rec; if (tok == NULL) { errno = EINVAL; return (-1); /* Invalid Token */ } /* Write the token to the record descriptor */ rec = open_desc_table[d]; if ((rec == NULL) || (rec->used == 0)) { errno = EINVAL; return (-1); /* Invalid descriptor */ } if (rec->len + tok->len + AUDIT_TRAILER_SIZE > MAX_AUDIT_RECORD_SIZE) { errno = ENOMEM; return (-1); } /* Add the token to the tail */ /* * XXX Not locking here -- we should not be writing to * XXX the same descriptor from different threads */ TAILQ_INSERT_TAIL(&rec->token_q, tok, tokens); rec->len += tok->len; /* grow record length by token size bytes */ /* Token should not be available after this call */ tok = NULL; return (0); /* Success */ } /* * Assemble an audit record out of its tokens, including allocating header and * trailer tokens. Does not free the token chain, which must be done by the * caller if desirable. * * XXX: Assumes there is sufficient space for the header and trailer. */ static int au_assemble(au_record_t *rec, short event) { #ifdef HAVE_AUDIT_SYSCALLS struct in6_addr *aptr; struct auditinfo_addr aia; struct timeval tm; size_t hdrsize; #endif /* HAVE_AUDIT_SYSCALLS */ token_t *header, *tok, *trailer; size_t tot_rec_size; u_char *dptr; int error; #ifdef HAVE_AUDIT_SYSCALLS /* * Grab the size of the address family stored in the kernel's audit * state. */ aia.ai_termid.at_type = AU_IPv4; aia.ai_termid.at_addr[0] = INADDR_ANY; if (audit_get_kaudit(&aia, sizeof(aia)) != 0) { if (errno != ENOSYS && errno != EPERM) return (-1); #endif /* HAVE_AUDIT_SYSCALLS */ tot_rec_size = rec->len + AUDIT_HEADER_SIZE + AUDIT_TRAILER_SIZE; header = au_to_header(tot_rec_size, event, 0); #ifdef HAVE_AUDIT_SYSCALLS } else { if (gettimeofday(&tm, NULL) < 0) return (-1); switch (aia.ai_termid.at_type) { case AU_IPv4: hdrsize = (aia.ai_termid.at_addr[0] == INADDR_ANY) ? AUDIT_HEADER_SIZE : AUDIT_HEADER_EX_SIZE(&aia); break; case AU_IPv6: aptr = (struct in6_addr *)&aia.ai_termid.at_addr[0]; hdrsize = (IN6_IS_ADDR_UNSPECIFIED(aptr)) ? AUDIT_HEADER_SIZE : AUDIT_HEADER_EX_SIZE(&aia); break; default: return (-1); } tot_rec_size = rec->len + hdrsize + AUDIT_TRAILER_SIZE; /* * A header size greater then AUDIT_HEADER_SIZE means * that we are using an extended header. */ if (hdrsize > AUDIT_HEADER_SIZE) header = au_to_header32_ex_tm(tot_rec_size, event, 0, tm, &aia); else header = au_to_header(tot_rec_size, event, 0); } #endif /* HAVE_AUDIT_SYSCALLS */ if (header == NULL) return (-1); trailer = au_to_trailer(tot_rec_size); if (trailer == NULL) { error = errno; au_free_token(header); errno = error; return (-1); } TAILQ_INSERT_HEAD(&rec->token_q, header, tokens); TAILQ_INSERT_TAIL(&rec->token_q, trailer, tokens); rec->len = tot_rec_size; dptr = rec->data; TAILQ_FOREACH(tok, &rec->token_q, tokens) { memcpy(dptr, tok->t_data, tok->len); dptr += tok->len; } return (0); } /* * Given a record that is no longer of interest, tear it down and convert to a * free record. */ static void au_teardown(au_record_t *rec) { token_t *tok; /* Free the token list */ while ((tok = TAILQ_FIRST(&rec->token_q)) != NULL) { TAILQ_REMOVE(&rec->token_q, tok, tokens); free(tok->t_data); free(tok); } rec->used = 0; rec->len = 0; #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif /* Add the record to the freelist tail */ LIST_INSERT_HEAD(&audit_free_q, rec, au_rec_q); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif } #ifdef HAVE_AUDIT_SYSCALLS /* * Add the header token, identify any missing tokens. Write out the tokens to * the record memory and finally, call audit. */ int au_close(int d, int keep, short event) { au_record_t *rec; size_t tot_rec_size; int retval = 0; rec = open_desc_table[d]; if ((rec == NULL) || (rec->used == 0)) { errno = EINVAL; return (-1); /* Invalid descriptor */ } if (keep == AU_TO_NO_WRITE) { retval = 0; goto cleanup; } tot_rec_size = rec->len + MAX_AUDIT_HEADER_SIZE + AUDIT_TRAILER_SIZE; if (tot_rec_size > MAX_AUDIT_RECORD_SIZE) { /* * XXXRW: Since au_write() is supposed to prevent this, spew * an error here. */ fprintf(stderr, "au_close failed"); errno = ENOMEM; retval = -1; goto cleanup; } if (au_assemble(rec, event) < 0) { /* * XXXRW: This is also not supposed to happen, but might if we * are unable to allocate header and trailer memory. */ retval = -1; goto cleanup; } /* Call the kernel interface to audit */ retval = audit(rec->data, rec->len); cleanup: /* CLEANUP */ au_teardown(rec); return (retval); } #endif /* HAVE_AUDIT_SYSCALLS */ /* * au_close(), except onto an in-memory buffer. Buffer size as an argument, * record size returned via same argument on success. */ int au_close_buffer(int d, short event, u_char *buffer, size_t *buflen) { size_t tot_rec_size; au_record_t *rec; int retval; rec = open_desc_table[d]; if ((rec == NULL) || (rec->used == 0)) { errno = EINVAL; return (-1); } retval = 0; tot_rec_size = rec->len + MAX_AUDIT_HEADER_SIZE + AUDIT_TRAILER_SIZE; if ((tot_rec_size > MAX_AUDIT_RECORD_SIZE) || (tot_rec_size > *buflen)) { /* * XXXRW: See au_close() comment. */ fprintf(stderr, "au_close_buffer failed %zd", tot_rec_size); errno = ENOMEM; retval = -1; goto cleanup; } if (au_assemble(rec, event) < 0) { /* XXXRW: See au_close() comment. */ retval = -1; goto cleanup; } memcpy(buffer, rec->data, rec->len); *buflen = rec->len; cleanup: au_teardown(rec); return (retval); } /* * au_close_token() returns the byte format of a token_t. This won't * generally be used by applications, but is quite useful for writing test * tools. Will free the token on either success or failure. */ int au_close_token(token_t *tok, u_char *buffer, size_t *buflen) { if (tok->len > *buflen) { au_free_token(tok); errno = ENOMEM; return (EINVAL); } memcpy(buffer, tok->t_data, tok->len); *buflen = tok->len; au_free_token(tok); return (0); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_class.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_class.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_class.c (revision 292449) @@ -1,302 +1,300 @@ /*- * Copyright (c) 2004 Apple Inc. * Copyright (c) 2006 Robert N. M. Watson * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_class.c#16 $ */ #include #include #include #ifdef HAVE_PTHREAD_MUTEX_LOCK #include #endif #include #include #ifndef HAVE_STRLCPY #include #endif /* * Parse the contents of the audit_class file to return struct au_class_ent * entries. */ static FILE *fp = NULL; static char linestr[AU_LINE_MAX]; static const char *classdelim = ":"; #ifdef HAVE_PTHREAD_MUTEX_LOCK static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; #endif /* * Parse a single line from the audit_class file passed in str to the struct * au_class_ent elements; store the result in c. */ static struct au_class_ent * classfromstr(char *str, struct au_class_ent *c) { char *classname, *classdesc, *classflag; char *last; /* Each line contains flag:name:desc. */ classflag = strtok_r(str, classdelim, &last); classname = strtok_r(NULL, classdelim, &last); classdesc = strtok_r(NULL, classdelim, &last); if ((classflag == NULL) || (classname == NULL) || (classdesc == NULL)) return (NULL); /* * Check for very large classnames. */ if (strlen(classname) >= AU_CLASS_NAME_MAX) return (NULL); strlcpy(c->ac_name, classname, AU_CLASS_NAME_MAX); /* * Check for very large class description. */ if (strlen(classdesc) >= AU_CLASS_DESC_MAX) return (NULL); strlcpy(c->ac_desc, classdesc, AU_CLASS_DESC_MAX); c->ac_class = strtoul(classflag, (char **) NULL, 0); return (c); } /* * Return the next au_class_ent structure from the file setauclass should be * called before invoking this function for the first time. * * Must be called with mutex held. */ static struct au_class_ent * getauclassent_r_locked(struct au_class_ent *c) { char *tokptr, *nl; if ((fp == NULL) && ((fp = fopen(AUDIT_CLASS_FILE, "r")) == NULL)) return (NULL); /* * Read until next non-comment line is found, or EOF. */ while (1) { if (fgets(linestr, AU_LINE_MAX, fp) == NULL) return (NULL); /* Skip comments. */ if (linestr[0] == '#') continue; /* Remove trailing new line character. */ if ((nl = strrchr(linestr, '\n')) != NULL) *nl = '\0'; /* Parse tokptr to au_class_ent components. */ tokptr = linestr; if (classfromstr(tokptr, c) == NULL) return (NULL); break; } return (c); } struct au_class_ent * getauclassent_r(struct au_class_ent *c) { struct au_class_ent *cp; #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif cp = getauclassent_r_locked(c); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (cp); } struct au_class_ent * getauclassent(void) { static char class_ent_name[AU_CLASS_NAME_MAX]; static char class_ent_desc[AU_CLASS_DESC_MAX]; static struct au_class_ent c, *cp; bzero(&c, sizeof(c)); bzero(class_ent_name, sizeof(class_ent_name)); bzero(class_ent_desc, sizeof(class_ent_desc)); c.ac_name = class_ent_name; c.ac_desc = class_ent_desc; #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif cp = getauclassent_r_locked(&c); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (cp); } /* * Rewind to the beginning of the enumeration. * * Must be called with mutex held. */ static void setauclass_locked(void) { if (fp != NULL) fseek(fp, 0, SEEK_SET); } void setauclass(void) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif setauclass_locked(); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif } /* * Return the next au_class_entry having the given class name. */ struct au_class_ent * getauclassnam_r(struct au_class_ent *c, const char *name) { struct au_class_ent *cp; if (name == NULL) return (NULL); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif setauclass_locked(); while ((cp = getauclassent_r_locked(c)) != NULL) { if (strcmp(name, cp->ac_name) == 0) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (cp); } } #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (NULL); } struct au_class_ent * getauclassnam(const char *name) { static char class_ent_name[AU_CLASS_NAME_MAX]; static char class_ent_desc[AU_CLASS_DESC_MAX]; static struct au_class_ent c; bzero(&c, sizeof(c)); bzero(class_ent_name, sizeof(class_ent_name)); bzero(class_ent_desc, sizeof(class_ent_desc)); c.ac_name = class_ent_name; c.ac_desc = class_ent_desc; return (getauclassnam_r(&c, name)); } /* * Return the next au_class_entry having the given class number. * * OpenBSM extension. */ struct au_class_ent * getauclassnum_r(struct au_class_ent *c, au_class_t class_number) { struct au_class_ent *cp; #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif setauclass_locked(); while ((cp = getauclassent_r_locked(c)) != NULL) { if (class_number == cp->ac_class) return (cp); } #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (NULL); } struct au_class_ent * getauclassnum(au_class_t class_number) { static char class_ent_name[AU_CLASS_NAME_MAX]; static char class_ent_desc[AU_CLASS_DESC_MAX]; static struct au_class_ent c; bzero(&c, sizeof(c)); bzero(class_ent_name, sizeof(class_ent_name)); bzero(class_ent_desc, sizeof(class_ent_desc)); c.ac_name = class_ent_name; c.ac_desc = class_ent_desc; return (getauclassnum_r(&c, class_number)); } /* * audit_class processing is complete; close any open files. */ void endauclass(void) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif if (fp != NULL) { fclose(fp); fp = NULL; } #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_control.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_control.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_control.c (revision 292449) @@ -1,710 +1,708 @@ /*- * Copyright (c) 2004, 2009 Apple Inc. * Copyright (c) 2006 Robert N. M. Watson * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_control.c#41 $ */ #include #include #include #include #include #include #ifdef HAVE_PTHREAD_MUTEX_LOCK #include #endif #include #include #ifndef HAVE_STRLCAT #include #endif #ifndef HAVE_STRLCPY #include #endif #include /* * Parse the contents of the audit_control file to return the audit control * parameters. These static fields are protected by 'mutex'. */ static FILE *fp = NULL; static char linestr[AU_LINE_MAX]; static char *delim = ":"; static char inacdir = 0; static char ptrmoved = 0; #ifdef HAVE_PTHREAD_MUTEX_LOCK static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; #endif /* * Audit policy string token table for au_poltostr() and au_strtopol(). */ struct audit_polstr { long ap_policy; const char *ap_str; }; static struct audit_polstr au_polstr[] = { { AUDIT_CNT, "cnt" }, { AUDIT_AHLT, "ahlt" }, { AUDIT_ARGV, "argv" }, { AUDIT_ARGE, "arge" }, { AUDIT_SEQ, "seq" }, { AUDIT_WINDATA, "windata" }, { AUDIT_USER, "user" }, { AUDIT_GROUP, "group" }, { AUDIT_TRAIL, "trail" }, { AUDIT_PATH, "path" }, { AUDIT_SCNT, "scnt" }, { AUDIT_PUBLIC, "public" }, { AUDIT_ZONENAME, "zonename" }, { AUDIT_PERZONE, "perzone" }, { -1, NULL } }; /* * Returns the string value corresponding to the given label from the * configuration file. * * Must be called with mutex held. */ static int getstrfromtype_locked(const char *name, char **str) { char *type, *nl; char *tokptr; char *last; *str = NULL; if ((fp == NULL) && ((fp = fopen(AUDIT_CONTROL_FILE, "r")) == NULL)) return (-1); /* Error */ while (1) { if (fgets(linestr, AU_LINE_MAX, fp) == NULL) { if (ferror(fp)) return (-1); return (0); /* EOF */ } if (linestr[0] == '#') continue; /* Remove trailing new line character and white space. */ nl = strchr(linestr, '\0') - 1; while (nl >= linestr && ('\n' == *nl || ' ' == *nl || '\t' == *nl)) { *nl = '\0'; nl--; } tokptr = linestr; if ((type = strtok_r(tokptr, delim, &last)) != NULL) { if (strcmp(name, type) == 0) { /* Found matching name. */ *str = strtok_r(NULL, delim, &last); if (*str == NULL) { errno = EINVAL; return (-1); /* Parse error in file */ } return (0); /* Success */ } } } } /* * Convert a given time value with a multiplier (seconds, hours, days, years) to * seconds. Return 0 on success. */ static int au_timetosec(time_t *seconds, u_long value, char mult) { if (NULL == seconds) return (-1); switch(mult) { case 's': /* seconds */ *seconds = (time_t)value; break; case 'h': /* hours */ *seconds = (time_t)value * 60 * 60; break; case 'd': /* days */ *seconds = (time_t)value * 60 * 60 * 24; break; case 'y': /* years. Add a day for each 4th (leap) year. */ *seconds = (time_t)value * 60 * 60 * 24 * 364 + ((time_t)value / 4) * 60 * 60 * 24; break; default: return (-1); } return (0); } /* * Convert a given disk space value with a multiplier (bytes, kilobytes, * megabytes, gigabytes) to bytes. Return 0 on success. */ static int au_spacetobytes(size_t *bytes, u_long value, char mult) { if (NULL == bytes) return (-1); switch(mult) { case 'B': case ' ': /* Bytes */ *bytes = (size_t)value; break; case 'K': /* Kilobytes */ *bytes = (size_t)value * 1024; break; case 'M': /* Megabytes */ *bytes = (size_t)value * 1024 * 1024; break; case 'G': /* Gigabytes */ *bytes = (size_t)value * 1024 * 1024 * 1024; break; default: return (-1); } return (0); } /* * Convert a policy to a string. Return -1 on failure, or >= 0 representing * the actual size of the string placed in the buffer (excluding terminating * nul). */ ssize_t au_poltostr(int policy, size_t maxsize, char *buf) { int first = 1; int i = 0; if (maxsize < 1) return (-1); buf[0] = '\0'; do { if (policy & au_polstr[i].ap_policy) { if (!first && strlcat(buf, ",", maxsize) >= maxsize) return (-1); if (strlcat(buf, au_polstr[i].ap_str, maxsize) >= maxsize) return (-1); first = 0; } } while (NULL != au_polstr[++i].ap_str); return (strlen(buf)); } /* * Convert a string to a policy. Return -1 on failure (with errno EINVAL, * ENOMEM) or 0 on success. */ int au_strtopol(const char *polstr, int *policy) { char *bufp, *string; char *buffer; int i, matched; *policy = 0; buffer = strdup(polstr); if (buffer == NULL) return (-1); bufp = buffer; while ((string = strsep(&bufp, ",")) != NULL) { matched = i = 0; do { if (strcmp(string, au_polstr[i].ap_str) == 0) { *policy |= au_polstr[i].ap_policy; matched = 1; break; } } while (NULL != au_polstr[++i].ap_str); if (!matched) { free(buffer); errno = EINVAL; return (-1); } } free(buffer); return (0); } /* * Rewind the file pointer to beginning. */ static void setac_locked(void) { static time_t lastctime = 0; struct stat sbuf; ptrmoved = 1; if (fp != NULL) { /* * Check to see if the file on disk has changed. If so, * force a re-read of the file by closing it. */ if (fstat(fileno(fp), &sbuf) < 0) goto closefp; if (lastctime != sbuf.st_ctime) { lastctime = sbuf.st_ctime; closefp: fclose(fp); fp = NULL; return; } fseek(fp, 0, SEEK_SET); } } void setac(void) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif setac_locked(); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif } /* * Close the audit_control file. */ void endac(void) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif ptrmoved = 1; if (fp != NULL) { fclose(fp); fp = NULL; } #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif } /* * Return audit directory information from the audit control file. */ int getacdir(char *name, int len) { char *dir; int ret = 0; /* * Check if another function was called between successive calls to * getacdir. */ #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif if (inacdir && ptrmoved) { ptrmoved = 0; if (fp != NULL) fseek(fp, 0, SEEK_SET); ret = 2; } if (getstrfromtype_locked(DIR_CONTROL_ENTRY, &dir) < 0) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-2); } if (dir == NULL) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-1); } if (strlen(dir) >= (size_t)len) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-3); } strlcpy(name, dir, len); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (ret); } /* * Return 1 if dist value is set to 'yes' or 'on'. * Return 0 if dist value is set to something else. * Return negative value on error. */ int getacdist(void) { char *str; int ret; #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif setac_locked(); if (getstrfromtype_locked(DIST_CONTROL_ENTRY, &str) < 0) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-2); } if (str == NULL) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (0); } if (strcasecmp(str, "on") == 0 || strcasecmp(str, "yes") == 0) ret = 1; else ret = 0; #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (ret); } /* * Return the minimum free diskspace value from the audit control file. */ int getacmin(int *min_val) { char *min; #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif setac_locked(); if (getstrfromtype_locked(MINFREE_CONTROL_ENTRY, &min) < 0) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-2); } if (min == NULL) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-1); } *min_val = atoi(min); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (0); } /* * Return the desired trail rotation size from the audit control file. */ int getacfilesz(size_t *filesz_val) { char *str; size_t val; char mult; int nparsed; #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif setac_locked(); if (getstrfromtype_locked(FILESZ_CONTROL_ENTRY, &str) < 0) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-2); } if (str == NULL) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif errno = EINVAL; return (-1); } /* Trim off any leading white space. */ while (*str == ' ' || *str == '\t') str++; nparsed = sscanf(str, "%ju%c", (uintmax_t *)&val, &mult); switch (nparsed) { case 1: /* If no multiplier then assume 'B' (bytes). */ mult = 'B'; /* fall through */ case 2: if (au_spacetobytes(filesz_val, val, mult) == 0) break; /* fall through */ default: errno = EINVAL; #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-1); } /* * The file size must either be 0 or >= MIN_AUDIT_FILE_SIZE. 0 * indicates no rotation size. */ if (*filesz_val < 0 || (*filesz_val > 0 && *filesz_val < MIN_AUDIT_FILE_SIZE)) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif filesz_val = 0L; errno = EINVAL; return (-1); } #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (0); } static int getaccommon(const char *name, char *auditstr, int len) { char *str; #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif setac_locked(); if (getstrfromtype_locked(name, &str) < 0) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-2); } if (str == NULL) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-1); } if (strlen(str) >= (size_t)len) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-3); } strlcpy(auditstr, str, len); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (0); } /* * Return the system audit value from the audit contol file. */ int getacflg(char *auditstr, int len) { return (getaccommon(FLAGS_CONTROL_ENTRY, auditstr, len)); } /* * Return the non attributable flags from the audit contol file. */ int getacna(char *auditstr, int len) { return (getaccommon(NA_CONTROL_ENTRY, auditstr, len)); } /* * Return the policy field from the audit control file. */ int getacpol(char *auditstr, size_t len) { return (getaccommon(POLICY_CONTROL_ENTRY, auditstr, len)); } int getachost(char *auditstr, size_t len) { return (getaccommon(HOST_CONTROL_ENTRY, auditstr, len)); } /* * Set expiration conditions. */ static int setexpirecond(time_t *age, size_t *size, u_long value, char mult) { if (isupper(mult) || ' ' == mult) return (au_spacetobytes(size, value, mult)); else return (au_timetosec(age, value, mult)); } /* * Return the expire-after field from the audit control file. */ int getacexpire(int *andflg, time_t *age, size_t *size) { char *str; int nparsed; u_long val1, val2; char mult1, mult2; char andor[AU_LINE_MAX]; *age = 0L; *size = 0LL; *andflg = 0; #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif setac_locked(); if (getstrfromtype_locked(EXPIRE_AFTER_CONTROL_ENTRY, &str) < 0) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-2); } if (str == NULL) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-1); } /* First, trim off any leading white space. */ while (*str == ' ' || *str == '\t') str++; nparsed = sscanf(str, "%lu%c%[ \tadnorADNOR]%lu%c", &val1, &mult1, andor, &val2, &mult2); switch (nparsed) { case 1: /* If no multiplier then assume 'B' (Bytes). */ mult1 = 'B'; /* fall through */ case 2: /* One expiration condition. */ if (setexpirecond(age, size, val1, mult1) != 0) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-1); } break; case 5: /* Two expiration conditions. */ if (setexpirecond(age, size, val1, mult1) != 0 || setexpirecond(age, size, val2, mult2) != 0) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-1); } if (strcasestr(andor, "and") != NULL) *andflg = 1; else if (strcasestr(andor, "or") != NULL) *andflg = 0; else { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-1); } break; default: #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-1); } #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (0); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_domain.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_domain.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_domain.c (revision 292449) @@ -1,492 +1,490 @@ /*- * Copyright (c) 2008 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_domain.c#3 $ */ #include #include #include #include #include struct bsm_domain { u_short bd_bsm_domain; int bd_local_domain; }; #define PF_NO_LOCAL_MAPPING -600 static const struct bsm_domain bsm_domains[] = { { BSM_PF_UNSPEC, PF_UNSPEC }, { BSM_PF_LOCAL, PF_LOCAL }, { BSM_PF_INET, PF_INET }, { BSM_PF_IMPLINK, #ifdef PF_IMPLINK PF_IMPLINK #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_PUP, #ifdef PF_PUP PF_PUP #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_CHAOS, #ifdef PF_CHAOS PF_CHAOS #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_NS, #ifdef PF_NS PF_NS #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_NBS, #ifdef PF_NBS PF_NBS #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_ECMA, #ifdef PF_ECMA PF_ECMA #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_DATAKIT, #ifdef PF_DATAKIT PF_DATAKIT #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_CCITT, #ifdef PF_CCITT PF_CCITT #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_SNA, PF_SNA }, { BSM_PF_DECnet, PF_DECnet }, { BSM_PF_DLI, #ifdef PF_DLI PF_DLI #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_LAT, #ifdef PF_LAT PF_LAT #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_HYLINK, #ifdef PF_HYLINK PF_HYLINK #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_APPLETALK, PF_APPLETALK }, { BSM_PF_NIT, #ifdef PF_NIT PF_NIT #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_802, #ifdef PF_802 PF_802 #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_OSI, #ifdef PF_OSI PF_OSI #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_X25, #ifdef PF_X25 PF_X25 #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_OSINET, #ifdef PF_OSINET PF_OSINET #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_GOSIP, #ifdef PF_GOSIP PF_GOSIP #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_IPX, PF_IPX }, { BSM_PF_ROUTE, PF_ROUTE }, { BSM_PF_LINK, #ifdef PF_LINK PF_LINK #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_INET6, PF_INET6 }, { BSM_PF_KEY, PF_KEY }, { BSM_PF_NCA, #ifdef PF_NCA PF_NCA #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_POLICY, #ifdef PF_POLICY PF_POLICY #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_INET_OFFLOAD, #ifdef PF_INET_OFFLOAD PF_INET_OFFLOAD #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_NETBIOS, #ifdef PF_NETBIOS PF_NETBIOS #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_ISO, #ifdef PF_ISO PF_ISO #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_XTP, #ifdef PF_XTP PF_XTP #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_COIP, #ifdef PF_COIP PF_COIP #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_CNT, #ifdef PF_CNT PF_CNT #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_RTIP, #ifdef PF_RTIP PF_RTIP #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_SIP, #ifdef PF_SIP PF_SIP #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_PIP, #ifdef PF_PIP PF_PIP #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_ISDN, #ifdef PF_ISDN PF_ISDN #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_E164, #ifdef PF_E164 PF_E164 #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_NATM, #ifdef PF_NATM PF_NATM #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_ATM, #ifdef PF_ATM PF_ATM #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_NETGRAPH, #ifdef PF_NETGRAPH PF_NETGRAPH #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_SLOW, #ifdef PF_SLOW PF_SLOW #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_SCLUSTER, #ifdef PF_SCLUSTER PF_SCLUSTER #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_ARP, #ifdef PF_ARP PF_ARP #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_BLUETOOTH, #ifdef PF_BLUETOOTH PF_BLUETOOTH #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_AX25, #ifdef PF_AX25 PF_AX25 #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_ROSE, #ifdef PF_ROSE PF_ROSE #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_NETBEUI, #ifdef PF_NETBEUI PF_NETBEUI #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_SECURITY, #ifdef PF_SECURITY PF_SECURITY #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_PACKET, #ifdef PF_PACKET PF_PACKET #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_ASH, #ifdef PF_ASH PF_ASH #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_ECONET, #ifdef PF_ECONET PF_ECONET #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_ATMSVC, #ifdef PF_ATMSVC PF_ATMSVC #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_IRDA, #ifdef PF_IRDA PF_IRDA #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_PPPOX, #ifdef PF_PPPOX PF_PPPOX #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_WANPIPE, #ifdef PF_WANPIPE PF_WANPIPE #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_LLC, #ifdef PF_LLC PF_LLC #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_CAN, #ifdef PF_CAN PF_CAN #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_TIPC, #ifdef PF_TIPC PF_TIPC #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_IUCV, #ifdef PF_IUCV PF_IUCV #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_RXRPC, #ifdef PF_RXRPC PF_RXRPC #else PF_NO_LOCAL_MAPPING #endif }, { BSM_PF_PHONET, #ifdef PF_PHONET PF_PHONET #else PF_NO_LOCAL_MAPPING #endif }, }; static const int bsm_domains_count = sizeof(bsm_domains) / sizeof(bsm_domains[0]); static const struct bsm_domain * bsm_lookup_local_domain(int local_domain) { int i; for (i = 0; i < bsm_domains_count; i++) { if (bsm_domains[i].bd_local_domain == local_domain) return (&bsm_domains[i]); } return (NULL); } u_short au_domain_to_bsm(int local_domain) { const struct bsm_domain *bstp; bstp = bsm_lookup_local_domain(local_domain); if (bstp == NULL) return (BSM_PF_UNKNOWN); return (bstp->bd_bsm_domain); } static const struct bsm_domain * bsm_lookup_bsm_domain(u_short bsm_domain) { int i; for (i = 0; i < bsm_domains_count; i++) { if (bsm_domains[i].bd_bsm_domain == bsm_domain) return (&bsm_domains[i]); } return (NULL); } int au_bsm_to_domain(u_short bsm_domain, int *local_domainp) { const struct bsm_domain *bstp; bstp = bsm_lookup_bsm_domain(bsm_domain); if (bstp == NULL || bstp->bd_local_domain) return (-1); *local_domainp = bstp->bd_local_domain; return (0); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_errno.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_errno.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_errno.c (revision 292449) @@ -1,773 +1,771 @@ /*- * Copyright (c) 2008 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_errno.c#22 $ */ #include #include #include #include #include #include /* * Different operating systems use different numeric constants for different * error numbers, and sometimes error numbers don't exist in more than one * operating system. These routines convert between BSM and local error * number spaces, subject to the above realities. BSM error numbers are * stored in a single 8-bit character, so don't have a byte order. * * Don't include string definitions when this code is compiled into a kernel. */ struct bsm_errno { int be_bsm_errno; int be_local_errno; #if !defined(KERNEL) && !defined(_KERNEL) const char *be_strerror; #endif }; #define ERRNO_NO_LOCAL_MAPPING -600 #if !defined(KERNEL) && !defined(_KERNEL) #define ES(x) x #else #define ES(x) #endif /* * Mapping table -- please maintain in numeric sorted order with respect to * the BSM constant. Today we do a linear lookup, but could switch to a * binary search if it makes sense. We only ifdef errors that aren't * generally available, but it does make the table a lot more ugly. * * XXXRW: It would be nice to have a similar ordered table mapping to BSM * constant from local constant, but the order of local constants varies by * OS. Really we need to build that table at compile-time but don't do that * yet. * * XXXRW: We currently embed English-language error strings here, but should * support catalogues; these are only used if the OS doesn't have an error * string using strerror(3). */ static const struct bsm_errno bsm_errnos[] = { { BSM_ERRNO_ESUCCESS, 0, ES("Success") }, { BSM_ERRNO_EPERM, EPERM, ES("Operation not permitted") }, { BSM_ERRNO_ENOENT, ENOENT, ES("No such file or directory") }, { BSM_ERRNO_ESRCH, ESRCH, ES("No such process") }, { BSM_ERRNO_EINTR, EINTR, ES("Interrupted system call") }, { BSM_ERRNO_EIO, EIO, ES("Input/output error") }, { BSM_ERRNO_ENXIO, ENXIO, ES("Device not configured") }, { BSM_ERRNO_E2BIG, E2BIG, ES("Argument list too long") }, { BSM_ERRNO_ENOEXEC, ENOEXEC, ES("Exec format error") }, { BSM_ERRNO_EBADF, EBADF, ES("Bad file descriptor") }, { BSM_ERRNO_ECHILD, ECHILD, ES("No child processes") }, { BSM_ERRNO_EAGAIN, EAGAIN, ES("Resource temporarily unavailable") }, { BSM_ERRNO_ENOMEM, ENOMEM, ES("Cannot allocate memory") }, { BSM_ERRNO_EACCES, EACCES, ES("Permission denied") }, { BSM_ERRNO_EFAULT, EFAULT, ES("Bad address") }, { BSM_ERRNO_ENOTBLK, ENOTBLK, ES("Block device required") }, { BSM_ERRNO_EBUSY, EBUSY, ES("Device busy") }, { BSM_ERRNO_EEXIST, EEXIST, ES("File exists") }, { BSM_ERRNO_EXDEV, EXDEV, ES("Cross-device link") }, { BSM_ERRNO_ENODEV, ENODEV, ES("Operation not supported by device") }, { BSM_ERRNO_ENOTDIR, ENOTDIR, ES("Not a directory") }, { BSM_ERRNO_EISDIR, EISDIR, ES("Is a directory") }, { BSM_ERRNO_EINVAL, EINVAL, ES("Invalid argument") }, { BSM_ERRNO_ENFILE, ENFILE, ES("Too many open files in system") }, { BSM_ERRNO_EMFILE, EMFILE, ES("Too many open files") }, { BSM_ERRNO_ENOTTY, ENOTTY, ES("Inappropriate ioctl for device") }, { BSM_ERRNO_ETXTBSY, ETXTBSY, ES("Text file busy") }, { BSM_ERRNO_EFBIG, EFBIG, ES("File too large") }, { BSM_ERRNO_ENOSPC, ENOSPC, ES("No space left on device") }, { BSM_ERRNO_ESPIPE, ESPIPE, ES("Illegal seek") }, { BSM_ERRNO_EROFS, EROFS, ES("Read-only file system") }, { BSM_ERRNO_EMLINK, EMLINK, ES("Too many links") }, { BSM_ERRNO_EPIPE, EPIPE, ES("Broken pipe") }, { BSM_ERRNO_EDOM, EDOM, ES("Numerical argument out of domain") }, { BSM_ERRNO_ERANGE, ERANGE, ES("Result too large") }, { BSM_ERRNO_ENOMSG, ENOMSG, ES("No message of desired type") }, { BSM_ERRNO_EIDRM, EIDRM, ES("Identifier removed") }, { BSM_ERRNO_ECHRNG, #ifdef ECHRNG ECHRNG, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Channel number out of range") }, { BSM_ERRNO_EL2NSYNC, #ifdef EL2NSYNC EL2NSYNC, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Level 2 not synchronized") }, { BSM_ERRNO_EL3HLT, #ifdef EL3HLT EL3HLT, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Level 3 halted") }, { BSM_ERRNO_EL3RST, #ifdef EL3RST EL3RST, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Level 3 reset") }, { BSM_ERRNO_ELNRNG, #ifdef ELNRNG ELNRNG, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Link number out of range") }, { BSM_ERRNO_EUNATCH, #ifdef EUNATCH EUNATCH, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Protocol driver not attached") }, { BSM_ERRNO_ENOCSI, #ifdef ENOCSI ENOCSI, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("No CSI structure available") }, { BSM_ERRNO_EL2HLT, #ifdef EL2HLT EL2HLT, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Level 2 halted") }, { BSM_ERRNO_EDEADLK, EDEADLK, ES("Resource deadlock avoided") }, { BSM_ERRNO_ENOLCK, ENOLCK, ES("No locks available") }, { BSM_ERRNO_ECANCELED, ECANCELED, ES("Operation canceled") }, { BSM_ERRNO_ENOTSUP, ENOTSUP, ES("Operation not supported") }, { BSM_ERRNO_EDQUOT, EDQUOT, ES("Disc quota exceeded") }, { BSM_ERRNO_EBADE, #ifdef EBADE EBADE, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Invalid exchange") }, { BSM_ERRNO_EBADR, #ifdef EBADR EBADR, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Invalid request descriptor") }, { BSM_ERRNO_EXFULL, #ifdef EXFULL EXFULL, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Exchange full") }, { BSM_ERRNO_ENOANO, #ifdef ENOANO ENOANO, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("No anode") }, { BSM_ERRNO_EBADRQC, #ifdef EBADRQC EBADRQC, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Invalid request descriptor") }, { BSM_ERRNO_EBADSLT, #ifdef EBADSLT EBADSLT, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Invalid slot") }, { BSM_ERRNO_EDEADLOCK, #ifdef EDEADLOCK EDEADLOCK, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Resource deadlock avoided") }, { BSM_ERRNO_EBFONT, #ifdef EBFONT EBFONT, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Bad font file format") }, { BSM_ERRNO_EOWNERDEAD, #ifdef EOWNERDEAD EOWNERDEAD, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Process died with the lock") }, { BSM_ERRNO_ENOTRECOVERABLE, #ifdef ENOTRECOVERABLE ENOTRECOVERABLE, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Lock is not recoverable") }, { BSM_ERRNO_ENOSTR, #ifdef ENOSTR ENOSTR, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Device not a stream") }, { BSM_ERRNO_ENONET, #ifdef ENONET ENONET, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Machine is not on the network") }, { BSM_ERRNO_ENOPKG, #ifdef ENOPKG ENOPKG, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Package not installed") }, { BSM_ERRNO_EREMOTE, EREMOTE, ES("Too many levels of remote in path") }, { BSM_ERRNO_ENOLINK, #ifdef ENOLINK ENOLINK, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Link has been severed") }, { BSM_ERRNO_EADV, #ifdef EADV EADV, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Advertise error") }, { BSM_ERRNO_ESRMNT, #ifdef ESRMNT ESRMNT, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("srmount error") }, { BSM_ERRNO_ECOMM, #ifdef ECOMM ECOMM, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Communication error on send") }, { BSM_ERRNO_EPROTO, #ifdef EPROTO EPROTO, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Protocol error") }, { BSM_ERRNO_ELOCKUNMAPPED, #ifdef ELOCKUNMAPPED ELOCKUNMAPPED, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Locked lock was unmapped") }, { BSM_ERRNO_ENOTACTIVE, #ifdef ENOTACTIVE ENOTACTIVE, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Facility is not active") }, { BSM_ERRNO_EMULTIHOP, #ifdef EMULTIHOP EMULTIHOP, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Multihop attempted") }, { BSM_ERRNO_EBADMSG, #ifdef EBADMSG EBADMSG, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Bad message") }, { BSM_ERRNO_ENAMETOOLONG, ENAMETOOLONG, ES("File name too long") }, { BSM_ERRNO_EOVERFLOW, EOVERFLOW, ES("Value too large to be stored in data type") }, { BSM_ERRNO_ENOTUNIQ, #ifdef ENOTUNIQ ENOTUNIQ, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Given log name not unique") }, { BSM_ERRNO_EBADFD, #ifdef EBADFD EBADFD, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Given f.d. invalid for this operation") }, { BSM_ERRNO_EREMCHG, #ifdef EREMCHG EREMCHG, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Remote address changed") }, { BSM_ERRNO_ELIBACC, #ifdef ELIBACC ELIBACC, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Can't access a needed shared lib") }, { BSM_ERRNO_ELIBBAD, #ifdef ELIBBAD ELIBBAD, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Accessing a corrupted shared lib") }, { BSM_ERRNO_ELIBSCN, #ifdef ELIBSCN ELIBSCN, #else ERRNO_NO_LOCAL_MAPPING, #endif ES(".lib section in a.out corrupted") }, { BSM_ERRNO_ELIBMAX, #ifdef ELIBMAX ELIBMAX, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Attempting to link in too many libs") }, { BSM_ERRNO_ELIBEXEC, #ifdef ELIBEXEC ELIBEXEC, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Attempting to exec a shared library") }, { BSM_ERRNO_EILSEQ, EILSEQ, ES("Illegal byte sequence") }, { BSM_ERRNO_ENOSYS, ENOSYS, ES("Function not implemented") }, { BSM_ERRNO_ELOOP, ELOOP, ES("Too many levels of symbolic links") }, { BSM_ERRNO_ERESTART, #ifdef ERESTART ERESTART, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Restart syscall") }, { BSM_ERRNO_ESTRPIPE, #ifdef ESTRPIPE ESTRPIPE, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("If pipe/FIFO, don't sleep in stream head") }, { BSM_ERRNO_ENOTEMPTY, ENOTEMPTY, ES("Directory not empty") }, { BSM_ERRNO_EUSERS, EUSERS, ES("Too many users") }, { BSM_ERRNO_ENOTSOCK, ENOTSOCK, ES("Socket operation on non-socket") }, { BSM_ERRNO_EDESTADDRREQ, EDESTADDRREQ, ES("Destination address required") }, { BSM_ERRNO_EMSGSIZE, EMSGSIZE, ES("Message too long") }, { BSM_ERRNO_EPROTOTYPE, EPROTOTYPE, ES("Protocol wrong type for socket") }, { BSM_ERRNO_ENOPROTOOPT, ENOPROTOOPT, ES("Protocol not available") }, { BSM_ERRNO_EPROTONOSUPPORT, EPROTONOSUPPORT, ES("Protocol not supported") }, { BSM_ERRNO_ESOCKTNOSUPPORT, ESOCKTNOSUPPORT, ES("Socket type not supported") }, { BSM_ERRNO_EOPNOTSUPP, EOPNOTSUPP, ES("Operation not supported") }, { BSM_ERRNO_EPFNOSUPPORT, EPFNOSUPPORT, ES("Protocol family not supported") }, { BSM_ERRNO_EAFNOSUPPORT, EAFNOSUPPORT, ES("Address family not supported by protocol family") }, { BSM_ERRNO_EADDRINUSE, EADDRINUSE, ES("Address already in use") }, { BSM_ERRNO_EADDRNOTAVAIL, EADDRNOTAVAIL, ES("Can't assign requested address") }, { BSM_ERRNO_ENETDOWN, ENETDOWN, ES("Network is down") }, { BSM_ERRNO_ENETRESET, ENETRESET, ES("Network dropped connection on reset") }, { BSM_ERRNO_ECONNABORTED, ECONNABORTED, ES("Software caused connection abort") }, { BSM_ERRNO_ECONNRESET, ECONNRESET, ES("Connection reset by peer") }, { BSM_ERRNO_ENOBUFS, ENOBUFS, ES("No buffer space available") }, { BSM_ERRNO_EISCONN, EISCONN, ES("Socket is already connected") }, { BSM_ERRNO_ENOTCONN, ENOTCONN, ES("Socket is not connected") }, { BSM_ERRNO_ESHUTDOWN, ESHUTDOWN, ES("Can't send after socket shutdown") }, { BSM_ERRNO_ETOOMANYREFS, ETOOMANYREFS, ES("Too many references: can't splice") }, { BSM_ERRNO_ETIMEDOUT, ETIMEDOUT, ES("Operation timed out") }, { BSM_ERRNO_ECONNREFUSED, ECONNREFUSED, ES("Connection refused") }, { BSM_ERRNO_EHOSTDOWN, EHOSTDOWN, ES("Host is down") }, { BSM_ERRNO_EHOSTUNREACH, EHOSTUNREACH, ES("No route to host") }, { BSM_ERRNO_EALREADY, EALREADY, ES("Operation already in progress") }, { BSM_ERRNO_EINPROGRESS, EINPROGRESS, ES("Operation now in progress") }, { BSM_ERRNO_ESTALE, ESTALE, ES("Stale NFS file handle") }, { BSM_ERRNO_EPROCLIM, #ifdef EPROCLIM EPROCLIM, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Too many processes") }, { BSM_ERRNO_EBADRPC, #ifdef EBADRPC EBADRPC, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("RPC struct is bad") }, { BSM_ERRNO_ERPCMISMATCH, #ifdef ERPCMISMATCH ERPCMISMATCH, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("RPC version wrong") }, { BSM_ERRNO_EPROGUNAVAIL, #ifdef EPROGUNAVAIL EPROGUNAVAIL, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("RPC prog. not avail") }, { BSM_ERRNO_EPROGMISMATCH, #ifdef EPROGMISMATCH EPROGMISMATCH, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("RPC version wrong") }, { BSM_ERRNO_EPROCUNAVAIL, #ifdef EPROCUNAVAIL EPROCUNAVAIL, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Bad procedure for program") }, { BSM_ERRNO_EFTYPE, #ifdef EFTYPE EFTYPE, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Inappropriate file type or format") }, { BSM_ERRNO_EAUTH, #ifdef EAUTH EAUTH, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Authenticateion error") }, { BSM_ERRNO_ENEEDAUTH, #ifdef ENEEDAUTH ENEEDAUTH, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Need authenticator") }, { BSM_ERRNO_ENOATTR, #ifdef ENOATTR ENOATTR, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Attribute not found") }, { BSM_ERRNO_EDOOFUS, #ifdef EDOOFUS EDOOFUS, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Programming error") }, { BSM_ERRNO_EJUSTRETURN, #ifdef EJUSTRETURN EJUSTRETURN, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Just return") }, { BSM_ERRNO_ENOIOCTL, #ifdef ENOIOCTL ENOIOCTL, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("ioctl not handled by this layer") }, { BSM_ERRNO_EDIRIOCTL, #ifdef EDIRIOCTL EDIRIOCTL, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("do direct ioctl in GEOM") }, { BSM_ERRNO_EPWROFF, #ifdef EPWROFF EPWROFF, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Device power is off") }, { BSM_ERRNO_EDEVERR, #ifdef EDEVERR EDEVERR, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Device error") }, { BSM_ERRNO_EBADEXEC, #ifdef EBADEXEC EBADEXEC, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Bad executable") }, { BSM_ERRNO_EBADARCH, #ifdef EBADARCH EBADARCH, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Bad CPU type in executable") }, { BSM_ERRNO_ESHLIBVERS, #ifdef ESHLIBVERS ESHLIBVERS, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Shared library version mismatch") }, { BSM_ERRNO_EBADMACHO, #ifdef EBADMACHO EBADMACHO, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Malformed Macho file") }, { BSM_ERRNO_EPOLICY, #ifdef EPOLICY EPOLICY, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Operation failed by policy") }, { BSM_ERRNO_EDOTDOT, #ifdef EDOTDOT EDOTDOT, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("RFS specific error") }, { BSM_ERRNO_EUCLEAN, #ifdef EUCLEAN EUCLEAN, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Structure needs cleaning") }, { BSM_ERRNO_ENOTNAM, #ifdef ENOTNAM ENOTNAM, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Not a XENIX named type file") }, { BSM_ERRNO_ENAVAIL, #ifdef ENAVAIL ENAVAIL, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("No XENIX semaphores available") }, { BSM_ERRNO_EISNAM, #ifdef EISNAM EISNAM, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Is a named type file") }, { BSM_ERRNO_EREMOTEIO, #ifdef EREMOTEIO EREMOTEIO, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Remote I/O error") }, { BSM_ERRNO_ENOMEDIUM, #ifdef ENOMEDIUM ENOMEDIUM, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("No medium found") }, { BSM_ERRNO_EMEDIUMTYPE, #ifdef EMEDIUMTYPE EMEDIUMTYPE, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Wrong medium type") }, { BSM_ERRNO_ENOKEY, #ifdef ENOKEY ENOKEY, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Required key not available") }, { BSM_ERRNO_EKEYEXPIRED, #ifdef EKEYEXPIRED EKEYEXPIRED, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Key has expired") }, { BSM_ERRNO_EKEYREVOKED, #ifdef EKEYREVOKED EKEYREVOKED, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Key has been revoked") }, { BSM_ERRNO_EKEYREJECTED, #ifdef EKEYREJECTED EKEYREJECTED, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Key was rejected by service") }, { BSM_ERRNO_ENOTCAPABLE, #ifdef ENOTCAPABLE ENOTCAPABLE, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Capabilities insufficient") }, { BSM_ERRNO_ECAPMODE, #ifdef ECAPMODE ECAPMODE, #else ERRNO_NO_LOCAL_MAPPING, #endif ES("Not permitted in capability mode") }, }; static const int bsm_errnos_count = sizeof(bsm_errnos) / sizeof(bsm_errnos[0]); static const struct bsm_errno * bsm_lookup_errno_local(int local_errno) { int i; for (i = 0; i < bsm_errnos_count; i++) { if (bsm_errnos[i].be_local_errno == local_errno) return (&bsm_errnos[i]); } return (NULL); } /* * Conversion to the BSM errno space isn't allowed to fail; we simply map to * BSM_ERRNO_UNKNOWN and let the remote endpoint deal with it. */ u_char au_errno_to_bsm(int local_errno) { const struct bsm_errno *bsme; bsme = bsm_lookup_errno_local(local_errno); if (bsme == NULL) return (BSM_ERRNO_UNKNOWN); return (bsme->be_bsm_errno); } static const struct bsm_errno * bsm_lookup_errno_bsm(u_char bsm_errno) { int i; for (i = 0; i < bsm_errnos_count; i++) { if (bsm_errnos[i].be_bsm_errno == bsm_errno) return (&bsm_errnos[i]); } return (NULL); } /* * Converstion from a BSM error to a local error number may fail if either * OpenBSM doesn't recognize the error on the wire, or because there is no * appropriate local mapping. */ int au_bsm_to_errno(u_char bsm_errno, int *errorp) { const struct bsm_errno *bsme; bsme = bsm_lookup_errno_bsm(bsm_errno); if (bsme == NULL || bsme->be_local_errno == ERRNO_NO_LOCAL_MAPPING) return (-1); *errorp = bsme->be_local_errno; return (0); } #if !defined(KERNEL) && !defined(_KERNEL) const char * au_strerror(u_char bsm_errno) { const struct bsm_errno *bsme; bsme = bsm_lookup_errno_bsm(bsm_errno); if (bsme == NULL) return ("Unrecognized BSM error"); if (bsme->be_local_errno != ERRNO_NO_LOCAL_MAPPING) return (strerror(bsme->be_local_errno)); return (bsme->be_strerror); } #endif Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_event.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_event.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_event.c (revision 292449) @@ -1,363 +1,361 @@ /*- * Copyright (c) 2004 Apple Inc. * Copyright (c) 2006 Robert N. M. Watson * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_event.c#17 $ */ #include #include #include #ifdef HAVE_PTHREAD_MUTEX_LOCK #include #endif #include #include #ifndef HAVE_STRLCPY #include #endif /* * Parse the contents of the audit_event file to return * au_event_ent entries */ static FILE *fp = NULL; static char linestr[AU_LINE_MAX]; static const char *eventdelim = ":"; #ifdef HAVE_PTHREAD_MUTEX_LOCK static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; #endif /* * Parse one line from the audit_event file into the au_event_ent structure. */ static struct au_event_ent * eventfromstr(char *str, struct au_event_ent *e) { char *evno, *evname, *evdesc, *evclass; struct au_mask evmask; char *last; evno = strtok_r(str, eventdelim, &last); evname = strtok_r(NULL, eventdelim, &last); evdesc = strtok_r(NULL, eventdelim, &last); evclass = strtok_r(NULL, eventdelim, &last); if ((evno == NULL) || (evname == NULL)) return (NULL); if (strlen(evname) >= AU_EVENT_NAME_MAX) return (NULL); strlcpy(e->ae_name, evname, AU_EVENT_NAME_MAX); if (evdesc != NULL) { if (strlen(evdesc) >= AU_EVENT_DESC_MAX) return (NULL); strlcpy(e->ae_desc, evdesc, AU_EVENT_DESC_MAX); } else strlcpy(e->ae_desc, "", AU_EVENT_DESC_MAX); e->ae_number = atoi(evno); /* * Find out the mask that corresponds to the given list of classes. */ if (evclass != NULL) { if (getauditflagsbin(evclass, &evmask) != 0) e->ae_class = 0; else e->ae_class = evmask.am_success; } else e->ae_class = 0; return (e); } /* * Rewind the audit_event file. */ static void setauevent_locked(void) { if (fp != NULL) fseek(fp, 0, SEEK_SET); } void setauevent(void) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif setauevent_locked(); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif } /* * Close the open file pointers. */ void endauevent(void) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif if (fp != NULL) { fclose(fp); fp = NULL; } #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif } /* * Enumerate the au_event_ent entries. */ static struct au_event_ent * getauevent_r_locked(struct au_event_ent *e) { char *nl; if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL)) return (NULL); while (1) { if (fgets(linestr, AU_LINE_MAX, fp) == NULL) return (NULL); /* Remove new lines. */ if ((nl = strrchr(linestr, '\n')) != NULL) *nl = '\0'; /* Skip comments. */ if (linestr[0] == '#') continue; /* Get the next event structure. */ if (eventfromstr(linestr, e) == NULL) return (NULL); break; } return (e); } struct au_event_ent * getauevent_r(struct au_event_ent *e) { struct au_event_ent *ep; #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif ep = getauevent_r_locked(e); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (ep); } struct au_event_ent * getauevent(void) { static char event_ent_name[AU_EVENT_NAME_MAX]; static char event_ent_desc[AU_EVENT_DESC_MAX]; static struct au_event_ent e; bzero(&e, sizeof(e)); bzero(event_ent_name, sizeof(event_ent_name)); bzero(event_ent_desc, sizeof(event_ent_desc)); e.ae_name = event_ent_name; e.ae_desc = event_ent_desc; return (getauevent_r(&e)); } /* * Search for an audit event structure having the given event name. * * XXXRW: Why accept NULL name? */ static struct au_event_ent * getauevnam_r_locked(struct au_event_ent *e, const char *name) { char *nl; if (name == NULL) return (NULL); /* Rewind to beginning of the file. */ setauevent_locked(); if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL)) return (NULL); while (fgets(linestr, AU_LINE_MAX, fp) != NULL) { /* Remove new lines. */ if ((nl = strrchr(linestr, '\n')) != NULL) *nl = '\0'; if (eventfromstr(linestr, e) != NULL) { if (strcmp(name, e->ae_name) == 0) return (e); } } return (NULL); } struct au_event_ent * getauevnam_r(struct au_event_ent *e, const char *name) { struct au_event_ent *ep; #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif ep = getauevnam_r_locked(e, name); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (ep); } struct au_event_ent * getauevnam(const char *name) { static char event_ent_name[AU_EVENT_NAME_MAX]; static char event_ent_desc[AU_EVENT_DESC_MAX]; static struct au_event_ent e; bzero(&e, sizeof(e)); bzero(event_ent_name, sizeof(event_ent_name)); bzero(event_ent_desc, sizeof(event_ent_desc)); e.ae_name = event_ent_name; e.ae_desc = event_ent_desc; return (getauevnam_r(&e, name)); } /* * Search for an audit event structure having the given event number. */ static struct au_event_ent * getauevnum_r_locked(struct au_event_ent *e, au_event_t event_number) { char *nl; /* Rewind to beginning of the file. */ setauevent_locked(); if ((fp == NULL) && ((fp = fopen(AUDIT_EVENT_FILE, "r")) == NULL)) return (NULL); while (fgets(linestr, AU_LINE_MAX, fp) != NULL) { /* Remove new lines. */ if ((nl = strrchr(linestr, '\n')) != NULL) *nl = '\0'; if (eventfromstr(linestr, e) != NULL) { if (event_number == e->ae_number) return (e); } } return (NULL); } struct au_event_ent * getauevnum_r(struct au_event_ent *e, au_event_t event_number) { struct au_event_ent *ep; #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif ep = getauevnum_r_locked(e, event_number); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (ep); } struct au_event_ent * getauevnum(au_event_t event_number) { static char event_ent_name[AU_EVENT_NAME_MAX]; static char event_ent_desc[AU_EVENT_DESC_MAX]; static struct au_event_ent e; bzero(&e, sizeof(e)); bzero(event_ent_name, sizeof(event_ent_name)); bzero(event_ent_desc, sizeof(event_ent_desc)); e.ae_name = event_ent_name; e.ae_desc = event_ent_desc; return (getauevnum_r(&e, event_number)); } /* * Search for an audit_event entry with a given event_name and returns the * corresponding event number. */ au_event_t * getauevnonam_r(au_event_t *ev, const char *event_name) { static char event_ent_name[AU_EVENT_NAME_MAX]; static char event_ent_desc[AU_EVENT_DESC_MAX]; static struct au_event_ent e, *ep; bzero(event_ent_name, sizeof(event_ent_name)); bzero(event_ent_desc, sizeof(event_ent_desc)); bzero(&e, sizeof(e)); e.ae_name = event_ent_name; e.ae_desc = event_ent_desc; ep = getauevnam_r(&e, event_name); if (ep == NULL) return (NULL); *ev = e.ae_number; return (ev); } au_event_t * getauevnonam(const char *event_name) { static au_event_t event; return (getauevnonam_r(&event, event_name)); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_fcntl.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_fcntl.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_fcntl.c (revision 292449) @@ -1,289 +1,287 @@ /*- * Copyright (c) 2008-2009 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_fcntl.c#2 $ */ #include #include #include #include #include struct bsm_fcntl_cmd { u_short bfc_bsm_fcntl_cmd; int bfc_local_fcntl_cmd; }; typedef struct bsm_fcntl_cmd bsm_fcntl_cmd_t; static const bsm_fcntl_cmd_t bsm_fcntl_cmdtab[] = { { BSM_F_DUPFD, F_DUPFD }, { BSM_F_GETFD, F_GETFD }, { BSM_F_SETFD, F_SETFD }, { BSM_F_GETFL, F_GETFL }, { BSM_F_SETFL, F_SETFL }, #ifdef F_O_GETLK { BSM_F_O_GETLK, F_O_GETLK }, #endif { BSM_F_SETLK, F_SETLK }, { BSM_F_SETLKW, F_SETLK }, #ifdef F_CHFL { BSM_F_CHKFL, F_CHKFL }, #endif #ifdef F_DUP2FD { BSM_F_DUP2FD, F_DUP2FD }, #endif #ifdef F_ALLOCSP { BSM_F_ALLOCSP, F_ALLOCSP }, #endif #ifdef F_FREESP { BSM_F_FREESP, F_FREESP }, #endif #ifdef F_ISSTREAM { BSM_F_ISSTREAM, F_ISSTREAM}, #endif { BSM_F_GETLK, F_GETLK }, #ifdef F_PRIV { BSM_F_PRIV, F_PRIV }, #endif #ifdef F_NPRIV { BSM_F_NPRIV, F_NPRIV }, #endif #ifdef F_QUOTACTL { BSM_F_QUOTACTL, F_QUOTACTL }, #endif #ifdef F_BLOCKS { BSM_F_BLOCKS, F_BLOCKS }, #endif #ifdef F_BLKSIZE { BSM_F_BLKSIZE, F_BLKSIZE }, #endif { BSM_F_GETOWN, F_GETOWN }, { BSM_F_SETOWN, F_SETOWN }, #ifdef F_REVOKE { BSM_F_REVOKE, F_REVOKE }, #endif #ifdef F_HASREMOTEBLOCKS { BSM_F_HASREMOTEBLOCKS, F_HASREMOTEBLOCKS }, #endif #ifdef F_FREESP { BSM_F_FREESP, F_FREESP }, #endif #ifdef F_ALLOCSP { BSM_F_ALLOCSP, F_ALLOCSP }, #endif #ifdef F_FREESP64 { BSM_F_FREESP64, F_FREESP64 }, #endif #ifdef F_ALLOCSP64 { BSM_F_ALLOCSP64, F_ALLOCSP64 }, #endif #ifdef F_GETLK64 { BSM_F_GETLK64, F_GETLK64 }, #endif #ifdef F_SETLK64 { BSM_F_SETLK64, F_SETLK64 }, #endif #ifdef F_SETLKW64 { BSM_F_SETLKW64, F_SETLKW64 }, #endif #ifdef F_SHARE { BSM_F_SHARE, F_SHARE }, #endif #ifdef F_UNSHARE { BSM_F_UNSHARE, F_UNSHARE }, #endif #ifdef F_SETLK_NBMAND { BSM_F_SETLK_NBMAND, F_SETLK_NBMAND }, #endif #ifdef F_SHARE_NBMAND { BSM_F_SHARE_NBMAND, F_SHARE_NBMAND }, #endif #ifdef F_SETLK64_NBMAND { BSM_F_SETLK64_NBMAND, F_SETLK64_NBMAND }, #endif #ifdef F_GETXFL { BSM_F_GETXFL, F_GETXFL }, #endif #ifdef F_BADFD { BSM_F_BADFD, F_BADFD }, #endif #ifdef F_OGETLK { BSM_F_OGETLK, F_OGETLK }, #endif #ifdef F_OSETLK { BSM_F_OSETLK, F_OSETLK }, #endif #ifdef F_OSETLKW { BSM_F_OSETLKW, F_OSETLKW }, #endif #ifdef F_SETLK_REMOTE { BSM_F_SETLK_REMOTE, F_SETLK_REMOTE }, #endif #ifdef F_SETSIG { BSM_F_SETSIG, F_SETSIG }, #endif #ifdef F_GETSIG { BSM_F_GETSIG, F_GETSIG }, #endif #ifdef F_CHKCLEAN { BSM_F_CHKCLEAN, F_CHKCLEAN }, #endif #ifdef F_PREALLOCATE { BSM_F_PREALLOCATE, F_PREALLOCATE }, #endif #ifdef F_SETSIZE { BSM_F_SETSIZE, F_SETSIZE }, #endif #ifdef F_RDADVISE { BSM_F_RDADVISE, F_RDADVISE }, #endif #ifdef F_RDAHEAD { BSM_F_RDAHEAD, F_RDAHEAD }, #endif #ifdef F_READBOOTSTRAP { BSM_F_READBOOTSTRAP, F_READBOOTSTRAP }, #endif #ifdef F_WRITEBOOTSTRAP { BSM_F_WRITEBOOTSTRAP, F_WRITEBOOTSTRAP }, #endif #ifdef F_NOCACHE { BSM_F_NOCACHE, F_NOCACHE }, #endif #ifdef F_LOG2PHYS { BSM_F_LOG2PHYS, F_LOG2PHYS }, #endif #ifdef F_GETPATH { BSM_F_GETPATH, F_GETPATH }, #endif #ifdef F_FULLFSYNC { BSM_F_FULLFSYNC, F_FULLFSYNC }, #endif #ifdef F_PATHPKG_CHECK { BSM_F_PATHPKG_CHECK, F_PATHPKG_CHECK }, #endif #ifdef F_FREEZE_FS { BSM_F_FREEZE_FS, F_FREEZE_FS }, #endif #ifdef F_THAW_FS { BSM_F_THAW_FS, F_THAW_FS }, #endif #ifdef F_GLOBAL_NOCACHE { BSM_F_GLOBAL_NOCACHE, F_GLOBAL_NOCACHE }, #endif #ifdef F_OPENFROM { BSM_F_OPENFROM, F_OPENFROM }, #endif #ifdef F_UNLINKFROM { BSM_F_UNLINKFROM, F_UNLINKFROM }, #endif #ifdef F_CHECK_OPENEVT { BSM_F_CHECK_OPENEVT, F_CHECK_OPENEVT }, #endif #ifdef F_ADDSIGS { BSM_F_ADDSIGS, F_ADDSIGS }, #endif #ifdef F_MARKDEPENDENCY { BSM_F_MARKDEPENDENCY, F_MARKDEPENDENCY }, #endif #ifdef FCNTL_FS_SPECIFIC_BASE { BSM_F_FS_SPECIFIC_0, FCNTL_FS_SPECIFIC_BASE}, { BSM_F_FS_SPECIFIC_1, FCNTL_FS_SPECIFIC_BASE + 1}, { BSM_F_FS_SPECIFIC_2, FCNTL_FS_SPECIFIC_BASE + 2}, { BSM_F_FS_SPECIFIC_3, FCNTL_FS_SPECIFIC_BASE + 3}, { BSM_F_FS_SPECIFIC_4, FCNTL_FS_SPECIFIC_BASE + 4}, { BSM_F_FS_SPECIFIC_5, FCNTL_FS_SPECIFIC_BASE + 5}, { BSM_F_FS_SPECIFIC_6, FCNTL_FS_SPECIFIC_BASE + 6}, { BSM_F_FS_SPECIFIC_7, FCNTL_FS_SPECIFIC_BASE + 7}, { BSM_F_FS_SPECIFIC_8, FCNTL_FS_SPECIFIC_BASE + 8}, { BSM_F_FS_SPECIFIC_9, FCNTL_FS_SPECIFIC_BASE + 9}, { BSM_F_FS_SPECIFIC_10, FCNTL_FS_SPECIFIC_BASE + 10}, { BSM_F_FS_SPECIFIC_11, FCNTL_FS_SPECIFIC_BASE + 11}, { BSM_F_FS_SPECIFIC_12, FCNTL_FS_SPECIFIC_BASE + 12}, { BSM_F_FS_SPECIFIC_13, FCNTL_FS_SPECIFIC_BASE + 13}, { BSM_F_FS_SPECIFIC_14, FCNTL_FS_SPECIFIC_BASE + 14}, { BSM_F_FS_SPECIFIC_15, FCNTL_FS_SPECIFIC_BASE + 15}, #endif /* FCNTL_FS_SPECIFIC_BASE */ }; static const int bsm_fcntl_cmd_count = sizeof(bsm_fcntl_cmdtab) / sizeof(bsm_fcntl_cmdtab[0]); static const bsm_fcntl_cmd_t * bsm_lookup_local_fcntl_cmd(int local_fcntl_cmd) { int i; for (i = 0; i < bsm_fcntl_cmd_count; i++) { if (bsm_fcntl_cmdtab[i].bfc_local_fcntl_cmd == local_fcntl_cmd) return (&bsm_fcntl_cmdtab[i]); } return (NULL); } u_short au_fcntl_cmd_to_bsm(int local_fcntl_cmd) { const bsm_fcntl_cmd_t *bfcp; bfcp = bsm_lookup_local_fcntl_cmd(local_fcntl_cmd); if (bfcp == NULL) return (BSM_F_UNKNOWN); return (bfcp->bfc_bsm_fcntl_cmd); } static const bsm_fcntl_cmd_t * bsm_lookup_bsm_fcntl_cmd(u_short bsm_fcntl_cmd) { int i; for (i = 0; i < bsm_fcntl_cmd_count; i++) { if (bsm_fcntl_cmdtab[i].bfc_bsm_fcntl_cmd == bsm_fcntl_cmd) return (&bsm_fcntl_cmdtab[i]); } return (NULL); } int au_bsm_to_fcntl_cmd(u_short bsm_fcntl_cmd, int *local_fcntl_cmdp) { const bsm_fcntl_cmd_t *bfcp; bfcp = bsm_lookup_bsm_fcntl_cmd(bsm_fcntl_cmd); if (bfcp == NULL || bfcp->bfc_local_fcntl_cmd) return (-1); *local_fcntl_cmdp = bfcp->bfc_local_fcntl_cmd; return (0); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_flags.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_flags.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_flags.c (revision 292449) @@ -1,182 +1,180 @@ /*- * Copyright (c) 2004 Apple Inc. * Copyright (c) 2006 Robert N. M. Watson * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_flags.c#16 $ */ #include #include #include #include #include #ifndef HAVE_STRLCPY #include #endif static const char *flagdelim = ","; /* * Convert the character representation of audit values into the au_mask_t * field. */ int getauditflagsbin(char *auditstr, au_mask_t *masks) { char class_ent_name[AU_CLASS_NAME_MAX]; char class_ent_desc[AU_CLASS_DESC_MAX]; struct au_class_ent c; char *tok; char sel, sub; char *last; bzero(&c, sizeof(c)); bzero(class_ent_name, sizeof(class_ent_name)); bzero(class_ent_desc, sizeof(class_ent_desc)); c.ac_name = class_ent_name; c.ac_desc = class_ent_desc; masks->am_success = 0; masks->am_failure = 0; tok = strtok_r(auditstr, flagdelim, &last); while (tok != NULL) { /* Check for the events that should not be audited. */ if (tok[0] == '^') { sub = 1; tok++; } else sub = 0; /* Check for the events to be audited for success. */ if (tok[0] == '+') { sel = AU_PRS_SUCCESS; tok++; } else if (tok[0] == '-') { sel = AU_PRS_FAILURE; tok++; } else sel = AU_PRS_BOTH; if ((getauclassnam_r(&c, tok)) != NULL) { if (sub) SUB_FROM_MASK(masks, c.ac_class, sel); else ADD_TO_MASK(masks, c.ac_class, sel); } else { errno = EINVAL; return (-1); } /* Get the next class. */ tok = strtok_r(NULL, flagdelim, &last); } return (0); } /* * Convert the au_mask_t fields into a string value. If verbose is non-zero * the long flag names are used else the short (2-character)flag names are * used. * * XXXRW: If bits are specified that are not matched by any class, they are * omitted rather than rejected with EINVAL. * * XXXRW: This is not thread-safe as it relies on atomicity between * setauclass() and sequential calls to getauclassent(). This could be * fixed by iterating through the bitmask fields rather than iterating * through the classes. */ int getauditflagschar(char *auditstr, au_mask_t *masks, int verbose) { char class_ent_name[AU_CLASS_NAME_MAX]; char class_ent_desc[AU_CLASS_DESC_MAX]; struct au_class_ent c; char *strptr = auditstr; u_char sel; bzero(&c, sizeof(c)); bzero(class_ent_name, sizeof(class_ent_name)); bzero(class_ent_desc, sizeof(class_ent_desc)); c.ac_name = class_ent_name; c.ac_desc = class_ent_desc; /* * Enumerate the class entries, check if each is selected in either * the success or failure masks. */ setauclass(); while ((getauclassent_r(&c)) != NULL) { sel = 0; /* Dont do anything for class = no. */ if (c.ac_class == 0) continue; sel |= ((c.ac_class & masks->am_success) == c.ac_class) ? AU_PRS_SUCCESS : 0; sel |= ((c.ac_class & masks->am_failure) == c.ac_class) ? AU_PRS_FAILURE : 0; /* * No prefix should be attached if both success and failure * are selected. */ if ((sel & AU_PRS_BOTH) == 0) { if ((sel & AU_PRS_SUCCESS) != 0) { *strptr = '+'; strptr = strptr + 1; } else if ((sel & AU_PRS_FAILURE) != 0) { *strptr = '-'; strptr = strptr + 1; } } if (sel != 0) { if (verbose) { strlcpy(strptr, c.ac_desc, AU_CLASS_DESC_MAX); strptr += strlen(c.ac_desc); } else { strlcpy(strptr, c.ac_name, AU_CLASS_NAME_MAX); strptr += strlen(c.ac_name); } *strptr = ','; /* delimiter */ strptr = strptr + 1; } } /* Overwrite the last delimiter with the string terminator. */ if (strptr != auditstr) *(strptr-1) = '\0'; return (0); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_io.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_io.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_io.c (revision 292449) @@ -1,4613 +1,4612 @@ /*- * Copyright (c) 2004-2009 Apple Inc. * Copyright (c) 2005 SPARTA, Inc. * Copyright (c) 2006 Robert N. M. Watson * Copyright (c) 2006 Martin Voros * All rights reserved. * * This code was developed in part by Robert N. M. Watson, Senior Principal * Scientist, SPARTA, Inc. * * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_io.c#75 $ */ #include #include #ifdef USE_ENDIAN_H #include #endif #ifdef USE_SYS_ENDIAN_H #include #endif #ifdef USE_MACHINE_ENDIAN_H #include #endif #ifdef USE_COMPAT_ENDIAN_H #include #endif #ifdef USE_COMPAT_ENDIAN_ENC_H #include #endif #ifdef HAVE_FULL_QUEUE_H #include #else /* !HAVE_FULL_QUEUE_H */ #include #endif /* !HAVE_FULL_QUEUE_H */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_VIS #include #else #include #endif #include #define READ_TOKEN_BYTES(buf, len, dest, size, bytesread, err) do { \ if ((bytesread) + (size) > (u_int32_t)(len)) { \ (err) = 1; \ } else { \ memcpy((dest), (buf) + (bytesread), (size)); \ bytesread += size; \ } \ } while (0) #define READ_TOKEN_U_CHAR(buf, len, dest, bytesread, err) do { \ if ((bytesread) + sizeof(u_char) <= (u_int32_t)(len)) { \ (dest) = buf[(bytesread)]; \ (bytesread) += sizeof(u_char); \ } else \ (err) = 1; \ } while (0) #define READ_TOKEN_U_INT16(buf, len, dest, bytesread, err) do { \ if ((bytesread) + sizeof(u_int16_t) <= (u_int32_t)(len)) { \ (dest) = be16dec((buf) + (bytesread)); \ (bytesread) += sizeof(u_int16_t); \ } else \ (err) = 1; \ } while (0) #define READ_TOKEN_U_INT32(buf, len, dest, bytesread, err) do { \ if ((bytesread) + sizeof(u_int32_t) <= (u_int32_t)(len)) { \ (dest) = be32dec((buf) + (bytesread)); \ (bytesread) += sizeof(u_int32_t); \ } else \ (err) = 1; \ } while (0) #define READ_TOKEN_U_INT64(buf, len, dest, bytesread, err) do { \ if ((bytesread) + sizeof(u_int64_t) <= (u_int32_t)(len)) { \ dest = be64dec((buf) + (bytesread)); \ (bytesread) += sizeof(u_int64_t); \ } else \ (err) = 1; \ } while (0) #define SET_PTR(buf, len, ptr, size, bytesread, err) do { \ if ((bytesread) + (size) > (u_int32_t)(len)) \ (err) = 1; \ else { \ (ptr) = (buf) + (bytesread); \ (bytesread) += (size); \ } \ } while (0) /* * XML option. */ #define AU_PLAIN 0 #define AU_XML 1 /* * Prints the delimiter string. */ static void print_delim(FILE *fp, const char *del) { fprintf(fp, "%s", del); } /* * Prints a single byte in the given format. */ static void print_1_byte(FILE *fp, u_char val, const char *format) { fprintf(fp, format, val); } /* * Print 2 bytes in the given format. */ static void print_2_bytes(FILE *fp, u_int16_t val, const char *format) { fprintf(fp, format, val); } /* * Prints 4 bytes in the given format. */ static void print_4_bytes(FILE *fp, u_int32_t val, const char *format) { fprintf(fp, format, val); } /* * Prints 8 bytes in the given format. */ static void print_8_bytes(FILE *fp, u_int64_t val, const char *format) { fprintf(fp, format, val); } /* * Prints the given size of data bytes in hex. */ static void print_mem(FILE *fp, u_char *data, size_t len) { u_int32_t i; if (len > 0) { fprintf(fp, "0x"); for (i = 0; i < len; i++) fprintf(fp, "%02x", data[i]); } } /* * Prints the given data bytes as a string. */ static void print_string(FILE *fp, const char *str, size_t len) { u_int32_t i; if (len > 0) { for (i = 0; i < len; i++) { if (str[i] != '\0') fprintf(fp, "%c", str[i]); } } } /* * Prints the given data bytes as an XML-sanitized string. */ static void print_xml_string(FILE *fp, const char *str, size_t len) { u_int32_t i; char visbuf[5]; if (len == 0) return; for (i = 0; i < len; i++) { switch (str[i]) { case '\0': return; case '&': (void) fprintf(fp, "&"); break; case '<': (void) fprintf(fp, "<"); break; case '>': (void) fprintf(fp, ">"); break; case '\"': (void) fprintf(fp, """); break; case '\'': (void) fprintf(fp, "'"); break; default: (void) vis(visbuf, str[i], VIS_CSTYLE, 0); (void) fprintf(fp, "%s", visbuf); break; } } } /* - * Prints the beggining of attribute. + * Prints the beginning of an attribute. */ static void open_attr(FILE *fp, const char *str) { fprintf(fp,"%s=\"", str); } /* - * Prints the end of attribute. + * Prints the end of an attribute. */ static void close_attr(FILE *fp) { fprintf(fp,"\" "); } /* - * Prints the end of tag. + * Prints the end of a tag. */ static void close_tag(FILE *fp, u_char type) { switch(type) { case AUT_HEADER32: fprintf(fp, ">"); break; case AUT_HEADER32_EX: fprintf(fp, ">"); break; case AUT_HEADER64: fprintf(fp, ">"); break; case AUT_HEADER64_EX: fprintf(fp, ">"); break; case AUT_ARG32: fprintf(fp, "/>"); break; case AUT_ARG64: fprintf(fp, "/>"); break; case AUT_ATTR32: fprintf(fp, "/>"); break; case AUT_ATTR64: fprintf(fp, "/>"); break; case AUT_EXIT: fprintf(fp, "/>"); break; case AUT_EXEC_ARGS: fprintf(fp, ""); break; case AUT_EXEC_ENV: fprintf(fp, ""); break; case AUT_OTHER_FILE32: fprintf(fp, ""); break; case AUT_NEWGROUPS: fprintf(fp, ""); break; case AUT_IN_ADDR: fprintf(fp, ""); break; case AUT_IN_ADDR_EX: fprintf(fp, ""); break; case AUT_IP: fprintf(fp, "/>"); break; case AUT_IPC: fprintf(fp, "/>"); break; case AUT_IPC_PERM: fprintf(fp, "/>"); break; case AUT_IPORT: fprintf(fp, ""); break; case AUT_OPAQUE: fprintf(fp, ""); break; case AUT_PATH: fprintf(fp, ""); break; case AUT_PROCESS32: fprintf(fp, "/>"); break; case AUT_PROCESS32_EX: fprintf(fp, "/>"); break; case AUT_PROCESS64: fprintf(fp, "/>"); break; case AUT_PROCESS64_EX: fprintf(fp, "/>"); break; case AUT_RETURN32: fprintf(fp, "/>"); break; case AUT_RETURN64: fprintf(fp, "/>"); break; case AUT_SEQ: fprintf(fp, "/>"); break; case AUT_SOCKET: fprintf(fp, "/>"); break; case AUT_SOCKINET32: fprintf(fp, "/>"); break; case AUT_SOCKUNIX: fprintf(fp, "/>"); break; case AUT_SOCKINET128: fprintf(fp, "/>"); break; case AUT_SUBJECT32: fprintf(fp, "/>"); break; case AUT_SUBJECT64: fprintf(fp, "/>"); break; case AUT_SUBJECT32_EX: fprintf(fp, "/>"); break; case AUT_SUBJECT64_EX: fprintf(fp, "/>"); break; case AUT_TEXT: fprintf(fp, ""); break; case AUT_SOCKET_EX: fprintf(fp, "/>"); break; case AUT_DATA: fprintf(fp, ""); break; case AUT_ZONENAME: fprintf(fp, "/>"); break; } } /* * Prints the token type in either the raw or the default form. */ static void print_tok_type(FILE *fp, u_char type, const char *tokname, int oflags) { if (oflags & AU_OFLAG_XML) { switch(type) { case AUT_HEADER32: fprintf(fp, ""); break; case AUT_ARG32: fprintf(fp, ""); break; case AUT_EXEC_ENV: fprintf(fp, ""); break; case AUT_OTHER_FILE32: fprintf(fp, ""); break; case AUT_IN_ADDR: fprintf(fp, ""); break; case AUT_IN_ADDR_EX: fprintf(fp, ""); break; case AUT_IP: fprintf(fp, ""); break; case AUT_OPAQUE: fprintf(fp, ""); break; case AUT_PATH: fprintf(fp, ""); break; case AUT_PROCESS32: fprintf(fp, ""); break; case AUT_SOCKET_EX: fprintf(fp, "pw_name); else fprintf(fp, "%d", usr); } } /* * Prints a group value. */ static void print_group(FILE *fp, u_int32_t grp, int oflags) { struct group *grpent; if (oflags & AU_OFLAG_RAW) fprintf(fp, "%d", grp); else { grpent = getgrgid(grp); if (grpent != NULL) fprintf(fp, "%s", grpent->gr_name); else fprintf(fp, "%d", grp); } } /* * Prints the event from the header token in either the short, default or raw * form. */ static void print_event(FILE *fp, u_int16_t ev, int oflags) { char event_ent_name[AU_EVENT_NAME_MAX]; char event_ent_desc[AU_EVENT_DESC_MAX]; struct au_event_ent e, *ep; bzero(&e, sizeof(e)); bzero(event_ent_name, sizeof(event_ent_name)); bzero(event_ent_desc, sizeof(event_ent_desc)); e.ae_name = event_ent_name; e.ae_desc = event_ent_desc; ep = getauevnum_r(&e, ev); if (ep == NULL) { fprintf(fp, "%u", ev); return; } if (oflags & AU_OFLAG_RAW) fprintf(fp, "%u", ev); else if (oflags & AU_OFLAG_SHORT) fprintf(fp, "%s", e.ae_name); else fprintf(fp, "%s", e.ae_desc); } /* * Prints the event modifier from the header token in either the default or * raw form. */ static void print_evmod(FILE *fp, u_int16_t evmod, int oflags) { if (oflags & AU_OFLAG_RAW) fprintf(fp, "%u", evmod); else fprintf(fp, "%u", evmod); } /* * Prints seconds in the ctime format. */ static void print_sec32(FILE *fp, u_int32_t sec, int oflags) { time_t timestamp; char timestr[26]; if (oflags & AU_OFLAG_RAW) fprintf(fp, "%u", sec); else { timestamp = (time_t)sec; ctime_r(×tamp, timestr); timestr[24] = '\0'; /* No new line */ fprintf(fp, "%s", timestr); } } /* * XXXRW: 64-bit token streams make use of 64-bit time stamps; since we * assume a 32-bit time_t, we simply truncate for now. */ static void print_sec64(FILE *fp, u_int64_t sec, int oflags) { time_t timestamp; char timestr[26]; if (oflags & AU_OFLAG_RAW) fprintf(fp, "%u", (u_int32_t)sec); else { timestamp = (time_t)sec; ctime_r(×tamp, timestr); timestr[24] = '\0'; /* No new line */ fprintf(fp, "%s", timestr); } } /* * Prints the excess milliseconds. */ static void print_msec32(FILE *fp, u_int32_t msec, int oflags) { if (oflags & AU_OFLAG_RAW) fprintf(fp, "%u", msec); else fprintf(fp, " + %u msec", msec); } /* * XXXRW: 64-bit token streams make use of 64-bit time stamps; since we assume * a 32-bit msec, we simply truncate for now. */ static void print_msec64(FILE *fp, u_int64_t msec, int oflags) { msec &= 0xffffffff; if (oflags & AU_OFLAG_RAW) fprintf(fp, "%u", (u_int32_t)msec); else fprintf(fp, " + %u msec", (u_int32_t)msec); } /* * Prints a dotted form for the IP address. */ static void print_ip_address(FILE *fp, u_int32_t ip) { struct in_addr ipaddr; ipaddr.s_addr = ip; fprintf(fp, "%s", inet_ntoa(ipaddr)); } /* * Prints a string value for the given ip address. */ static void print_ip_ex_address(FILE *fp, u_int32_t type, u_int32_t *ipaddr) { struct in_addr ipv4; struct in6_addr ipv6; char dst[INET6_ADDRSTRLEN]; switch (type) { case AU_IPv4: ipv4.s_addr = (in_addr_t)(ipaddr[0]); fprintf(fp, "%s", inet_ntop(AF_INET, &ipv4, dst, INET6_ADDRSTRLEN)); break; case AU_IPv6: bcopy(ipaddr, &ipv6, sizeof(ipv6)); fprintf(fp, "%s", inet_ntop(AF_INET6, &ipv6, dst, INET6_ADDRSTRLEN)); break; default: fprintf(fp, "invalid"); } } /* * Prints return value as success or failure. */ static void print_retval(FILE *fp, u_char status, int oflags) { int error; if (oflags & AU_OFLAG_RAW) fprintf(fp, "%u", status); else { /* * Convert to a local error number and print the OS's version * of the error string if possible. We may want to provide * an au_strerror(3) in the future so that we can print * strings for non-local errors. */ if (au_bsm_to_errno(status, &error) == 0) { if (error == 0) fprintf(fp, "success"); else fprintf(fp, "failure : %s", strerror(error)); } else fprintf(fp, "failure: Unknown error: %d", status); } } /* * Prints the exit value. */ static void print_errval(FILE *fp, u_int32_t val) { fprintf(fp, "Error %u", val); } /* * Prints IPC type. */ static void print_ipctype(FILE *fp, u_char type, int oflags) { if (oflags & AU_OFLAG_RAW) fprintf(fp, "%u", type); else { if (type == AT_IPC_MSG) fprintf(fp, "Message IPC"); else if (type == AT_IPC_SEM) fprintf(fp, "Semaphore IPC"); else if (type == AT_IPC_SHM) fprintf(fp, "Shared Memory IPC"); else fprintf(fp, "%u", type); } } /* * Print XML header. */ void au_print_xml_header(FILE *outfp) { fprintf(outfp, "\n"); fprintf(outfp, "\n"); } /* * Print XML footer. */ void au_print_xml_footer(FILE *outfp) { fprintf(outfp, "\n"); } /* * record byte count 4 bytes * version # 1 byte [2] * event type 2 bytes * event modifier 2 bytes * seconds of time 4 bytes/8 bytes (32-bit/64-bit value) * milliseconds of time 4 bytes/8 bytes (32-bit/64-bit value) */ static int fetch_header32_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32.size, tok->len, err); if (err) return (-1); READ_TOKEN_U_CHAR(buf, len, tok->tt.hdr32.version, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT16(buf, len, tok->tt.hdr32.e_type, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT16(buf, len, tok->tt.hdr32.e_mod, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32.s, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32.ms, tok->len, err); if (err) return (-1); return (0); } static void print_header32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "header", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "version"); print_1_byte(fp, tok->tt.hdr32.version, "%u"); close_attr(fp); open_attr(fp, "event"); print_event(fp, tok->tt.hdr32.e_type, oflags); close_attr(fp); open_attr(fp, "modifier"); print_evmod(fp, tok->tt.hdr32.e_mod, oflags); close_attr(fp); open_attr(fp, "time"); print_sec32(fp, tok->tt.hdr32.s, oflags); close_attr(fp); open_attr(fp, "msec"); print_msec32(fp, tok->tt.hdr32.ms, oflags); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_4_bytes(fp, tok->tt.hdr32.size, "%u"); print_delim(fp, del); print_1_byte(fp, tok->tt.hdr32.version, "%u"); print_delim(fp, del); print_event(fp, tok->tt.hdr32.e_type, oflags); print_delim(fp, del); print_evmod(fp, tok->tt.hdr32.e_mod, oflags); print_delim(fp, del); print_sec32(fp, tok->tt.hdr32.s, oflags); print_delim(fp, del); print_msec32(fp, tok->tt.hdr32.ms, oflags); } } /* * The Solaris specifications for AUE_HEADER32_EX seem to differ a bit * depending on the bit of the specifications found. The OpenSolaris source * code uses a 4-byte address length, followed by some number of bytes of * address data. This contrasts with the Solaris audit.log.5 man page, which * specifies a 1-byte length field. We use the Solaris 10 definition so that * we can parse audit trails from that system. * * record byte count 4 bytes * version # 1 byte [2] * event type 2 bytes * event modifier 2 bytes * address type/length 4 bytes * [ Solaris man page: address type/length 1 byte] * machine address 4 bytes/16 bytes (IPv4/IPv6 address) * seconds of time 4 bytes/8 bytes (32/64-bits) * nanoseconds of time 4 bytes/8 bytes (32/64-bits) */ static int fetch_header32_ex_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32_ex.size, tok->len, err); if (err) return (-1); READ_TOKEN_U_CHAR(buf, len, tok->tt.hdr32_ex.version, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT16(buf, len, tok->tt.hdr32_ex.e_type, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT16(buf, len, tok->tt.hdr32_ex.e_mod, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32_ex.ad_type, tok->len, err); if (err) return (-1); bzero(tok->tt.hdr32_ex.addr, sizeof(tok->tt.hdr32_ex.addr)); switch (tok->tt.hdr32_ex.ad_type) { case AU_IPv4: READ_TOKEN_BYTES(buf, len, &tok->tt.hdr32_ex.addr[0], sizeof(tok->tt.hdr32_ex.addr[0]), tok->len, err); if (err) return (-1); break; case AU_IPv6: READ_TOKEN_BYTES(buf, len, tok->tt.hdr32_ex.addr, sizeof(tok->tt.hdr32_ex.addr), tok->len, err); break; } READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32_ex.s, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.hdr32_ex.ms, tok->len, err); if (err) return (-1); return (0); } static void print_header32_ex_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "header_ex", oflags); if (oflags & AU_OFLAG_RAW) { open_attr(fp, "version"); print_1_byte(fp, tok->tt.hdr32_ex.version, "%u"); close_attr(fp); open_attr(fp, "event"); print_event(fp, tok->tt.hdr32_ex.e_type, oflags); close_attr(fp); open_attr(fp, "modifier"); print_evmod(fp, tok->tt.hdr32_ex.e_mod, oflags); close_attr(fp); open_attr(fp, "host"); print_ip_ex_address(fp, tok->tt.hdr32_ex.ad_type, tok->tt.hdr32_ex.addr); close_attr(fp); open_attr(fp, "time"); print_sec32(fp, tok->tt.hdr32_ex.s, oflags); close_attr(fp); open_attr(fp, "msec"); print_msec32(fp, tok->tt.hdr32_ex.ms, oflags); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_4_bytes(fp, tok->tt.hdr32_ex.size, "%u"); print_delim(fp, del); print_1_byte(fp, tok->tt.hdr32_ex.version, "%u"); print_delim(fp, del); print_event(fp, tok->tt.hdr32_ex.e_type, oflags); print_delim(fp, del); print_evmod(fp, tok->tt.hdr32_ex.e_mod, oflags); print_delim(fp, del); print_ip_ex_address(fp, tok->tt.hdr32_ex.ad_type, tok->tt.hdr32_ex.addr); print_delim(fp, del); print_sec32(fp, tok->tt.hdr32_ex.s, oflags); print_delim(fp, del); print_msec32(fp, tok->tt.hdr32_ex.ms, oflags); } } /* * record byte count 4 bytes * event type 2 bytes * event modifier 2 bytes * seconds of time 4 bytes/8 bytes (32-bit/64-bit value) * milliseconds of time 4 bytes/8 bytes (32-bit/64-bit value) * version # */ static int fetch_header64_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.hdr64.size, tok->len, err); if (err) return (-1); READ_TOKEN_U_CHAR(buf, len, tok->tt.hdr64.version, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT16(buf, len, tok->tt.hdr64.e_type, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT16(buf, len, tok->tt.hdr64.e_mod, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT64(buf, len, tok->tt.hdr64.s, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT64(buf, len, tok->tt.hdr64.ms, tok->len, err); if (err) return (-1); return (0); } static void print_header64_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "header", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "version"); print_1_byte(fp, tok->tt.hdr64.version, "%u"); close_attr(fp); open_attr(fp, "event"); print_event(fp, tok->tt.hdr64.e_type, oflags); close_attr(fp); open_attr(fp, "modifier"); print_evmod(fp, tok->tt.hdr64.e_mod, oflags); close_attr(fp); open_attr(fp, "time"); print_sec64(fp, tok->tt.hdr64.s, oflags); close_attr(fp); open_attr(fp, "msec"); print_msec64(fp, tok->tt.hdr64.ms, oflags); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_4_bytes(fp, tok->tt.hdr64.size, "%u"); print_delim(fp, del); print_1_byte(fp, tok->tt.hdr64.version, "%u"); print_delim(fp, del); print_event(fp, tok->tt.hdr64.e_type, oflags); print_delim(fp, del); print_evmod(fp, tok->tt.hdr64.e_mod, oflags); print_delim(fp, del); print_sec64(fp, tok->tt.hdr64.s, oflags); print_delim(fp, del); print_msec64(fp, tok->tt.hdr64.ms, oflags); } } /* * record byte count 4 bytes * version # 1 byte [2] * event type 2 bytes * event modifier 2 bytes * address type/length 4 bytes * [ Solaris man page: address type/length 1 byte] * machine address 4 bytes/16 bytes (IPv4/IPv6 address) * seconds of time 4 bytes/8 bytes (32/64-bits) * nanoseconds of time 4 bytes/8 bytes (32/64-bits) * * XXXAUDIT: See comment by fetch_header32_ex_tok() for details on the * accuracy of the BSM spec. */ static int fetch_header64_ex_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.hdr64_ex.size, tok->len, err); if (err) return (-1); READ_TOKEN_U_CHAR(buf, len, tok->tt.hdr64_ex.version, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT16(buf, len, tok->tt.hdr64_ex.e_type, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT16(buf, len, tok->tt.hdr64_ex.e_mod, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.hdr64_ex.ad_type, tok->len, err); if (err) return (-1); bzero(tok->tt.hdr64_ex.addr, sizeof(tok->tt.hdr64_ex.addr)); switch (tok->tt.hdr64_ex.ad_type) { case AU_IPv4: READ_TOKEN_BYTES(buf, len, &tok->tt.hdr64_ex.addr[0], sizeof(tok->tt.hdr64_ex.addr[0]), tok->len, err); if (err) return (-1); break; case AU_IPv6: READ_TOKEN_BYTES(buf, len, tok->tt.hdr64_ex.addr, sizeof(tok->tt.hdr64_ex.addr), tok->len, err); break; } READ_TOKEN_U_INT64(buf, len, tok->tt.hdr64_ex.s, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT64(buf, len, tok->tt.hdr64_ex.ms, tok->len, err); if (err) return (-1); return (0); } static void print_header64_ex_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "header_ex", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "version"); print_1_byte(fp, tok->tt.hdr64_ex.version, "%u"); close_attr(fp); open_attr(fp, "event"); print_event(fp, tok->tt.hdr64_ex.e_type, oflags); close_attr(fp); open_attr(fp, "modifier"); print_evmod(fp, tok->tt.hdr64_ex.e_mod, oflags); close_attr(fp); open_attr(fp, "host"); print_ip_ex_address(fp, tok->tt.hdr64_ex.ad_type, tok->tt.hdr64_ex.addr); close_attr(fp); open_attr(fp, "time"); print_sec64(fp, tok->tt.hdr64_ex.s, oflags); close_attr(fp); open_attr(fp, "msec"); print_msec64(fp, tok->tt.hdr64_ex.ms, oflags); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_4_bytes(fp, tok->tt.hdr64_ex.size, "%u"); print_delim(fp, del); print_1_byte(fp, tok->tt.hdr64_ex.version, "%u"); print_delim(fp, del); print_event(fp, tok->tt.hdr64_ex.e_type, oflags); print_delim(fp, del); print_evmod(fp, tok->tt.hdr64_ex.e_mod, oflags); print_delim(fp, del); print_ip_ex_address(fp, tok->tt.hdr64_ex.ad_type, tok->tt.hdr64_ex.addr); print_delim(fp, del); print_sec64(fp, tok->tt.hdr64_ex.s, oflags); print_delim(fp, del); print_msec64(fp, tok->tt.hdr64_ex.ms, oflags); } } /* * trailer magic 2 bytes * record size 4 bytes */ static int fetch_trailer_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT16(buf, len, tok->tt.trail.magic, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.trail.count, tok->len, err); if (err) return (-1); return (0); } static void print_trailer_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "trailer", oflags); if (!(oflags & AU_OFLAG_XML)) { print_delim(fp, del); print_4_bytes(fp, tok->tt.trail.count, "%u"); } } /* * argument # 1 byte * argument value 4 bytes/8 bytes (32-bit/64-bit value) * text length 2 bytes * text N bytes + 1 terminating NULL byte */ static int fetch_arg32_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_CHAR(buf, len, tok->tt.arg32.no, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.arg32.val, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT16(buf, len, tok->tt.arg32.len, tok->len, err); if (err) return (-1); SET_PTR((char*)buf, len, tok->tt.arg32.text, tok->tt.arg32.len, tok->len, err); if (err) return (-1); return (0); } static void print_arg32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "argument", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "arg-num"); print_1_byte(fp, tok->tt.arg32.no, "%u"); close_attr(fp); open_attr(fp, "value"); print_4_bytes(fp, tok->tt.arg32.val, "0x%x"); close_attr(fp); open_attr(fp, "desc"); print_string(fp, tok->tt.arg32.text, tok->tt.arg32.len); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_1_byte(fp, tok->tt.arg32.no, "%u"); print_delim(fp, del); print_4_bytes(fp, tok->tt.arg32.val, "0x%x"); print_delim(fp, del); print_string(fp, tok->tt.arg32.text, tok->tt.arg32.len); } } static int fetch_arg64_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_CHAR(buf, len, tok->tt.arg64.no, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT64(buf, len, tok->tt.arg64.val, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT16(buf, len, tok->tt.arg64.len, tok->len, err); if (err) return (-1); SET_PTR((char*)buf, len, tok->tt.arg64.text, tok->tt.arg64.len, tok->len, err); if (err) return (-1); return (0); } static void print_arg64_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "argument", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "arg-num"); print_1_byte(fp, tok->tt.arg64.no, "%u"); close_attr(fp); open_attr(fp, "value"); print_8_bytes(fp, tok->tt.arg64.val, "0x%llx"); close_attr(fp); open_attr(fp, "desc"); print_string(fp, tok->tt.arg64.text, tok->tt.arg64.len); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_1_byte(fp, tok->tt.arg64.no, "%u"); print_delim(fp, del); print_8_bytes(fp, tok->tt.arg64.val, "0x%llx"); print_delim(fp, del); print_string(fp, tok->tt.arg64.text, tok->tt.arg64.len); } } /* * how to print 1 byte * basic unit 1 byte * unit count 1 byte * data items (depends on basic unit) */ static int fetch_arb_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; int datasize; READ_TOKEN_U_CHAR(buf, len, tok->tt.arb.howtopr, tok->len, err); if (err) return (-1); READ_TOKEN_U_CHAR(buf, len, tok->tt.arb.bu, tok->len, err); if (err) return (-1); READ_TOKEN_U_CHAR(buf, len, tok->tt.arb.uc, tok->len, err); if (err) return (-1); /* * Determine the size of the basic unit. */ switch(tok->tt.arb.bu) { case AUR_BYTE: /* case AUR_CHAR: */ datasize = AUR_BYTE_SIZE; break; case AUR_SHORT: datasize = AUR_SHORT_SIZE; break; case AUR_INT32: /* case AUR_INT: */ datasize = AUR_INT32_SIZE; break; case AUR_INT64: datasize = AUR_INT64_SIZE; break; default: return (-1); } SET_PTR(buf, len, tok->tt.arb.data, datasize * tok->tt.arb.uc, tok->len, err); if (err) return (-1); return (0); } static void print_arb_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { char *str; char *format; size_t size; int i; print_tok_type(fp, tok->id, "arbitrary", oflags); if (!(oflags & AU_OFLAG_XML)) print_delim(fp, del); switch(tok->tt.arb.howtopr) { case AUP_BINARY: str = "binary"; format = " %c"; break; case AUP_OCTAL: str = "octal"; format = " %o"; break; case AUP_DECIMAL: str = "decimal"; format = " %d"; break; case AUP_HEX: str = "hex"; format = " %x"; break; case AUP_STRING: str = "string"; format = "%c"; break; default: return; } if (oflags & AU_OFLAG_XML) { open_attr(fp, "print"); fprintf(fp, "%s",str); close_attr(fp); } else { print_string(fp, str, strlen(str)); print_delim(fp, del); } switch(tok->tt.arb.bu) { case AUR_BYTE: /* case AUR_CHAR: */ str = "byte"; size = AUR_BYTE_SIZE; if (oflags & AU_OFLAG_XML) { open_attr(fp, "type"); fprintf(fp, "%zu", size); close_attr(fp); open_attr(fp, "count"); print_1_byte(fp, tok->tt.arb.uc, "%u"); close_attr(fp); fprintf(fp, ">"); for (i = 0; itt.arb.uc; i++) fprintf(fp, format, *(tok->tt.arb.data + (size * i))); close_tag(fp, tok->id); } else { print_string(fp, str, strlen(str)); print_delim(fp, del); print_1_byte(fp, tok->tt.arb.uc, "%u"); print_delim(fp, del); for (i = 0; itt.arb.uc; i++) fprintf(fp, format, *(tok->tt.arb.data + (size * i))); } break; case AUR_SHORT: str = "short"; size = AUR_SHORT_SIZE; if (oflags & AU_OFLAG_XML) { open_attr(fp, "type"); fprintf(fp, "%zu", size); close_attr(fp); open_attr(fp, "count"); print_1_byte(fp, tok->tt.arb.uc, "%u"); close_attr(fp); fprintf(fp, ">"); for (i = 0; i < tok->tt.arb.uc; i++) fprintf(fp, format, *((u_int16_t *)(tok->tt.arb.data + (size * i)))); close_tag(fp, tok->id); } else { print_string(fp, str, strlen(str)); print_delim(fp, del); print_1_byte(fp, tok->tt.arb.uc, "%u"); print_delim(fp, del); for (i = 0; i < tok->tt.arb.uc; i++) fprintf(fp, format, *((u_int16_t *)(tok->tt.arb.data + (size * i)))); } break; case AUR_INT32: /* case AUR_INT: */ str = "int"; size = AUR_INT32_SIZE; if (oflags & AU_OFLAG_XML) { open_attr(fp, "type"); fprintf(fp, "%zu", size); close_attr(fp); open_attr(fp, "count"); print_1_byte(fp, tok->tt.arb.uc, "%u"); close_attr(fp); fprintf(fp, ">"); for (i = 0; i < tok->tt.arb.uc; i++) fprintf(fp, format, *((u_int32_t *)(tok->tt.arb.data + (size * i)))); close_tag(fp, tok->id); } else { print_string(fp, str, strlen(str)); print_delim(fp, del); print_1_byte(fp, tok->tt.arb.uc, "%u"); print_delim(fp, del); for (i = 0; i < tok->tt.arb.uc; i++) fprintf(fp, format, *((u_int32_t *)(tok->tt.arb.data + (size * i)))); } break; case AUR_INT64: str = "int64"; size = AUR_INT64_SIZE; if (oflags & AU_OFLAG_XML) { open_attr(fp, "type"); fprintf(fp, "%zu", size); close_attr(fp); open_attr(fp, "count"); print_1_byte(fp, tok->tt.arb.uc, "%u"); close_attr(fp); fprintf(fp, ">"); for (i = 0; i < tok->tt.arb.uc; i++) fprintf(fp, format, *((u_int64_t *)(tok->tt.arb.data + (size * i)))); close_tag(fp, tok->id); } else { print_string(fp, str, strlen(str)); print_delim(fp, del); print_1_byte(fp, tok->tt.arb.uc, "%u"); print_delim(fp, del); for (i = 0; i < tok->tt.arb.uc; i++) fprintf(fp, format, *((u_int64_t *)(tok->tt.arb.data + (size * i)))); } break; default: return; } } /* * file access mode 4 bytes * owner user ID 4 bytes * owner group ID 4 bytes * file system ID 4 bytes * node ID 8 bytes * device 4 bytes/8 bytes (32-bit/64-bit) */ static int fetch_attr32_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.attr32.mode, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.attr32.uid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.attr32.gid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.attr32.fsid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT64(buf, len, tok->tt.attr32.nid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.attr32.dev, tok->len, err); if (err) return (-1); return (0); } static void print_attr32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "attribute", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "mode"); print_4_bytes(fp, tok->tt.attr32.mode, "%o"); close_attr(fp); open_attr(fp, "uid"); print_user(fp, tok->tt.attr32.uid, oflags); close_attr(fp); open_attr(fp, "gid"); print_group(fp, tok->tt.attr32.gid, oflags); close_attr(fp); open_attr(fp, "fsid"); print_4_bytes(fp, tok->tt.attr32.fsid, "%u"); close_attr(fp); open_attr(fp, "nodeid"); print_8_bytes(fp, tok->tt.attr32.nid, "%lld"); close_attr(fp); open_attr(fp, "device"); print_4_bytes(fp, tok->tt.attr32.dev, "%u"); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_4_bytes(fp, tok->tt.attr32.mode, "%o"); print_delim(fp, del); print_user(fp, tok->tt.attr32.uid, oflags); print_delim(fp, del); print_group(fp, tok->tt.attr32.gid, oflags); print_delim(fp, del); print_4_bytes(fp, tok->tt.attr32.fsid, "%u"); print_delim(fp, del); print_8_bytes(fp, tok->tt.attr32.nid, "%lld"); print_delim(fp, del); print_4_bytes(fp, tok->tt.attr32.dev, "%u"); } } /* * file access mode 4 bytes * owner user ID 4 bytes * owner group ID 4 bytes * file system ID 4 bytes * node ID 8 bytes * device 4 bytes/8 bytes (32-bit/64-bit) */ static int fetch_attr64_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.attr64.mode, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.attr64.uid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.attr64.gid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.attr64.fsid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT64(buf, len, tok->tt.attr64.nid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT64(buf, len, tok->tt.attr64.dev, tok->len, err); if (err) return (-1); return (0); } static void print_attr64_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "attribute", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "mode"); print_4_bytes(fp, tok->tt.attr64.mode, "%o"); close_attr(fp); open_attr(fp, "uid"); print_user(fp, tok->tt.attr64.uid, oflags); close_attr(fp); open_attr(fp, "gid"); print_group(fp, tok->tt.attr64.gid, oflags); close_attr(fp); open_attr(fp, "fsid"); print_4_bytes(fp, tok->tt.attr64.fsid, "%u"); close_attr(fp); open_attr(fp, "nodeid"); print_8_bytes(fp, tok->tt.attr64.nid, "%lld"); close_attr(fp); open_attr(fp, "device"); print_8_bytes(fp, tok->tt.attr64.dev, "%llu"); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_4_bytes(fp, tok->tt.attr64.mode, "%o"); print_delim(fp, del); print_user(fp, tok->tt.attr64.uid, oflags); print_delim(fp, del); print_group(fp, tok->tt.attr64.gid, oflags); print_delim(fp, del); print_4_bytes(fp, tok->tt.attr64.fsid, "%u"); print_delim(fp, del); print_8_bytes(fp, tok->tt.attr64.nid, "%lld"); print_delim(fp, del); print_8_bytes(fp, tok->tt.attr64.dev, "%llu"); } } /* * status 4 bytes * return value 4 bytes */ static int fetch_exit_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.exit.status, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.exit.ret, tok->len, err); if (err) return (-1); return (0); } static void print_exit_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "exit", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "errval"); print_errval(fp, tok->tt.exit.status); close_attr(fp); open_attr(fp, "retval"); print_4_bytes(fp, tok->tt.exit.ret, "%u"); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_errval(fp, tok->tt.exit.status); print_delim(fp, del); print_4_bytes(fp, tok->tt.exit.ret, "%u"); } } /* * count 4 bytes * text count null-terminated string(s) */ static int fetch_execarg_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; u_int32_t i; u_char *bptr; READ_TOKEN_U_INT32(buf, len, tok->tt.execarg.count, tok->len, err); if (err) return (-1); for (i = 0; i < tok->tt.execarg.count; i++) { bptr = buf + tok->len; if (i < AUDIT_MAX_ARGS) tok->tt.execarg.text[i] = (char*)bptr; /* Look for a null terminated string. */ while (bptr && (*bptr != '\0')) { if (++tok->len >= (u_int32_t)len) return (-1); bptr = buf + tok->len; } if (!bptr) return (-1); tok->len++; /* \0 character */ } if (tok->tt.execarg.count > AUDIT_MAX_ARGS) tok->tt.execarg.count = AUDIT_MAX_ARGS; return (0); } static void print_execarg_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { u_int32_t i; print_tok_type(fp, tok->id, "exec arg", oflags); for (i = 0; i < tok->tt.execarg.count; i++) { if (oflags & AU_OFLAG_XML) { fprintf(fp, ""); print_xml_string(fp, tok->tt.execarg.text[i], strlen(tok->tt.execarg.text[i])); fprintf(fp, ""); } else { print_delim(fp, del); print_string(fp, tok->tt.execarg.text[i], strlen(tok->tt.execarg.text[i])); } } if (oflags & AU_OFLAG_XML) close_tag(fp, tok->id); } /* * count 4 bytes * text count null-terminated string(s) */ static int fetch_execenv_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; u_int32_t i; u_char *bptr; READ_TOKEN_U_INT32(buf, len, tok->tt.execenv.count, tok->len, err); if (err) return (-1); for (i = 0; i < tok->tt.execenv.count; i++) { bptr = buf + tok->len; if (i < AUDIT_MAX_ENV) tok->tt.execenv.text[i] = (char*)bptr; /* Look for a null terminated string. */ while (bptr && (*bptr != '\0')) { if (++tok->len >= (u_int32_t)len) return (-1); bptr = buf + tok->len; } if (!bptr) return (-1); tok->len++; /* \0 character */ } if (tok->tt.execenv.count > AUDIT_MAX_ENV) tok->tt.execenv.count = AUDIT_MAX_ENV; return (0); } static void print_execenv_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { u_int32_t i; print_tok_type(fp, tok->id, "exec env", oflags); for (i = 0; i< tok->tt.execenv.count; i++) { if (oflags & AU_OFLAG_XML) { fprintf(fp, ""); print_xml_string(fp, tok->tt.execenv.text[i], strlen(tok->tt.execenv.text[i])); fprintf(fp, ""); } else { print_delim(fp, del); print_string(fp, tok->tt.execenv.text[i], strlen(tok->tt.execenv.text[i])); } } if (oflags & AU_OFLAG_XML) close_tag(fp, tok->id); } /* * seconds of time 4 bytes * milliseconds of time 4 bytes * file name len 2 bytes * file pathname N bytes + 1 terminating NULL byte */ static int fetch_file_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.file.s, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.file.ms, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT16(buf, len, tok->tt.file.len, tok->len, err); if (err) return (-1); SET_PTR((char*)buf, len, tok->tt.file.name, tok->tt.file.len, tok->len, err); if (err) return (-1); return (0); } static void print_file_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "file", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "time"); print_sec32(fp, tok->tt.file.s, oflags); close_attr(fp); open_attr(fp, "msec"); print_msec32(fp, tok->tt.file.ms, oflags); close_attr(fp); fprintf(fp, ">"); print_string(fp, tok->tt.file.name, tok->tt.file.len); close_tag(fp, tok->id); } else { print_delim(fp, del); print_sec32(fp, tok->tt.file.s, oflags); print_delim(fp, del); print_msec32(fp, tok->tt.file.ms, oflags); print_delim(fp, del); print_string(fp, tok->tt.file.name, tok->tt.file.len); } } /* * number groups 2 bytes * group list count * 4 bytes */ static int fetch_newgroups_tok(tokenstr_t *tok, u_char *buf, int len) { int i; int err = 0; READ_TOKEN_U_INT16(buf, len, tok->tt.grps.no, tok->len, err); if (err) return (-1); for (i = 0; itt.grps.no; i++) { READ_TOKEN_U_INT32(buf, len, tok->tt.grps.list[i], tok->len, err); if (err) return (-1); } return (0); } static void print_newgroups_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { int i; print_tok_type(fp, tok->id, "group", oflags); for (i = 0; i < tok->tt.grps.no; i++) { if (oflags & AU_OFLAG_XML) { fprintf(fp, ""); print_group(fp, tok->tt.grps.list[i], oflags); fprintf(fp, ""); close_tag(fp, tok->id); } else { print_delim(fp, del); print_group(fp, tok->tt.grps.list[i], oflags); } } } /* * Internet addr 4 bytes */ static int fetch_inaddr_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_BYTES(buf, len, &tok->tt.inaddr.addr, sizeof(uint32_t), tok->len, err); if (err) return (-1); return (0); } static void print_inaddr_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "ip addr", oflags); if (oflags & AU_OFLAG_XML) { print_ip_address(fp, tok->tt.inaddr.addr); close_tag(fp, tok->id); } else { print_delim(fp, del); print_ip_address(fp, tok->tt.inaddr.addr); } } /* * type 4 bytes * address 16 bytes */ static int fetch_inaddr_ex_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.inaddr_ex.type, tok->len, err); if (err) return (-1); if (tok->tt.inaddr_ex.type == AU_IPv4) { READ_TOKEN_BYTES(buf, len, &tok->tt.inaddr_ex.addr[0], sizeof(tok->tt.inaddr_ex.addr[0]), tok->len, err); if (err) return (-1); } else if (tok->tt.inaddr_ex.type == AU_IPv6) { READ_TOKEN_BYTES(buf, len, tok->tt.inaddr_ex.addr, sizeof(tok->tt.inaddr_ex.addr), tok->len, err); if (err) return (-1); } else return (-1); return (0); } static void print_inaddr_ex_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "ip addr ex", oflags); if (oflags & AU_OFLAG_XML) { print_ip_ex_address(fp, tok->tt.inaddr_ex.type, tok->tt.inaddr_ex.addr); close_tag(fp, tok->id); } else { print_delim(fp, del); print_ip_ex_address(fp, tok->tt.inaddr_ex.type, tok->tt.inaddr_ex.addr); } } /* * ip header 20 bytes */ static int fetch_ip_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_CHAR(buf, len, tok->tt.ip.version, tok->len, err); if (err) return (-1); READ_TOKEN_U_CHAR(buf, len, tok->tt.ip.tos, tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.ip.len, sizeof(uint16_t), tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.ip.id, sizeof(uint16_t), tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.ip.offset, sizeof(uint16_t), tok->len, err); if (err) return (-1); READ_TOKEN_U_CHAR(buf, len, tok->tt.ip.ttl, tok->len, err); if (err) return (-1); READ_TOKEN_U_CHAR(buf, len, tok->tt.ip.prot, tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.ip.chksm, sizeof(uint16_t), tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.ip.src, sizeof(tok->tt.ip.src), tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.ip.dest, sizeof(tok->tt.ip.dest), tok->len, err); if (err) return (-1); return (0); } static void print_ip_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "ip", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "version"); print_mem(fp, (u_char *)(&tok->tt.ip.version), sizeof(u_char)); close_attr(fp); open_attr(fp, "service_type"); print_mem(fp, (u_char *)(&tok->tt.ip.tos), sizeof(u_char)); close_attr(fp); open_attr(fp, "len"); print_2_bytes(fp, ntohs(tok->tt.ip.len), "%u"); close_attr(fp); open_attr(fp, "id"); print_2_bytes(fp, ntohs(tok->tt.ip.id), "%u"); close_attr(fp); open_attr(fp, "offset"); print_2_bytes(fp, ntohs(tok->tt.ip.offset), "%u"); close_attr(fp); open_attr(fp, "time_to_live"); print_mem(fp, (u_char *)(&tok->tt.ip.ttl), sizeof(u_char)); close_attr(fp); open_attr(fp, "protocol"); print_mem(fp, (u_char *)(&tok->tt.ip.prot), sizeof(u_char)); close_attr(fp); open_attr(fp, "cksum"); print_2_bytes(fp, ntohs(tok->tt.ip.chksm), "%u"); close_attr(fp); open_attr(fp, "src_addr"); print_ip_address(fp, tok->tt.ip.src); close_attr(fp); open_attr(fp, "dest_addr"); print_ip_address(fp, tok->tt.ip.dest); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_mem(fp, (u_char *)(&tok->tt.ip.version), sizeof(u_char)); print_delim(fp, del); print_mem(fp, (u_char *)(&tok->tt.ip.tos), sizeof(u_char)); print_delim(fp, del); print_2_bytes(fp, ntohs(tok->tt.ip.len), "%u"); print_delim(fp, del); print_2_bytes(fp, ntohs(tok->tt.ip.id), "%u"); print_delim(fp, del); print_2_bytes(fp, ntohs(tok->tt.ip.offset), "%u"); print_delim(fp, del); print_mem(fp, (u_char *)(&tok->tt.ip.ttl), sizeof(u_char)); print_delim(fp, del); print_mem(fp, (u_char *)(&tok->tt.ip.prot), sizeof(u_char)); print_delim(fp, del); print_2_bytes(fp, ntohs(tok->tt.ip.chksm), "%u"); print_delim(fp, del); print_ip_address(fp, tok->tt.ip.src); print_delim(fp, del); print_ip_address(fp, tok->tt.ip.dest); } } /* * object ID type 1 byte * Object ID 4 bytes */ static int fetch_ipc_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_CHAR(buf, len, tok->tt.ipc.type, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.ipc.id, tok->len, err); if (err) return (-1); return (0); } static void print_ipc_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "IPC", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "ipc-type"); print_ipctype(fp, tok->tt.ipc.type, oflags); close_attr(fp); open_attr(fp, "ipc-id"); print_4_bytes(fp, tok->tt.ipc.id, "%u"); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_ipctype(fp, tok->tt.ipc.type, oflags); print_delim(fp, del); print_4_bytes(fp, tok->tt.ipc.id, "%u"); } } /* * owner user id 4 bytes * owner group id 4 bytes * creator user id 4 bytes * creator group id 4 bytes * access mode 4 bytes * slot seq 4 bytes * key 4 bytes */ static int fetch_ipcperm_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.uid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.gid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.puid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.pgid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.mode, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.seq, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.ipcperm.key, tok->len, err); if (err) return (-1); return (0); } static void print_ipcperm_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "IPC perm", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "uid"); print_user(fp, tok->tt.ipcperm.uid, oflags); close_attr(fp); open_attr(fp, "gid"); print_group(fp, tok->tt.ipcperm.gid, oflags); close_attr(fp); open_attr(fp, "creator-uid"); print_user(fp, tok->tt.ipcperm.puid, oflags); close_attr(fp); open_attr(fp, "creator-gid"); print_group(fp, tok->tt.ipcperm.pgid, oflags); close_attr(fp); open_attr(fp, "mode"); print_4_bytes(fp, tok->tt.ipcperm.mode, "%o"); close_attr(fp); open_attr(fp, "seq"); print_4_bytes(fp, tok->tt.ipcperm.seq, "%u"); close_attr(fp); open_attr(fp, "key"); print_4_bytes(fp, tok->tt.ipcperm.key, "%u"); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_user(fp, tok->tt.ipcperm.uid, oflags); print_delim(fp, del); print_group(fp, tok->tt.ipcperm.gid, oflags); print_delim(fp, del); print_user(fp, tok->tt.ipcperm.puid, oflags); print_delim(fp, del); print_group(fp, tok->tt.ipcperm.pgid, oflags); print_delim(fp, del); print_4_bytes(fp, tok->tt.ipcperm.mode, "%o"); print_delim(fp, del); print_4_bytes(fp, tok->tt.ipcperm.seq, "%u"); print_delim(fp, del); print_4_bytes(fp, tok->tt.ipcperm.key, "%u"); } } /* * port Ip address 2 bytes */ static int fetch_iport_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_BYTES(buf, len, &tok->tt.iport.port, sizeof(uint16_t), tok->len, err); if (err) return (-1); return (0); } static void print_iport_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "ip port", oflags); if (oflags & AU_OFLAG_XML) { print_2_bytes(fp, ntohs(tok->tt.iport.port), "%#x"); close_tag(fp, tok->id); } else { print_delim(fp, del); print_2_bytes(fp, ntohs(tok->tt.iport.port), "%#x"); } } /* * size 2 bytes * data size bytes */ static int fetch_opaque_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT16(buf, len, tok->tt.opaque.size, tok->len, err); if (err) return (-1); SET_PTR((char*)buf, len, tok->tt.opaque.data, tok->tt.opaque.size, tok->len, err); if (err) return (-1); return (0); } static void print_opaque_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "opaque", oflags); if (oflags & AU_OFLAG_XML) { print_mem(fp, (u_char*)tok->tt.opaque.data, tok->tt.opaque.size); close_tag(fp, tok->id); } else { print_delim(fp, del); print_2_bytes(fp, tok->tt.opaque.size, "%u"); print_delim(fp, del); print_mem(fp, (u_char*)tok->tt.opaque.data, tok->tt.opaque.size); } } /* * size 2 bytes * data size bytes */ static int fetch_path_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT16(buf, len, tok->tt.path.len, tok->len, err); if (err) return (-1); SET_PTR((char*)buf, len, tok->tt.path.path, tok->tt.path.len, tok->len, err); if (err) return (-1); return (0); } static void print_path_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "path", oflags); if (oflags & AU_OFLAG_XML) { print_string(fp, tok->tt.path.path, tok->tt.path.len); close_tag(fp, tok->id); } else { print_delim(fp, del); print_string(fp, tok->tt.path.path, tok->tt.path.len); } } /* * token ID 1 byte * audit ID 4 bytes * euid 4 bytes * egid 4 bytes * ruid 4 bytes * rgid 4 bytes * pid 4 bytes * sessid 4 bytes * terminal ID * portid 4 bytes * machine id 4 bytes */ static int fetch_process32_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.auid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.euid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.egid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.ruid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.rgid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.pid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.sid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc32.tid.port, tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.proc32.tid.addr, sizeof(tok->tt.proc32.tid.addr), tok->len, err); if (err) return (-1); return (0); } static void print_process32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "process", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "audit-uid"); print_user(fp, tok->tt.proc32.auid, oflags); close_attr(fp); open_attr(fp, "uid"); print_user(fp, tok->tt.proc32.euid, oflags); close_attr(fp); open_attr(fp, "gid"); print_group(fp, tok->tt.proc32.egid, oflags); close_attr(fp); open_attr(fp, "ruid"); print_user(fp, tok->tt.proc32.ruid, oflags); close_attr(fp); open_attr(fp, "rgid"); print_group(fp, tok->tt.proc32.rgid, oflags); close_attr(fp); open_attr(fp, "pid"); print_4_bytes(fp, tok->tt.proc32.pid, "%u"); close_attr(fp); open_attr(fp, "sid"); print_4_bytes(fp, tok->tt.proc32.sid, "%u"); close_attr(fp); open_attr(fp, "tid"); print_4_bytes(fp, tok->tt.proc32.tid.port, "%u"); print_ip_address(fp, tok->tt.proc32.tid.addr); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_user(fp, tok->tt.proc32.auid, oflags); print_delim(fp, del); print_user(fp, tok->tt.proc32.euid, oflags); print_delim(fp, del); print_group(fp, tok->tt.proc32.egid, oflags); print_delim(fp, del); print_user(fp, tok->tt.proc32.ruid, oflags); print_delim(fp, del); print_group(fp, tok->tt.proc32.rgid, oflags); print_delim(fp, del); print_4_bytes(fp, tok->tt.proc32.pid, "%u"); print_delim(fp, del); print_4_bytes(fp, tok->tt.proc32.sid, "%u"); print_delim(fp, del); print_4_bytes(fp, tok->tt.proc32.tid.port, "%u"); print_delim(fp, del); print_ip_address(fp, tok->tt.proc32.tid.addr); } } /* * token ID 1 byte * audit ID 4 bytes * euid 4 bytes * egid 4 bytes * ruid 4 bytes * rgid 4 bytes * pid 4 bytes * sessid 4 bytes * terminal ID * portid 8 bytes * machine id 4 bytes */ static int fetch_process64_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.proc64.auid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc64.euid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc64.egid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc64.ruid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc64.rgid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc64.pid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc64.sid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT64(buf, len, tok->tt.proc64.tid.port, tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.proc64.tid.addr, sizeof(tok->tt.proc64.tid.addr), tok->len, err); if (err) return (-1); return (0); } static void print_process64_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "process", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "audit-uid"); print_user(fp, tok->tt.proc64.auid, oflags); close_attr(fp); open_attr(fp, "uid"); print_user(fp, tok->tt.proc64.euid, oflags); close_attr(fp); open_attr(fp, "gid"); print_group(fp, tok->tt.proc64.egid, oflags); close_attr(fp); open_attr(fp, "ruid"); print_user(fp, tok->tt.proc64.ruid, oflags); close_attr(fp); open_attr(fp, "rgid"); print_group(fp, tok->tt.proc64.rgid, oflags); close_attr(fp); open_attr(fp, "pid"); print_4_bytes(fp, tok->tt.proc64.pid, "%u"); close_attr(fp); open_attr(fp, "sid"); print_4_bytes(fp, tok->tt.proc64.sid, "%u"); close_attr(fp); open_attr(fp, "tid"); print_8_bytes(fp, tok->tt.proc64.tid.port, "%llu"); print_ip_address(fp, tok->tt.proc64.tid.addr); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_user(fp, tok->tt.proc64.auid, oflags); print_delim(fp, del); print_user(fp, tok->tt.proc64.euid, oflags); print_delim(fp, del); print_group(fp, tok->tt.proc64.egid, oflags); print_delim(fp, del); print_user(fp, tok->tt.proc64.ruid, oflags); print_delim(fp, del); print_group(fp, tok->tt.proc64.rgid, oflags); print_delim(fp, del); print_4_bytes(fp, tok->tt.proc64.pid, "%u"); print_delim(fp, del); print_4_bytes(fp, tok->tt.proc64.sid, "%u"); print_delim(fp, del); print_8_bytes(fp, tok->tt.proc64.tid.port, "%llu"); print_delim(fp, del); print_ip_address(fp, tok->tt.proc64.tid.addr); } } /* * token ID 1 byte * audit ID 4 bytes * effective user ID 4 bytes * effective group ID 4 bytes * real user ID 4 bytes * real group ID 4 bytes * process ID 4 bytes * session ID 4 bytes * terminal ID * port ID 4 bytes * address type-len 4 bytes * machine address 16 bytes */ static int fetch_process32ex_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.auid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.euid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.egid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.ruid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.rgid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.pid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.sid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.tid.port, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc32_ex.tid.type, tok->len, err); if (err) return (-1); if (tok->tt.proc32_ex.tid.type == AU_IPv4) { READ_TOKEN_BYTES(buf, len, &tok->tt.proc32_ex.tid.addr[0], sizeof(tok->tt.proc32_ex.tid.addr[0]), tok->len, err); if (err) return (-1); } else if (tok->tt.proc32_ex.tid.type == AU_IPv6) { READ_TOKEN_BYTES(buf, len, tok->tt.proc32_ex.tid.addr, sizeof(tok->tt.proc32_ex.tid.addr), tok->len, err); if (err) return (-1); } else return (-1); return (0); } static void print_process32ex_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "process_ex", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "audit-uid"); print_user(fp, tok->tt.proc32_ex.auid, oflags); close_attr(fp); open_attr(fp, "uid"); print_user(fp, tok->tt.proc32_ex.euid, oflags); close_attr(fp); open_attr(fp, "gid"); print_group(fp, tok->tt.proc32_ex.egid, oflags); close_attr(fp); open_attr(fp, "ruid"); print_user(fp, tok->tt.proc32_ex.ruid, oflags); close_attr(fp); open_attr(fp, "rgid"); print_group(fp, tok->tt.proc32_ex.rgid, oflags); close_attr(fp); open_attr(fp, "pid"); print_4_bytes(fp, tok->tt.proc32_ex.pid, "%u"); close_attr(fp); open_attr(fp, "sid"); print_4_bytes(fp, tok->tt.proc32_ex.sid, "%u"); close_attr(fp); open_attr(fp, "tid"); print_4_bytes(fp, tok->tt.proc32_ex.tid.port, "%u"); print_ip_ex_address(fp, tok->tt.proc32_ex.tid.type, tok->tt.proc32_ex.tid.addr); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_user(fp, tok->tt.proc32_ex.auid, oflags); print_delim(fp, del); print_user(fp, tok->tt.proc32_ex.euid, oflags); print_delim(fp, del); print_group(fp, tok->tt.proc32_ex.egid, oflags); print_delim(fp, del); print_user(fp, tok->tt.proc32_ex.ruid, oflags); print_delim(fp, del); print_group(fp, tok->tt.proc32_ex.rgid, oflags); print_delim(fp, del); print_4_bytes(fp, tok->tt.proc32_ex.pid, "%u"); print_delim(fp, del); print_4_bytes(fp, tok->tt.proc32_ex.sid, "%u"); print_delim(fp, del); print_4_bytes(fp, tok->tt.proc32_ex.tid.port, "%u"); print_delim(fp, del); print_ip_ex_address(fp, tok->tt.proc32_ex.tid.type, tok->tt.proc32_ex.tid.addr); } } /* * token ID 1 byte * audit ID 4 bytes * effective user ID 4 bytes * effective group ID 4 bytes * real user ID 4 bytes * real group ID 4 bytes * process ID 4 bytes * session ID 4 bytes * terminal ID * port ID 8 bytes * address type-len 4 bytes * machine address 16 bytes */ static int fetch_process64ex_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.proc64_ex.auid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc64_ex.euid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc64_ex.egid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc64_ex.ruid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc64_ex.rgid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc64_ex.pid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc64_ex.sid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT64(buf, len, tok->tt.proc64_ex.tid.port, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.proc64_ex.tid.type, tok->len, err); if (err) return (-1); if (tok->tt.proc64_ex.tid.type == AU_IPv4) { READ_TOKEN_BYTES(buf, len, &tok->tt.proc64_ex.tid.addr[0], sizeof(tok->tt.proc64_ex.tid.addr[0]), tok->len, err); if (err) return (-1); } else if (tok->tt.proc64_ex.tid.type == AU_IPv6) { READ_TOKEN_BYTES(buf, len, tok->tt.proc64_ex.tid.addr, sizeof(tok->tt.proc64_ex.tid.addr), tok->len, err); if (err) return (-1); } else return (-1); return (0); } static void print_process64ex_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "process_ex", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "audit-uid"); print_user(fp, tok->tt.proc64_ex.auid, oflags); close_attr(fp); open_attr(fp, "uid"); print_user(fp, tok->tt.proc64_ex.euid, oflags); close_attr(fp); open_attr(fp, "gid"); print_group(fp, tok->tt.proc64_ex.egid, oflags); close_attr(fp); open_attr(fp, "ruid"); print_user(fp, tok->tt.proc64_ex.ruid, oflags); close_attr(fp); open_attr(fp, "rgid"); print_group(fp, tok->tt.proc64_ex.rgid, oflags); close_attr(fp); open_attr(fp, "pid"); print_4_bytes(fp, tok->tt.proc64_ex.pid, "%u"); close_attr(fp); open_attr(fp, "sid"); print_4_bytes(fp, tok->tt.proc64_ex.sid, "%u"); close_attr(fp); open_attr(fp, "tid"); print_8_bytes(fp, tok->tt.proc64_ex.tid.port, "%llu"); print_ip_ex_address(fp, tok->tt.proc64_ex.tid.type, tok->tt.proc64_ex.tid.addr); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_user(fp, tok->tt.proc64_ex.auid, oflags); print_delim(fp, del); print_user(fp, tok->tt.proc64_ex.euid, oflags); print_delim(fp, del); print_group(fp, tok->tt.proc64_ex.egid, oflags); print_delim(fp, del); print_user(fp, tok->tt.proc64_ex.ruid, oflags); print_delim(fp, del); print_group(fp, tok->tt.proc64_ex.rgid, oflags); print_delim(fp, del); print_4_bytes(fp, tok->tt.proc64_ex.pid, "%u"); print_delim(fp, del); print_4_bytes(fp, tok->tt.proc64_ex.sid, "%u"); print_delim(fp, del); print_8_bytes(fp, tok->tt.proc64_ex.tid.port, "%llu"); print_delim(fp, del); print_ip_ex_address(fp, tok->tt.proc64_ex.tid.type, tok->tt.proc64_ex.tid.addr); } } /* * errno 1 byte * return value 4 bytes */ static int fetch_return32_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_CHAR(buf, len, tok->tt.ret32.status, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.ret32.ret, tok->len, err); if (err) return (-1); return (0); } static void print_return32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "return", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp ,"errval"); print_retval(fp, tok->tt.ret32.status, oflags); close_attr(fp); open_attr(fp, "retval"); print_4_bytes(fp, tok->tt.ret32.ret, "%u"); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_retval(fp, tok->tt.ret32.status, oflags); print_delim(fp, del); print_4_bytes(fp, tok->tt.ret32.ret, "%u"); } } static int fetch_return64_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_CHAR(buf, len, tok->tt.ret64.err, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT64(buf, len, tok->tt.ret64.val, tok->len, err); if (err) return (-1); return (0); } static void print_return64_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "return", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "errval"); print_retval(fp, tok->tt.ret64.err, oflags); close_attr(fp); open_attr(fp, "retval"); print_8_bytes(fp, tok->tt.ret64.val, "%lld"); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_retval(fp, tok->tt.ret64.err, oflags); print_delim(fp, del); print_8_bytes(fp, tok->tt.ret64.val, "%lld"); } } /* * seq 4 bytes */ static int fetch_seq_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.seq.seqno, tok->len, err); if (err) return (-1); return (0); } static void print_seq_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "sequence", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "seq-num"); print_4_bytes(fp, tok->tt.seq.seqno, "%u"); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_4_bytes(fp, tok->tt.seq.seqno, "%u"); } } /* * socket family 2 bytes * local port 2 bytes * socket address 4 bytes */ static int fetch_sock_inet32_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT16(buf, len, tok->tt.sockinet_ex32.family, tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.sockinet_ex32.port, sizeof(uint16_t), tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.sockinet_ex32.addr, sizeof(tok->tt.sockinet_ex32.addr[0]), tok->len, err); if (err) return (-1); return (0); } static void print_sock_inet32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "socket-inet", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "type"); print_2_bytes(fp, tok->tt.sockinet_ex32.family, "%u"); close_attr(fp); open_attr(fp, "port"); print_2_bytes(fp, ntohs(tok->tt.sockinet_ex32.port), "%u"); close_attr(fp); open_attr(fp, "addr"); print_ip_address(fp, tok->tt.sockinet_ex32.addr[0]); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_2_bytes(fp, tok->tt.sockinet_ex32.family, "%u"); print_delim(fp, del); print_2_bytes(fp, ntohs(tok->tt.sockinet_ex32.port), "%u"); print_delim(fp, del); print_ip_address(fp, tok->tt.sockinet_ex32.addr[0]); } } /* * socket family 2 bytes * local port 2 bytes * socket address 16 bytes */ static int fetch_sock_inet128_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT16(buf, len, tok->tt.sockinet_ex32.family, tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.sockinet_ex32.port, sizeof(uint16_t), tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.sockinet_ex32.addr, sizeof(tok->tt.sockinet_ex32.addr), tok->len, err); if (err) return (-1); return (0); } static void print_sock_inet128_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "socket-inet6", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "type"); print_2_bytes(fp, tok->tt.sockinet_ex32.family, "%u"); close_attr(fp); open_attr(fp, "port"); print_2_bytes(fp, ntohs(tok->tt.sockinet_ex32.port), "%u"); close_attr(fp); open_attr(fp, "addr"); print_ip_ex_address(fp, AU_IPv6, tok->tt.sockinet_ex32.addr); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_2_bytes(fp, tok->tt.sockinet_ex32.family, "%u"); print_delim(fp, del); print_2_bytes(fp, ntohs(tok->tt.sockinet_ex32.port), "%u"); print_delim(fp, del); print_ip_ex_address(fp, AU_IPv6, tok->tt.sockinet_ex32.addr); } } /* * socket family 2 bytes * path (up to) 104 bytes + NULL (NULL terminated string). */ static int fetch_sock_unix_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; u_char *p; int slen; READ_TOKEN_U_INT16(buf, len, tok->tt.sockunix.family, tok->len, err); if (err) return (-1); /* slen = strnlen((buf + tok->len), 104) + 1; */ p = (u_char *)memchr((const void *)(buf + tok->len), '\0', 104); slen = (p ? (int)(p - (buf + tok->len)) : 104) + 1; READ_TOKEN_BYTES(buf, len, tok->tt.sockunix.path, slen, tok->len, err); if (err) return (-1); return (0); } static void print_sock_unix_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "socket-unix", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "type"); print_2_bytes(fp, tok->tt.sockunix.family, "%u"); close_attr(fp); open_attr(fp, "port"); close_attr(fp); open_attr(fp, "addr"); print_string(fp, tok->tt.sockunix.path, strlen(tok->tt.sockunix.path)); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_2_bytes(fp, tok->tt.sockunix.family, "%u"); print_delim(fp, del); print_string(fp, tok->tt.sockunix.path, strlen(tok->tt.sockunix.path)); } } /* * socket type 2 bytes * local port 2 bytes * local address 4 bytes * remote port 2 bytes * remote address 4 bytes */ static int fetch_socket_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT16(buf, len, tok->tt.socket.type, tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.socket.l_port, sizeof(uint16_t), tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.socket.l_addr, sizeof(tok->tt.socket.l_addr), tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.socket.r_port, sizeof(uint16_t), tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.socket.l_addr, sizeof(tok->tt.socket.r_addr), tok->len, err); if (err) return (-1); return (0); } static void print_socket_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "socket", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "sock_type"); print_2_bytes(fp, tok->tt.socket.type, "%u"); close_attr(fp); open_attr(fp, "lport"); print_2_bytes(fp, ntohs(tok->tt.socket.l_port), "%u"); close_attr(fp); open_attr(fp, "laddr"); print_ip_address(fp, tok->tt.socket.l_addr); close_attr(fp); open_attr(fp, "fport"); print_2_bytes(fp, ntohs(tok->tt.socket.r_port), "%u"); close_attr(fp); open_attr(fp, "faddr"); print_ip_address(fp, tok->tt.socket.r_addr); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_2_bytes(fp, tok->tt.socket.type, "%u"); print_delim(fp, del); print_2_bytes(fp, ntohs(tok->tt.socket.l_port), "%u"); print_delim(fp, del); print_ip_address(fp, tok->tt.socket.l_addr); print_delim(fp, del); print_2_bytes(fp, ntohs(tok->tt.socket.r_port), "%u"); print_delim(fp, del); print_ip_address(fp, tok->tt.socket.r_addr); } } /* * audit ID 4 bytes * euid 4 bytes * egid 4 bytes * ruid 4 bytes * rgid 4 bytes * pid 4 bytes * sessid 4 bytes * terminal ID * portid 4 bytes/8 bytes (32-bit/64-bit value) * machine id 4 bytes */ static int fetch_subject32_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.auid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.euid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.egid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.ruid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.rgid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.pid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.sid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj32.tid.port, tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.subj32.tid.addr, sizeof(tok->tt.subj32.tid.addr), tok->len, err); if (err) return (-1); return (0); } static void print_subject32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "subject", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "audit-uid"); print_user(fp, tok->tt.subj32.auid, oflags); close_attr(fp); open_attr(fp, "uid"); print_user(fp, tok->tt.subj32.euid, oflags); close_attr(fp); open_attr(fp, "gid"); print_group(fp, tok->tt.subj32.egid, oflags); close_attr(fp); open_attr(fp, "ruid"); print_user(fp, tok->tt.subj32.ruid, oflags); close_attr(fp); open_attr(fp, "rgid"); print_group(fp, tok->tt.subj32.rgid, oflags); close_attr(fp); open_attr(fp,"pid"); print_4_bytes(fp, tok->tt.subj32.pid, "%u"); close_attr(fp); open_attr(fp,"sid"); print_4_bytes(fp, tok->tt.subj32.sid, "%u"); close_attr(fp); open_attr(fp,"tid"); print_4_bytes(fp, tok->tt.subj32.tid.port, "%u "); print_ip_address(fp, tok->tt.subj32.tid.addr); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_user(fp, tok->tt.subj32.auid, oflags); print_delim(fp, del); print_user(fp, tok->tt.subj32.euid, oflags); print_delim(fp, del); print_group(fp, tok->tt.subj32.egid, oflags); print_delim(fp, del); print_user(fp, tok->tt.subj32.ruid, oflags); print_delim(fp, del); print_group(fp, tok->tt.subj32.rgid, oflags); print_delim(fp, del); print_4_bytes(fp, tok->tt.subj32.pid, "%u"); print_delim(fp, del); print_4_bytes(fp, tok->tt.subj32.sid, "%u"); print_delim(fp, del); print_4_bytes(fp, tok->tt.subj32.tid.port, "%u"); print_delim(fp, del); print_ip_address(fp, tok->tt.subj32.tid.addr); } } static void print_upriv_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "use of privilege", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "status"); if (tok->tt.priv.sorf) (void) fprintf(fp, "successful use of priv"); else (void) fprintf(fp, "failed use of priv"); close_attr(fp); open_attr(fp, "name"); print_string(fp, tok->tt.priv.priv, tok->tt.priv.privstrlen); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); if (tok->tt.priv.sorf) (void) fprintf(fp, "successful use of priv"); else (void) fprintf(fp, "failed use of priv"); print_delim(fp, del); print_string(fp, tok->tt.priv.priv, tok->tt.priv.privstrlen); } } /* * status 1 byte * privstrlen 2 bytes * priv N bytes + 1 (\0 byte) */ static int fetch_priv_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_CHAR(buf, len, tok->tt.priv.sorf, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT16(buf, len, tok->tt.priv.privstrlen, tok->len, err); if (err) return (-1); SET_PTR((char *)buf, len, tok->tt.priv.priv, tok->tt.priv.privstrlen, tok->len, err); if (err) return (-1); return (0); } /* * privtstrlen 1 byte * privtstr N bytes + 1 * privstrlen 1 byte * privstr N bytes + 1 */ static int fetch_privset_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT16(buf, len, tok->tt.privset.privtstrlen, tok->len, err); if (err) return (-1); SET_PTR((char *)buf, len, tok->tt.privset.privtstr, tok->tt.privset.privtstrlen, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT16(buf, len, tok->tt.privset.privstrlen, tok->len, err); if (err) return (-1); SET_PTR((char *)buf, len, tok->tt.privset.privstr, tok->tt.privset.privstrlen, tok->len, err); if (err) return (-1); return (0); } static void print_privset_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "privilege", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "type"); print_string(fp, tok->tt.privset.privtstr, tok->tt.privset.privtstrlen); close_attr(fp); open_attr(fp, "priv"); print_string(fp, tok->tt.privset.privstr, tok->tt.privset.privstrlen); close_attr(fp); } else { print_delim(fp, del); print_string(fp, tok->tt.privset.privtstr, tok->tt.privset.privtstrlen); print_delim(fp, del); print_string(fp, tok->tt.privset.privstr, tok->tt.privset.privstrlen); } } /* * audit ID 4 bytes * euid 4 bytes * egid 4 bytes * ruid 4 bytes * rgid 4 bytes * pid 4 bytes * sessid 4 bytes * terminal ID * portid 4 bytes/8 bytes (32-bit/64-bit value) * machine id 4 bytes */ static int fetch_subject64_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.auid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.euid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.egid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.ruid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.rgid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.pid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj64.sid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT64(buf, len, tok->tt.subj64.tid.port, tok->len, err); if (err) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.subj64.tid.addr, sizeof(tok->tt.subj64.tid.addr), tok->len, err); if (err) return (-1); return (0); } static void print_subject64_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "subject", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "audit-uid"); print_user(fp, tok->tt.subj64.auid, oflags); close_attr(fp); open_attr(fp, "uid"); print_user(fp, tok->tt.subj64.euid, oflags); close_attr(fp); open_attr(fp, "gid"); print_group(fp, tok->tt.subj64.egid, oflags); close_attr(fp); open_attr(fp, "ruid"); print_user(fp, tok->tt.subj64.ruid, oflags); close_attr(fp); open_attr(fp, "rgid"); print_group(fp, tok->tt.subj64.rgid, oflags); close_attr(fp); open_attr(fp, "pid"); print_4_bytes(fp, tok->tt.subj64.pid, "%u"); close_attr(fp); open_attr(fp, "sid"); print_4_bytes(fp, tok->tt.subj64.sid, "%u"); close_attr(fp); open_attr(fp, "tid"); print_8_bytes(fp, tok->tt.subj64.tid.port, "%llu"); print_ip_address(fp, tok->tt.subj64.tid.addr); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_user(fp, tok->tt.subj64.auid, oflags); print_delim(fp, del); print_user(fp, tok->tt.subj64.euid, oflags); print_delim(fp, del); print_group(fp, tok->tt.subj64.egid, oflags); print_delim(fp, del); print_user(fp, tok->tt.subj64.ruid, oflags); print_delim(fp, del); print_group(fp, tok->tt.subj64.rgid, oflags); print_delim(fp, del); print_4_bytes(fp, tok->tt.subj64.pid, "%u"); print_delim(fp, del); print_4_bytes(fp, tok->tt.subj64.sid, "%u"); print_delim(fp, del); print_8_bytes(fp, tok->tt.subj64.tid.port, "%llu"); print_delim(fp, del); print_ip_address(fp, tok->tt.subj64.tid.addr); } } /* * audit ID 4 bytes * euid 4 bytes * egid 4 bytes * ruid 4 bytes * rgid 4 bytes * pid 4 bytes * sessid 4 bytes * terminal ID * portid 4 bytes * type 4 bytes * machine id 16 bytes */ static int fetch_subject32ex_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.auid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.euid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.egid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.ruid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.rgid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.pid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.sid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.tid.port, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj32_ex.tid.type, tok->len, err); if (err) return (-1); if (tok->tt.subj32_ex.tid.type == AU_IPv4) { READ_TOKEN_BYTES(buf, len, &tok->tt.subj32_ex.tid.addr[0], sizeof(tok->tt.subj32_ex.tid.addr[0]), tok->len, err); if (err) return (-1); } else if (tok->tt.subj32_ex.tid.type == AU_IPv6) { READ_TOKEN_BYTES(buf, len, tok->tt.subj32_ex.tid.addr, sizeof(tok->tt.subj32_ex.tid.addr), tok->len, err); if (err) return (-1); } else return (-1); return (0); } static void print_subject32ex_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "subject_ex", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "audit-uid"); print_user(fp, tok->tt.subj32_ex.auid, oflags); close_attr(fp); open_attr(fp, "uid"); print_user(fp, tok->tt.subj32_ex.euid, oflags); close_attr(fp); open_attr(fp, "gid"); print_group(fp, tok->tt.subj32_ex.egid, oflags); close_attr(fp); open_attr(fp, "ruid"); print_user(fp, tok->tt.subj32_ex.ruid, oflags); close_attr(fp); open_attr(fp, "rgid"); print_group(fp, tok->tt.subj32_ex.rgid, oflags); close_attr(fp); open_attr(fp, "pid"); print_4_bytes(fp, tok->tt.subj32_ex.pid, "%u"); close_attr(fp); open_attr(fp, "sid"); print_4_bytes(fp, tok->tt.subj32_ex.sid, "%u"); close_attr(fp); open_attr(fp, "tid"); print_4_bytes(fp, tok->tt.subj32_ex.tid.port, "%u"); print_ip_ex_address(fp, tok->tt.subj32_ex.tid.type, tok->tt.subj32_ex.tid.addr); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_user(fp, tok->tt.subj32_ex.auid, oflags); print_delim(fp, del); print_user(fp, tok->tt.subj32_ex.euid, oflags); print_delim(fp, del); print_group(fp, tok->tt.subj32_ex.egid, oflags); print_delim(fp, del); print_user(fp, tok->tt.subj32_ex.ruid, oflags); print_delim(fp, del); print_group(fp, tok->tt.subj32_ex.rgid, oflags); print_delim(fp, del); print_4_bytes(fp, tok->tt.subj32_ex.pid, "%u"); print_delim(fp, del); print_4_bytes(fp, tok->tt.subj32_ex.sid, "%u"); print_delim(fp, del); print_4_bytes(fp, tok->tt.subj32_ex.tid.port, "%u"); print_delim(fp, del); print_ip_ex_address(fp, tok->tt.subj32_ex.tid.type, tok->tt.subj32_ex.tid.addr); } } /* * audit ID 4 bytes * euid 4 bytes * egid 4 bytes * ruid 4 bytes * rgid 4 bytes * pid 4 bytes * sessid 4 bytes * terminal ID * portid 8 bytes * type 4 bytes * machine id 16 bytes */ static int fetch_subject64ex_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT32(buf, len, tok->tt.subj64_ex.auid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj64_ex.euid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj64_ex.egid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj64_ex.ruid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj64_ex.rgid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj64_ex.pid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj64_ex.sid, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT64(buf, len, tok->tt.subj64_ex.tid.port, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT32(buf, len, tok->tt.subj64_ex.tid.type, tok->len, err); if (err) return (-1); if (tok->tt.subj64_ex.tid.type == AU_IPv4) { READ_TOKEN_BYTES(buf, len, &tok->tt.subj64_ex.tid.addr[0], sizeof(tok->tt.subj64_ex.tid.addr[0]), tok->len, err); if (err) return (-1); } else if (tok->tt.subj64_ex.tid.type == AU_IPv6) { READ_TOKEN_BYTES(buf, len, tok->tt.subj64_ex.tid.addr, sizeof(tok->tt.subj64_ex.tid.addr), tok->len, err); if (err) return (-1); } else return (-1); return (0); } static void print_subject64ex_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "subject_ex", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "audit-uid"); print_user(fp, tok->tt.subj64_ex.auid, oflags); close_attr(fp); open_attr(fp, "uid"); print_user(fp, tok->tt.subj64_ex.euid, oflags); close_attr(fp); open_attr(fp, "gid"); print_group(fp, tok->tt.subj64_ex.egid, oflags); close_attr(fp); open_attr(fp, "ruid"); print_user(fp, tok->tt.subj64_ex.ruid, oflags); close_attr(fp); open_attr(fp, "rgid"); print_group(fp, tok->tt.subj64_ex.rgid, oflags); close_attr(fp); open_attr(fp, "pid"); print_4_bytes(fp, tok->tt.subj64_ex.pid, "%u"); close_attr(fp); open_attr(fp, "sid"); print_4_bytes(fp, tok->tt.subj64_ex.sid, "%u"); close_attr(fp); open_attr(fp, "tid"); print_8_bytes(fp, tok->tt.subj64_ex.tid.port, "%llu"); print_ip_ex_address(fp, tok->tt.subj64_ex.tid.type, tok->tt.subj64_ex.tid.addr); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_user(fp, tok->tt.subj64_ex.auid, oflags); print_delim(fp, del); print_user(fp, tok->tt.subj64_ex.euid, oflags); print_delim(fp, del); print_group(fp, tok->tt.subj64_ex.egid, oflags); print_delim(fp, del); print_user(fp, tok->tt.subj64_ex.ruid, oflags); print_delim(fp, del); print_group(fp, tok->tt.subj64_ex.rgid, oflags); print_delim(fp, del); print_4_bytes(fp, tok->tt.subj64_ex.pid, "%u"); print_delim(fp, del); print_4_bytes(fp, tok->tt.subj64_ex.sid, "%u"); print_delim(fp, del); print_8_bytes(fp, tok->tt.subj64_ex.tid.port, "%llu"); print_delim(fp, del); print_ip_ex_address(fp, tok->tt.subj64_ex.tid.type, tok->tt.subj64_ex.tid.addr); } } /* * size 2 bytes * data size bytes */ static int fetch_text_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT16(buf, len, tok->tt.text.len, tok->len, err); if (err) return (-1); SET_PTR((char*)buf, len, tok->tt.text.text, tok->tt.text.len, tok->len, err); if (err) return (-1); return (0); } static void print_text_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "text", oflags); if (oflags & AU_OFLAG_XML) { print_string(fp, tok->tt.text.text, tok->tt.text.len); close_tag(fp, tok->id); } else { print_delim(fp, del); print_string(fp, tok->tt.text.text, tok->tt.text.len); } } /* * socket domain 2 bytes * socket type 2 bytes * address type 2 bytes * local port 2 bytes * local Internet address 4/16 bytes * remote port 2 bytes * remote Internet address 4/16 bytes */ static int fetch_socketex32_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT16(buf, len, tok->tt.socket_ex32.domain, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT16(buf, len, tok->tt.socket_ex32.type, tok->len, err); if (err) return (-1); READ_TOKEN_U_INT16(buf, len, tok->tt.socket_ex32.atype, tok->len, err); if (err) return (-1); if (tok->tt.socket_ex32.atype != AU_IPv4 && tok->tt.socket_ex32.atype != AU_IPv6) return (-1); READ_TOKEN_BYTES(buf, len, &tok->tt.socket_ex32.l_port, sizeof(uint16_t), tok->len, err); if (err) return (-1); if (tok->tt.socket_ex32.atype == AU_IPv4) { READ_TOKEN_BYTES(buf, len, &tok->tt.socket_ex32.l_addr, sizeof(tok->tt.socket_ex32.l_addr[0]), tok->len, err); if (err) return (-1); } else { READ_TOKEN_BYTES(buf, len, &tok->tt.socket_ex32.l_addr, sizeof(tok->tt.socket_ex32.l_addr), tok->len, err); if (err) return (-1); } READ_TOKEN_BYTES(buf, len, &tok->tt.socket_ex32.r_port, sizeof(uint16_t), tok->len, err); if (err) return (-1); if (tok->tt.socket_ex32.atype == AU_IPv4) { READ_TOKEN_BYTES(buf, len, &tok->tt.socket_ex32.r_addr, sizeof(tok->tt.socket_ex32.r_addr[0]), tok->len, err); if (err) return (-1); } else { READ_TOKEN_BYTES(buf, len, &tok->tt.socket_ex32.r_addr, sizeof(tok->tt.socket_ex32.r_addr), tok->len, err); if (err) return (-1); } return (0); } static void print_socketex32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { /* * This print routine prints BSM constant space domains and socket * types rather than converting them. If we add string printers for * these constants in the future, we may want to call conversion * routines. */ print_tok_type(fp, tok->id, "socket", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "sock_dom"); print_2_bytes(fp, tok->tt.socket_ex32.domain, "%#x"); close_attr(fp); open_attr(fp, "sock_type"); print_2_bytes(fp, tok->tt.socket_ex32.type, "%#x"); close_attr(fp); open_attr(fp, "lport"); print_2_bytes(fp, ntohs(tok->tt.socket_ex32.l_port), "%#x"); close_attr(fp); open_attr(fp, "laddr"); print_ip_ex_address(fp, tok->tt.socket_ex32.atype, tok->tt.socket_ex32.l_addr); close_attr(fp); open_attr(fp, "faddr"); print_ip_ex_address(fp, tok->tt.socket_ex32.atype, tok->tt.socket_ex32.r_addr); close_attr(fp); open_attr(fp, "fport"); print_2_bytes(fp, ntohs(tok->tt.socket_ex32.r_port), "%#x"); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_2_bytes(fp, tok->tt.socket_ex32.domain, "%#x"); print_delim(fp, del); print_2_bytes(fp, tok->tt.socket_ex32.type, "%#x"); print_delim(fp, del); print_2_bytes(fp, ntohs(tok->tt.socket_ex32.l_port), "%#x"); print_delim(fp, del); print_ip_ex_address(fp, tok->tt.socket_ex32.atype, tok->tt.socket_ex32.l_addr); print_delim(fp, del); print_4_bytes(fp, ntohs(tok->tt.socket_ex32.r_port), "%#x"); print_delim(fp, del); print_ip_ex_address(fp, tok->tt.socket_ex32.atype, tok->tt.socket_ex32.r_addr); } } static int fetch_invalid_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; int recoversize; recoversize = len - (tok->len + AUDIT_TRAILER_SIZE); if (recoversize <= 0) return (-1); tok->tt.invalid.length = recoversize; SET_PTR((char*)buf, len, tok->tt.invalid.data, recoversize, tok->len, err); if (err) return (-1); return (0); } static void print_invalid_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { if (!(oflags & AU_OFLAG_XML)) { print_tok_type(fp, tok->id, "unknown", oflags); print_delim(fp, del); print_mem(fp, (u_char*)tok->tt.invalid.data, tok->tt.invalid.length); } } /* * size 2 bytes; * zonename size bytes; */ static int fetch_zonename_tok(tokenstr_t *tok, u_char *buf, int len) { int err = 0; READ_TOKEN_U_INT16(buf, len, tok->tt.zonename.len, tok->len, err); if (err) return (-1); SET_PTR((char *)buf, len, tok->tt.zonename.zonename, tok->tt.zonename.len, tok->len, err); if (err) return (-1); return (0); } static void print_zonename_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) { print_tok_type(fp, tok->id, "zone", oflags); if (oflags & AU_OFLAG_XML) { open_attr(fp, "name"); print_string(fp, tok->tt.zonename.zonename, tok->tt.zonename.len); close_attr(fp); close_tag(fp, tok->id); } else { print_delim(fp, del); print_string(fp, tok->tt.zonename.zonename, tok->tt.zonename.len); } } /* * Reads the token beginning at buf into tok. */ int au_fetch_tok(tokenstr_t *tok, u_char *buf, int len) { if (len <= 0) return (-1); tok->len = 1; tok->data = buf; tok->id = *buf; switch(tok->id) { case AUT_HEADER32: return (fetch_header32_tok(tok, buf, len)); case AUT_HEADER32_EX: return (fetch_header32_ex_tok(tok, buf, len)); case AUT_HEADER64: return (fetch_header64_tok(tok, buf, len)); case AUT_HEADER64_EX: return (fetch_header64_ex_tok(tok, buf, len)); case AUT_TRAILER: return (fetch_trailer_tok(tok, buf, len)); case AUT_ARG32: return (fetch_arg32_tok(tok, buf, len)); case AUT_ARG64: return (fetch_arg64_tok(tok, buf, len)); case AUT_ATTR32: return (fetch_attr32_tok(tok, buf, len)); case AUT_ATTR64: return (fetch_attr64_tok(tok, buf, len)); case AUT_EXIT: return (fetch_exit_tok(tok, buf, len)); case AUT_EXEC_ARGS: return (fetch_execarg_tok(tok, buf, len)); case AUT_EXEC_ENV: return (fetch_execenv_tok(tok, buf, len)); case AUT_OTHER_FILE32: return (fetch_file_tok(tok, buf, len)); case AUT_NEWGROUPS: return (fetch_newgroups_tok(tok, buf, len)); case AUT_IN_ADDR: return (fetch_inaddr_tok(tok, buf, len)); case AUT_IN_ADDR_EX: return (fetch_inaddr_ex_tok(tok, buf, len)); case AUT_IP: return (fetch_ip_tok(tok, buf, len)); case AUT_IPC: return (fetch_ipc_tok(tok, buf, len)); case AUT_IPC_PERM: return (fetch_ipcperm_tok(tok, buf, len)); case AUT_IPORT: return (fetch_iport_tok(tok, buf, len)); case AUT_OPAQUE: return (fetch_opaque_tok(tok, buf, len)); case AUT_PATH: return (fetch_path_tok(tok, buf, len)); case AUT_PROCESS32: return (fetch_process32_tok(tok, buf, len)); case AUT_PROCESS32_EX: return (fetch_process32ex_tok(tok, buf, len)); case AUT_PROCESS64: return (fetch_process64_tok(tok, buf, len)); case AUT_PROCESS64_EX: return (fetch_process64ex_tok(tok, buf, len)); case AUT_RETURN32: return (fetch_return32_tok(tok, buf, len)); case AUT_RETURN64: return (fetch_return64_tok(tok, buf, len)); case AUT_SEQ: return (fetch_seq_tok(tok, buf, len)); case AUT_SOCKET: return (fetch_socket_tok(tok, buf, len)); case AUT_SOCKINET32: return (fetch_sock_inet32_tok(tok, buf, len)); case AUT_SOCKUNIX: return (fetch_sock_unix_tok(tok, buf, len)); case AUT_SOCKINET128: return (fetch_sock_inet128_tok(tok, buf, len)); case AUT_SUBJECT32: return (fetch_subject32_tok(tok, buf, len)); case AUT_SUBJECT32_EX: return (fetch_subject32ex_tok(tok, buf, len)); case AUT_SUBJECT64: return (fetch_subject64_tok(tok, buf, len)); case AUT_SUBJECT64_EX: return (fetch_subject64ex_tok(tok, buf, len)); case AUT_TEXT: return (fetch_text_tok(tok, buf, len)); case AUT_SOCKET_EX: return (fetch_socketex32_tok(tok, buf, len)); case AUT_DATA: return (fetch_arb_tok(tok, buf, len)); case AUT_ZONENAME: return (fetch_zonename_tok(tok, buf, len)); case AUT_UPRIV: return (fetch_priv_tok(tok, buf, len)); case AUT_PRIV: return (fetch_privset_tok(tok, buf, len)); default: return (fetch_invalid_tok(tok, buf, len)); } } void au_print_flags_tok(FILE *outfp, tokenstr_t *tok, char *del, int oflags) { switch(tok->id) { case AUT_HEADER32: print_header32_tok(outfp, tok, del, oflags); return; case AUT_HEADER32_EX: print_header32_ex_tok(outfp, tok, del, oflags); return; case AUT_HEADER64: print_header64_tok(outfp, tok, del, oflags); return; case AUT_HEADER64_EX: print_header64_ex_tok(outfp, tok, del, oflags); return; case AUT_TRAILER: print_trailer_tok(outfp, tok, del, oflags); return; case AUT_ARG32: print_arg32_tok(outfp, tok, del, oflags); return; case AUT_ARG64: print_arg64_tok(outfp, tok, del, oflags); return; case AUT_DATA: print_arb_tok(outfp, tok, del, oflags); return; case AUT_ATTR32: print_attr32_tok(outfp, tok, del, oflags); return; case AUT_ATTR64: print_attr64_tok(outfp, tok, del, oflags); return; case AUT_EXIT: print_exit_tok(outfp, tok, del, oflags); return; case AUT_EXEC_ARGS: print_execarg_tok(outfp, tok, del, oflags); return; case AUT_EXEC_ENV: print_execenv_tok(outfp, tok, del, oflags); return; case AUT_OTHER_FILE32: print_file_tok(outfp, tok, del, oflags); return; case AUT_NEWGROUPS: print_newgroups_tok(outfp, tok, del, oflags); return; case AUT_IN_ADDR: print_inaddr_tok(outfp, tok, del, oflags); return; case AUT_IN_ADDR_EX: print_inaddr_ex_tok(outfp, tok, del, oflags); return; case AUT_IP: print_ip_tok(outfp, tok, del, oflags); return; case AUT_IPC: print_ipc_tok(outfp, tok, del, oflags); return; case AUT_IPC_PERM: print_ipcperm_tok(outfp, tok, del, oflags); return; case AUT_IPORT: print_iport_tok(outfp, tok, del, oflags); return; case AUT_OPAQUE: print_opaque_tok(outfp, tok, del, oflags); return; case AUT_PATH: print_path_tok(outfp, tok, del, oflags); return; case AUT_PROCESS32: print_process32_tok(outfp, tok, del, oflags); return; case AUT_PROCESS32_EX: print_process32ex_tok(outfp, tok, del, oflags); return; case AUT_PROCESS64: print_process64_tok(outfp, tok, del, oflags); return; case AUT_PROCESS64_EX: print_process64ex_tok(outfp, tok, del, oflags); return; case AUT_RETURN32: print_return32_tok(outfp, tok, del, oflags); return; case AUT_RETURN64: print_return64_tok(outfp, tok, del, oflags); return; case AUT_SEQ: print_seq_tok(outfp, tok, del, oflags); return; case AUT_SOCKET: print_socket_tok(outfp, tok, del, oflags); return; case AUT_SOCKINET32: print_sock_inet32_tok(outfp, tok, del, oflags); return; case AUT_SOCKUNIX: print_sock_unix_tok(outfp, tok, del, oflags); return; case AUT_SOCKINET128: print_sock_inet128_tok(outfp, tok, del, oflags); return; case AUT_SUBJECT32: print_subject32_tok(outfp, tok, del, oflags); return; case AUT_SUBJECT64: print_subject64_tok(outfp, tok, del, oflags); return; case AUT_SUBJECT32_EX: print_subject32ex_tok(outfp, tok, del, oflags); return; case AUT_SUBJECT64_EX: print_subject64ex_tok(outfp, tok, del, oflags); return; case AUT_TEXT: print_text_tok(outfp, tok, del, oflags); return; case AUT_SOCKET_EX: print_socketex32_tok(outfp, tok, del, oflags); return; case AUT_ZONENAME: print_zonename_tok(outfp, tok, del, oflags); return; case AUT_UPRIV: print_upriv_tok(outfp, tok, del, oflags); return; case AUT_PRIV: print_privset_tok(outfp, tok, del, oflags); return; default: print_invalid_tok(outfp, tok, del, oflags); } } /* * 'prints' the token out to outfp. */ void au_print_tok(FILE *outfp, tokenstr_t *tok, char *del, char raw, char sfrm) { int oflags = AU_OFLAG_NONE; if (raw) oflags |= AU_OFLAG_RAW; if (sfrm) oflags |= AU_OFLAG_SHORT; au_print_flags_tok(outfp, tok, del, oflags); } /* * 'prints' the token out to outfp in XML format. */ void au_print_tok_xml(FILE *outfp, tokenstr_t *tok, char *del, char raw, char sfrm) { int oflags = AU_OFLAG_XML; if (raw) oflags |= AU_OFLAG_RAW; if (sfrm) oflags |= AU_OFLAG_SHORT; au_print_flags_tok(outfp, tok, del, oflags); } /* * Read a record from the file pointer, store data in buf memory for buf is * also allocated in this function and has to be free'd outside this call. * * au_read_rec() handles two possibilities: a stand-alone file token, or a * complete audit record. * * XXXRW: Note that if we hit an error, we leave the stream in an unusable * state, because it will be partly offset into a record. We should rewind * or do something more intelligent. Particularly interesting is the case * where we perform a partial read of a record from a non-blockable file * descriptor. We should return the partial read and continue...? */ int au_read_rec(FILE *fp, u_char **buf) { u_char *bptr; u_int32_t recsize; u_int32_t bytestoread; u_char type; u_int32_t sec, msec; u_int16_t filenamelen; type = fgetc(fp); switch (type) { case AUT_HEADER32: case AUT_HEADER32_EX: case AUT_HEADER64: case AUT_HEADER64_EX: /* read the record size from the token */ if (fread(&recsize, 1, sizeof(u_int32_t), fp) < sizeof(u_int32_t)) { errno = EINVAL; return (-1); } recsize = be32toh(recsize); /* Check for recsize sanity */ if (recsize < (sizeof(u_int32_t) + sizeof(u_char))) { errno = EINVAL; return (-1); } *buf = calloc(recsize, sizeof(u_char)); if (*buf == NULL) return (-1); bptr = *buf; /* store the token contents already read, back to the buffer*/ *bptr = type; bptr++; be32enc(bptr, recsize); bptr += sizeof(u_int32_t); /* now read remaining record bytes */ bytestoread = recsize - (sizeof(u_int32_t) + sizeof(u_char)); if (fread(bptr, 1, bytestoread, fp) < bytestoread) { free(*buf); errno = EINVAL; return (-1); } break; case AUT_OTHER_FILE32: /* * The file token is variable-length, as it includes a * pathname. As a result, we have to read incrementally * until we know the total length, then allocate space and * read the rest. */ if (fread(&sec, 1, sizeof(sec), fp) < sizeof(sec)) { errno = EINVAL; return (-1); } if (fread(&msec, 1, sizeof(msec), fp) < sizeof(msec)) { errno = EINVAL; return (-1); } if (fread(&filenamelen, 1, sizeof(filenamelen), fp) < sizeof(filenamelen)) { errno = EINVAL; return (-1); } recsize = sizeof(type) + sizeof(sec) + sizeof(msec) + sizeof(filenamelen) + ntohs(filenamelen); *buf = malloc(recsize); if (*buf == NULL) return (-1); bptr = *buf; bcopy(&type, bptr, sizeof(type)); bptr += sizeof(type); bcopy(&sec, bptr, sizeof(sec)); bptr += sizeof(sec); bcopy(&msec, bptr, sizeof(msec)); bptr += sizeof(msec); bcopy(&filenamelen, bptr, sizeof(filenamelen)); bptr += sizeof(filenamelen); if (fread(bptr, 1, ntohs(filenamelen), fp) < ntohs(filenamelen)) { free(buf); errno = EINVAL; return (-1); } break; default: errno = EINVAL; return (-1); } return (recsize); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_mask.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_mask.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_mask.c (revision 292449) @@ -1,214 +1,212 @@ /*- * Copyright (c) 2004 Apple Inc. * Copyright (c) 2005 Robert N. M. Watson * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_mask.c#15 $ */ #include #include #ifdef HAVE_FULL_QUEUE_H #include #else /* !HAVE_FULL_QUEUE_H */ #include #endif /* !HAVE_FULL_QUEUE_H */ #include #ifdef HAVE_PTHREAD_MUTEX_LOCK #include #endif #include #include /* MT-Safe */ #ifdef HAVE_PTHREAD_MUTEX_LOCK static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; #endif static int firsttime = 1; /* * XXX ev_cache, once created, sticks around until the calling program exits. * This may or may not be a problem as far as absolute memory usage goes, but * at least there don't appear to be any leaks in using the cache. * * XXXRW: Note that despite (mutex), load_event_table() could race with * other consumers of the getauevents() API. */ struct audit_event_map { char ev_name[AU_EVENT_NAME_MAX]; char ev_desc[AU_EVENT_DESC_MAX]; struct au_event_ent ev; LIST_ENTRY(audit_event_map) ev_list; }; static LIST_HEAD(, audit_event_map) ev_cache; static struct audit_event_map * audit_event_map_alloc(void) { struct audit_event_map *aemp; aemp = malloc(sizeof(*aemp)); if (aemp == NULL) return (aemp); bzero(aemp, sizeof(*aemp)); aemp->ev.ae_name = aemp->ev_name; aemp->ev.ae_desc = aemp->ev_desc; return (aemp); } static void audit_event_map_free(struct audit_event_map *aemp) { free(aemp); } /* * When reading into the cache fails, we need to flush the entire cache to * prevent it from containing some but not all records. */ static void flush_cache(void) { struct audit_event_map *aemp; /* XXX: Would assert 'mutex'. */ while ((aemp = LIST_FIRST(&ev_cache)) != NULL) { LIST_REMOVE(aemp, ev_list); audit_event_map_free(aemp); } } static int load_event_table(void) { struct audit_event_map *aemp; struct au_event_ent *ep; /* * XXX: Would assert 'mutex'. * Loading of the cache happens only once; dont check if cache is * already loaded. */ LIST_INIT(&ev_cache); setauevent(); /* Rewind to beginning of entries. */ do { aemp = audit_event_map_alloc(); if (aemp == NULL) { flush_cache(); return (-1); } ep = getauevent_r(&aemp->ev); if (ep != NULL) LIST_INSERT_HEAD(&ev_cache, aemp, ev_list); else audit_event_map_free(aemp); } while (ep != NULL); return (1); } /* * Read the event with the matching event number from the cache. */ static struct au_event_ent * read_from_cache(au_event_t event) { struct audit_event_map *elem; /* XXX: Would assert 'mutex'. */ LIST_FOREACH(elem, &ev_cache, ev_list) { if (elem->ev.ae_number == event) return (&elem->ev); } return (NULL); } /* * Check if the audit event is preselected against the preselection mask. */ int au_preselect(au_event_t event, au_mask_t *mask_p, int sorf, int flag) { struct au_event_ent *ev; au_class_t effmask = 0; if (mask_p == NULL) return (-1); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif if (firsttime) { firsttime = 0; if ( -1 == load_event_table()) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-1); } } switch (flag) { case AU_PRS_REREAD: flush_cache(); if (load_event_table() == -1) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-1); } ev = read_from_cache(event); break; case AU_PRS_USECACHE: ev = read_from_cache(event); break; default: ev = NULL; } if (ev == NULL) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (-1); } if (sorf & AU_PRS_SUCCESS) effmask |= (mask_p->am_success & ev->ae_class); if (sorf & AU_PRS_FAILURE) effmask |= (mask_p->am_failure & ev->ae_class); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif if (effmask != 0) return (1); return (0); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_notify.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_notify.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_notify.c (revision 292449) @@ -1,181 +1,179 @@ /*- * Copyright (c) 2004-2009 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_notify.c#17 $ */ /* * Based on sample code from Marc Majka. */ #include #include #ifdef HAVE_FULL_QUEUE_H #include #else /* !HAVE_FULL_QUEUE_H */ #include #endif /* !HAVE_FULL_QUEUE_H */ #include #include #include #include #include #include #include #ifdef __APPLE__ #include /* If 1, assumes a kernel that sends the right notification. */ #define AUDIT_NOTIFICATION_ENABLED 1 #if AUDIT_NOTIFICATION_ENABLED static int token = 0; #endif /* AUDIT_NOTIFICATION_ENABLED */ static int au_cond = AUC_UNSET; /* */ uint32_t au_notify_initialize(void) { #if AUDIT_NOTIFICATION_ENABLED uint32_t status; int ignore_first; status = notify_register_check(__BSM_INTERNAL_NOTIFY_KEY, &token); if (status != NOTIFY_STATUS_OK) return (status); status = notify_check(token, &ignore_first); if (status != NOTIFY_STATUS_OK) return (status); #endif if (audit_get_cond(&au_cond) != 0) { syslog(LOG_ERR, "Initial audit status check failed (%s)", strerror(errno)); if (errno == ENOSYS) /* auditon() unimplemented. */ return (AU_UNIMPL); return (NOTIFY_STATUS_FAILED); /* Is there a better code? */ } return (NOTIFY_STATUS_OK); } int au_notify_terminate(void) { #if AUDIT_NOTIFICATION_ENABLED return ((notify_cancel(token) == NOTIFY_STATUS_OK) ? 0 : -1); #else return (0); #endif } /* * On error of any notify(3) call, reset 'au_cond' to ensure we re-run * au_notify_initialize() next time 'round--but assume auditing is on. This * is a slight performance hit if auditing is off, but at least the system * will behave correctly. The notification calls are unlikely to fail, * anyway. */ int au_get_state(void) { #if AUDIT_NOTIFICATION_ENABLED int did_notify; #endif int status; /* * Don't make the client initialize this set of routines, but take the * slight performance hit by checking ourselves every time. */ if (au_cond == AUC_UNSET) { status = au_notify_initialize(); if (status != NOTIFY_STATUS_OK) { if (status == AU_UNIMPL) return (AU_UNIMPL); return (AUC_AUDITING); } else return (au_cond); } #if AUDIT_NOTIFICATION_ENABLED status = notify_check(token, &did_notify); if (status != NOTIFY_STATUS_OK) { au_cond = AUC_UNSET; return (AUC_AUDITING); } if (did_notify == 0) return (au_cond); #endif if (audit_get_cond(&au_cond) != 0) { /* XXX Reset au_cond to AUC_UNSET? */ syslog(LOG_ERR, "Audit status check failed (%s)", strerror(errno)); if (errno == ENOSYS) /* Function unimplemented. */ return (AU_UNIMPL); return (errno); } switch (au_cond) { case AUC_NOAUDIT: /* Auditing suspended. */ case AUC_DISABLED: /* Auditing shut off. */ return (AUC_NOAUDIT); case AUC_UNSET: /* Uninitialized; shouldn't get here. */ case AUC_AUDITING: /* Audit on. */ default: return (AUC_AUDITING); } } #endif /* !__APPLE__ */ int cannot_audit(int val __unused) { #ifdef __APPLE__ return (!(au_get_state() == AUC_AUDITING)); #else int cond; if (audit_get_cond(&cond) != 0) { if (errno != ENOSYS) { syslog(LOG_ERR, "Audit status check failed (%s)", strerror(errno)); } return (1); } if (cond == AUC_NOAUDIT || cond == AUC_DISABLED) return (1); return (0); #endif /* !__APPLE__ */ } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_socket_type.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_socket_type.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_socket_type.c (revision 292449) @@ -1,104 +1,102 @@ /*- * Copyright (c) 2008 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_socket_type.c#1 $ */ #include #include #include #include #include struct bsm_socket_type { u_short bst_bsm_socket_type; int bst_local_socket_type; }; #define ST_NO_LOCAL_MAPPING -600 static const struct bsm_socket_type bsm_socket_types[] = { { BSM_SOCK_DGRAM, SOCK_DGRAM }, { BSM_SOCK_STREAM, SOCK_STREAM }, { BSM_SOCK_RAW, SOCK_RAW }, { BSM_SOCK_RDM, SOCK_RDM }, { BSM_SOCK_SEQPACKET, SOCK_SEQPACKET }, }; static const int bsm_socket_types_count = sizeof(bsm_socket_types) / sizeof(bsm_socket_types[0]); static const struct bsm_socket_type * bsm_lookup_local_socket_type(int local_socket_type) { int i; for (i = 0; i < bsm_socket_types_count; i++) { if (bsm_socket_types[i].bst_local_socket_type == local_socket_type) return (&bsm_socket_types[i]); } return (NULL); } u_short au_socket_type_to_bsm(int local_socket_type) { const struct bsm_socket_type *bstp; bstp = bsm_lookup_local_socket_type(local_socket_type); if (bstp == NULL) return (BSM_SOCK_UNKNOWN); return (bstp->bst_bsm_socket_type); } static const struct bsm_socket_type * bsm_lookup_bsm_socket_type(u_short bsm_socket_type) { int i; for (i = 0; i < bsm_socket_types_count; i++) { if (bsm_socket_types[i].bst_bsm_socket_type == bsm_socket_type) return (&bsm_socket_types[i]); } return (NULL); } int au_bsm_to_socket_type(u_short bsm_socket_type, int *local_socket_typep) { const struct bsm_socket_type *bstp; bstp = bsm_lookup_bsm_socket_type(bsm_socket_type); if (bstp == NULL || bstp->bst_local_socket_type) return (-1); *local_socket_typep = bstp->bst_local_socket_type; return (0); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_token.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_token.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_token.c (revision 292449) @@ -1,1647 +1,1645 @@ /*- * Copyright (c) 2004-2009 Apple Inc. * Copyright (c) 2005 SPARTA, Inc. * All rights reserved. * * This code was developed in part by Robert N. M. Watson, Senior Principal * Scientist, SPARTA, Inc. * * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_token.c#99 $ */ #include #include #ifdef USE_ENDIAN_H #include #endif #ifdef USE_SYS_ENDIAN_H #include #endif #ifdef USE_MACHINE_ENDIAN_H #include #endif #ifdef USE_COMPAT_ENDIAN_H #include #endif #ifdef USE_COMPAT_ENDIAN_ENC_H #include #endif #ifdef HAVE_FULL_QUEUE_H #include #else /* !HAVE_FULL_QUEUE_H */ #include #endif /* !HAVE_FULL_QUEUE_H */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define GET_TOKEN_AREA(t, dptr, length) do { \ (t) = malloc(sizeof(token_t)); \ if ((t) != NULL) { \ (t)->len = (length); \ (dptr) = (t->t_data) = calloc((length), sizeof(u_char)); \ if ((dptr) == NULL) { \ free(t); \ (t) = NULL; \ } \ } else \ (dptr) = NULL; \ assert((t) == NULL || (dptr) != NULL); \ } while (0) /* * token ID 1 byte * success/failure 1 byte * privstrlen 2 bytes * privstr N bytes + 1 (\0 byte) */ token_t * au_to_upriv(char sorf, char *priv) { u_int16_t textlen; u_char *dptr; token_t *t; textlen = strlen(priv) + 1; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_char) + sizeof(u_int16_t) + textlen); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_UPRIV); ADD_U_CHAR(dptr, sorf); ADD_U_INT16(dptr, textlen); ADD_STRING(dptr, priv, textlen); return (t); } /* * token ID 1 byte * privtstrlen 2 bytes * privtstr N bytes + 1 * privstrlen 2 bytes * privstr N bytes + 1 */ token_t * au_to_privset(char *privtypestr, char *privstr) { u_int16_t type_len, priv_len; u_char *dptr; token_t *t; type_len = strlen(privtypestr) + 1; priv_len = strlen(privstr) + 1; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + sizeof(u_int16_t) + type_len + priv_len); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_PRIV); ADD_U_INT16(dptr, type_len); ADD_STRING(dptr, privtypestr, type_len); ADD_U_INT16(dptr, priv_len); ADD_STRING(dptr, privstr, priv_len); return (t); } /* * token ID 1 byte * argument # 1 byte * argument value 4 bytes/8 bytes (32-bit/64-bit value) * text length 2 bytes * text N bytes + 1 terminating NULL byte */ token_t * au_to_arg32(char n, const char *text, u_int32_t v) { token_t *t; u_char *dptr = NULL; u_int16_t textlen; textlen = strlen(text); textlen += 1; GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t) + sizeof(u_int16_t) + textlen); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_ARG32); ADD_U_CHAR(dptr, n); ADD_U_INT32(dptr, v); ADD_U_INT16(dptr, textlen); ADD_STRING(dptr, text, textlen); return (t); } token_t * au_to_arg64(char n, const char *text, u_int64_t v) { token_t *t; u_char *dptr = NULL; u_int16_t textlen; textlen = strlen(text); textlen += 1; GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int64_t) + sizeof(u_int16_t) + textlen); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_ARG64); ADD_U_CHAR(dptr, n); ADD_U_INT64(dptr, v); ADD_U_INT16(dptr, textlen); ADD_STRING(dptr, text, textlen); return (t); } token_t * au_to_arg(char n, const char *text, u_int32_t v) { return (au_to_arg32(n, text, v)); } #if defined(_KERNEL) || defined(KERNEL) /* * token ID 1 byte * file access mode 4 bytes * owner user ID 4 bytes * owner group ID 4 bytes * file system ID 4 bytes * node ID 8 bytes * device 4 bytes/8 bytes (32-bit/64-bit) */ token_t * au_to_attr32(struct vnode_au_info *vni) { token_t *t; u_char *dptr = NULL; u_int16_t pad0_16 = 0; u_int32_t pad0_32 = 0; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int16_t) + 3 * sizeof(u_int32_t) + sizeof(u_int64_t) + sizeof(u_int32_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_ATTR32); /* * BSD defines the size for the file mode as 2 bytes; BSM defines 4 * so pad with 0. * * XXXRW: Possibly should be conditionally compiled. * * XXXRW: Should any conversions take place on the mode? */ ADD_U_INT16(dptr, pad0_16); ADD_U_INT16(dptr, vni->vn_mode); ADD_U_INT32(dptr, vni->vn_uid); ADD_U_INT32(dptr, vni->vn_gid); ADD_U_INT32(dptr, vni->vn_fsid); /* * Some systems use 32-bit file ID's, others use 64-bit file IDs. * Attempt to handle both, and let the compiler sort it out. If we * could pick this out at compile-time, it would be better, so as to * avoid the else case below. */ if (sizeof(vni->vn_fileid) == sizeof(uint32_t)) { ADD_U_INT32(dptr, pad0_32); ADD_U_INT32(dptr, vni->vn_fileid); } else if (sizeof(vni->vn_fileid) == sizeof(uint64_t)) ADD_U_INT64(dptr, vni->vn_fileid); else ADD_U_INT64(dptr, 0LL); ADD_U_INT32(dptr, vni->vn_dev); return (t); } token_t * au_to_attr64(struct vnode_au_info *vni) { token_t *t; u_char *dptr = NULL; u_int16_t pad0_16 = 0; u_int32_t pad0_32 = 0; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int16_t) + 3 * sizeof(u_int32_t) + sizeof(u_int64_t) * 2); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_ATTR64); /* * BSD defines the size for the file mode as 2 bytes; BSM defines 4 * so pad with 0. * * XXXRW: Possibly should be conditionally compiled. * * XXXRW: Should any conversions take place on the mode? */ ADD_U_INT16(dptr, pad0_16); ADD_U_INT16(dptr, vni->vn_mode); ADD_U_INT32(dptr, vni->vn_uid); ADD_U_INT32(dptr, vni->vn_gid); ADD_U_INT32(dptr, vni->vn_fsid); /* * Some systems use 32-bit file ID's, other's use 64-bit file IDs. * Attempt to handle both, and let the compiler sort it out. If we * could pick this out at compile-time, it would be better, so as to * avoid the else case below. */ if (sizeof(vni->vn_fileid) == sizeof(uint32_t)) { ADD_U_INT32(dptr, pad0_32); ADD_U_INT32(dptr, vni->vn_fileid); } else if (sizeof(vni->vn_fileid) == sizeof(uint64_t)) ADD_U_INT64(dptr, vni->vn_fileid); else ADD_U_INT64(dptr, 0LL); ADD_U_INT64(dptr, vni->vn_dev); return (t); } token_t * au_to_attr(struct vnode_au_info *vni) { return (au_to_attr32(vni)); } #endif /* !(defined(_KERNEL) || defined(KERNEL) */ /* * token ID 1 byte * how to print 1 byte * basic unit 1 byte * unit count 1 byte * data items (depends on basic unit) */ token_t * au_to_data(char unit_print, char unit_type, char unit_count, const char *p) { token_t *t; u_char *dptr = NULL; size_t datasize, totdata; /* Determine the size of the basic unit. */ switch (unit_type) { case AUR_BYTE: /* case AUR_CHAR: */ datasize = AUR_BYTE_SIZE; break; case AUR_SHORT: datasize = AUR_SHORT_SIZE; break; case AUR_INT32: /* case AUR_INT: */ datasize = AUR_INT32_SIZE; break; case AUR_INT64: datasize = AUR_INT64_SIZE; break; default: errno = EINVAL; return (NULL); } totdata = datasize * unit_count; GET_TOKEN_AREA(t, dptr, 4 * sizeof(u_char) + totdata); if (t == NULL) return (NULL); /* * XXXRW: We should be byte-swapping each data item for multi-byte * types. */ ADD_U_CHAR(dptr, AUT_DATA); ADD_U_CHAR(dptr, unit_print); ADD_U_CHAR(dptr, unit_type); ADD_U_CHAR(dptr, unit_count); ADD_MEM(dptr, p, totdata); return (t); } /* * token ID 1 byte * status 4 bytes * return value 4 bytes */ token_t * au_to_exit(int retval, int err) { token_t *t; u_char *dptr = NULL; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int32_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_EXIT); ADD_U_INT32(dptr, err); ADD_U_INT32(dptr, retval); return (t); } /* */ token_t * au_to_groups(int *groups) { return (au_to_newgroups(AUDIT_MAX_GROUPS, (gid_t *)groups)); } /* * token ID 1 byte * number groups 2 bytes * group list count * 4 bytes */ token_t * au_to_newgroups(u_int16_t n, gid_t *groups) { token_t *t; u_char *dptr = NULL; int i; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + n * sizeof(u_int32_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_NEWGROUPS); ADD_U_INT16(dptr, n); for (i = 0; i < n; i++) ADD_U_INT32(dptr, groups[i]); return (t); } /* * token ID 1 byte * internet address 4 bytes */ token_t * au_to_in_addr(struct in_addr *internet_addr) { token_t *t; u_char *dptr = NULL; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(uint32_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_IN_ADDR); ADD_MEM(dptr, &internet_addr->s_addr, sizeof(uint32_t)); return (t); } /* * token ID 1 byte * address type/length 4 bytes * address 16 bytes */ token_t * au_to_in_addr_ex(struct in6_addr *internet_addr) { token_t *t; u_char *dptr = NULL; u_int32_t type = AU_IPv6; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 5 * sizeof(uint32_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_IN_ADDR_EX); ADD_U_INT32(dptr, type); ADD_MEM(dptr, internet_addr, 4 * sizeof(uint32_t)); return (t); } /* * token ID 1 byte * ip header 20 bytes * * The IP header should be submitted in network byte order. */ token_t * au_to_ip(struct ip *ip) { token_t *t; u_char *dptr = NULL; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(struct ip)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_IP); ADD_MEM(dptr, ip, sizeof(struct ip)); return (t); } /* * token ID 1 byte * object ID type 1 byte * object ID 4 bytes */ token_t * au_to_ipc(char type, int id) { token_t *t; u_char *dptr = NULL; GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_IPC); ADD_U_CHAR(dptr, type); ADD_U_INT32(dptr, id); return (t); } /* * token ID 1 byte * owner user ID 4 bytes * owner group ID 4 bytes * creator user ID 4 bytes * creator group ID 4 bytes * access mode 4 bytes * slot sequence # 4 bytes * key 4 bytes */ token_t * au_to_ipc_perm(struct ipc_perm *perm) { token_t *t; u_char *dptr = NULL; u_int16_t pad0 = 0; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 12 * sizeof(u_int16_t) + sizeof(u_int32_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_IPC_PERM); /* * Systems vary significantly in what types they use in struct * ipc_perm; at least a few still use 16-bit uid's and gid's, so * allow for that, as BSM define 32-bit values here. * Some systems define the sizes for ipc_perm members as 2 bytes; * BSM defines 4 so pad with 0. * * XXXRW: Possibly shoulid be conditionally compiled, and more cases * need to be handled. */ if (sizeof(perm->uid) != sizeof(u_int32_t)) { ADD_U_INT16(dptr, pad0); ADD_U_INT16(dptr, perm->uid); ADD_U_INT16(dptr, pad0); ADD_U_INT16(dptr, perm->gid); ADD_U_INT16(dptr, pad0); ADD_U_INT16(dptr, perm->cuid); ADD_U_INT16(dptr, pad0); ADD_U_INT16(dptr, perm->cgid); } else { ADD_U_INT32(dptr, perm->uid); ADD_U_INT32(dptr, perm->gid); ADD_U_INT32(dptr, perm->cuid); ADD_U_INT32(dptr, perm->cgid); } ADD_U_INT16(dptr, pad0); ADD_U_INT16(dptr, perm->mode); ADD_U_INT16(dptr, pad0); #ifdef HAVE_IPC_PERM___SEQ ADD_U_INT16(dptr, perm->__seq); #else /* HAVE_IPC_PERM___SEQ */ #ifdef HAVE_IPC_PERM__SEQ ADD_U_INT16(dptr, perm->_seq); #else /* HAVE_IPC_PERM__SEQ */ ADD_U_INT16(dptr, perm->seq); #endif /* HAVE_IPC_PERM__SEQ */ #endif /* HAVE_IPC_PERM___SEQ */ #ifdef HAVE_IPC_PERM___KEY ADD_U_INT32(dptr, perm->__key); #else /* HAVE_IPC_PERM___KEY */ #ifdef HAVE_IPC_PERM__KEY ADD_U_INT32(dptr, perm->_key); #else /* HAVE_IPC_PERM__KEY */ ADD_U_INT32(dptr, perm->key); #endif /* HAVE_IPC_PERM__KEY */ #endif /* HAVE_IPC_PERM___KEY */ return (t); } /* * token ID 1 byte * port IP address 2 bytes */ token_t * au_to_iport(u_int16_t iport) { token_t *t; u_char *dptr = NULL; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_IPORT); ADD_U_INT16(dptr, iport); return (t); } /* * token ID 1 byte * size 2 bytes * data size bytes */ token_t * au_to_opaque(const char *data, u_int16_t bytes) { token_t *t; u_char *dptr = NULL; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + bytes); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_OPAQUE); ADD_U_INT16(dptr, bytes); ADD_MEM(dptr, data, bytes); return (t); } /* * token ID 1 byte * seconds of time 4 bytes * milliseconds of time 4 bytes * file name len 2 bytes * file pathname N bytes + 1 terminating NULL byte */ token_t * au_to_file(const char *file, struct timeval tm) { token_t *t; u_char *dptr = NULL; u_int16_t filelen; u_int32_t timems; filelen = strlen(file); filelen += 1; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int32_t) + sizeof(u_int16_t) + filelen); if (t == NULL) return (NULL); timems = tm.tv_usec/1000; ADD_U_CHAR(dptr, AUT_OTHER_FILE32); ADD_U_INT32(dptr, tm.tv_sec); ADD_U_INT32(dptr, timems); /* We need time in ms. */ ADD_U_INT16(dptr, filelen); ADD_STRING(dptr, file, filelen); return (t); } /* * token ID 1 byte * text length 2 bytes * text N bytes + 1 terminating NULL byte */ token_t * au_to_text(const char *text) { token_t *t; u_char *dptr = NULL; u_int16_t textlen; textlen = strlen(text); textlen += 1; /* XXXRW: Should validate length against token size limit. */ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_TEXT); ADD_U_INT16(dptr, textlen); ADD_STRING(dptr, text, textlen); return (t); } /* * token ID 1 byte * path length 2 bytes * path N bytes + 1 terminating NULL byte */ token_t * au_to_path(const char *text) { token_t *t; u_char *dptr = NULL; u_int16_t textlen; textlen = strlen(text); textlen += 1; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_PATH); ADD_U_INT16(dptr, textlen); ADD_STRING(dptr, text, textlen); return (t); } /* * token ID 1 byte * audit ID 4 bytes * effective user ID 4 bytes * effective group ID 4 bytes * real user ID 4 bytes * real group ID 4 bytes * process ID 4 bytes * session ID 4 bytes * terminal ID * port ID 4 bytes/8 bytes (32-bit/64-bit value) * machine address 4 bytes */ token_t * au_to_process32(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_t *tid) { token_t *t; u_char *dptr = NULL; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 9 * sizeof(u_int32_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_PROCESS32); ADD_U_INT32(dptr, auid); ADD_U_INT32(dptr, euid); ADD_U_INT32(dptr, egid); ADD_U_INT32(dptr, ruid); ADD_U_INT32(dptr, rgid); ADD_U_INT32(dptr, pid); ADD_U_INT32(dptr, sid); ADD_U_INT32(dptr, tid->port); /* * Note: Solaris will write out IPv6 addresses here as a 32-bit * address type and 16 bytes of address, but for IPv4 addresses it * simply writes the 4-byte address directly. We support only IPv4 * addresses for process32 tokens. */ ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t)); return (t); } token_t * au_to_process64(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_t *tid) { token_t *t; u_char *dptr = NULL; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 8 * sizeof(u_int32_t) + sizeof(u_int64_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_PROCESS64); ADD_U_INT32(dptr, auid); ADD_U_INT32(dptr, euid); ADD_U_INT32(dptr, egid); ADD_U_INT32(dptr, ruid); ADD_U_INT32(dptr, rgid); ADD_U_INT32(dptr, pid); ADD_U_INT32(dptr, sid); ADD_U_INT64(dptr, tid->port); /* * Note: Solaris will write out IPv6 addresses here as a 32-bit * address type and 16 bytes of address, but for IPv4 addresses it * simply writes the 4-byte address directly. We support only IPv4 * addresses for process64 tokens. */ ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t)); return (t); } token_t * au_to_process(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_t *tid) { return (au_to_process32(auid, euid, egid, ruid, rgid, pid, sid, tid)); } /* * token ID 1 byte * audit ID 4 bytes * effective user ID 4 bytes * effective group ID 4 bytes * real user ID 4 bytes * real group ID 4 bytes * process ID 4 bytes * session ID 4 bytes * terminal ID * port ID 4 bytes/8 bytes (32-bit/64-bit value) * address type-len 4 bytes * machine address 16 bytes */ token_t * au_to_process32_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid) { token_t *t; u_char *dptr = NULL; if (tid->at_type == AU_IPv4) GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 10 * sizeof(u_int32_t)); else if (tid->at_type == AU_IPv6) GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 13 * sizeof(u_int32_t)); else { errno = EINVAL; return (NULL); } if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_PROCESS32_EX); ADD_U_INT32(dptr, auid); ADD_U_INT32(dptr, euid); ADD_U_INT32(dptr, egid); ADD_U_INT32(dptr, ruid); ADD_U_INT32(dptr, rgid); ADD_U_INT32(dptr, pid); ADD_U_INT32(dptr, sid); ADD_U_INT32(dptr, tid->at_port); ADD_U_INT32(dptr, tid->at_type); ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t)); if (tid->at_type == AU_IPv6) { ADD_MEM(dptr, &tid->at_addr[1], sizeof(u_int32_t)); ADD_MEM(dptr, &tid->at_addr[2], sizeof(u_int32_t)); ADD_MEM(dptr, &tid->at_addr[3], sizeof(u_int32_t)); } return (t); } token_t * au_to_process64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid) { token_t *t; u_char *dptr = NULL; if (tid->at_type == AU_IPv4) GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 7 * sizeof(u_int32_t) + sizeof(u_int64_t) + 2 * sizeof(u_int32_t)); else if (tid->at_type == AU_IPv6) GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 7 * sizeof(u_int32_t) + sizeof(u_int64_t) + 5 * sizeof(u_int32_t)); else { errno = EINVAL; return (NULL); } if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_PROCESS64_EX); ADD_U_INT32(dptr, auid); ADD_U_INT32(dptr, euid); ADD_U_INT32(dptr, egid); ADD_U_INT32(dptr, ruid); ADD_U_INT32(dptr, rgid); ADD_U_INT32(dptr, pid); ADD_U_INT32(dptr, sid); ADD_U_INT64(dptr, tid->at_port); ADD_U_INT32(dptr, tid->at_type); ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t)); if (tid->at_type == AU_IPv6) { ADD_MEM(dptr, &tid->at_addr[1], sizeof(u_int32_t)); ADD_MEM(dptr, &tid->at_addr[2], sizeof(u_int32_t)); ADD_MEM(dptr, &tid->at_addr[3], sizeof(u_int32_t)); } return (t); } token_t * au_to_process_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid) { return (au_to_process32_ex(auid, euid, egid, ruid, rgid, pid, sid, tid)); } /* * token ID 1 byte * error status 1 byte * return value 4 bytes/8 bytes (32-bit/64-bit value) */ token_t * au_to_return32(char status, u_int32_t ret) { token_t *t; u_char *dptr = NULL; GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_RETURN32); ADD_U_CHAR(dptr, status); ADD_U_INT32(dptr, ret); return (t); } token_t * au_to_return64(char status, u_int64_t ret) { token_t *t; u_char *dptr = NULL; GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int64_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_RETURN64); ADD_U_CHAR(dptr, status); ADD_U_INT64(dptr, ret); return (t); } token_t * au_to_return(char status, u_int32_t ret) { return (au_to_return32(status, ret)); } /* * token ID 1 byte * sequence number 4 bytes */ token_t * au_to_seq(long audit_count) { token_t *t; u_char *dptr = NULL; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_SEQ); ADD_U_INT32(dptr, audit_count); return (t); } /* * token ID 1 byte * socket domain 2 bytes * socket type 2 bytes * address type 2 byte * local port 2 bytes * local address 4 bytes/16 bytes (IPv4/IPv6 address) * remote port 2 bytes * remote address 4 bytes/16 bytes (IPv4/IPv6 address) * * Domain and type arguments to this routine are assumed to already have been * converted to the BSM constant space, so we don't do that here. */ token_t * au_to_socket_ex(u_short so_domain, u_short so_type, struct sockaddr *sa_local, struct sockaddr *sa_remote) { token_t *t; u_char *dptr = NULL; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; if (so_domain == AF_INET) GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 5 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t)); else if (so_domain == AF_INET6) GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 5 * sizeof(u_int16_t) + 8 * sizeof(u_int32_t)); else { errno = EINVAL; return (NULL); } if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_SOCKET_EX); ADD_U_INT16(dptr, au_domain_to_bsm(so_domain)); ADD_U_INT16(dptr, au_socket_type_to_bsm(so_type)); if (so_domain == AF_INET) { ADD_U_INT16(dptr, AU_IPv4); sin = (struct sockaddr_in *)sa_local; ADD_MEM(dptr, &sin->sin_port, sizeof(uint16_t)); ADD_MEM(dptr, &sin->sin_addr.s_addr, sizeof(uint32_t)); sin = (struct sockaddr_in *)sa_remote; ADD_MEM(dptr, &sin->sin_port, sizeof(uint16_t)); ADD_MEM(dptr, &sin->sin_addr.s_addr, sizeof(uint32_t)); } else { ADD_U_INT16(dptr, AU_IPv6); sin6 = (struct sockaddr_in6 *)sa_local; ADD_MEM(dptr, &sin6->sin6_port, sizeof(uint16_t)); ADD_MEM(dptr, &sin6->sin6_addr, 4 * sizeof(uint32_t)); sin6 = (struct sockaddr_in6 *)sa_remote; ADD_MEM(dptr, &sin6->sin6_port, sizeof(uint16_t)); ADD_MEM(dptr, &sin6->sin6_addr, 4 * sizeof(uint32_t)); } return (t); } /* * token ID 1 byte * socket family 2 bytes * path (up to) 104 bytes + NULL (NULL terminated string) */ token_t * au_to_sock_unix(struct sockaddr_un *so) { token_t *t; u_char *dptr; GET_TOKEN_AREA(t, dptr, 3 * sizeof(u_char) + strlen(so->sun_path) + 1); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_SOCKUNIX); /* BSM token has two bytes for family */ ADD_U_CHAR(dptr, 0); ADD_U_CHAR(dptr, so->sun_family); ADD_STRING(dptr, so->sun_path, strlen(so->sun_path) + 1); return (t); } /* * token ID 1 byte * socket family 2 bytes * local port 2 bytes * socket address 4 bytes */ token_t * au_to_sock_inet32(struct sockaddr_in *so) { token_t *t; u_char *dptr = NULL; uint16_t family; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(uint16_t) + sizeof(uint32_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_SOCKINET32); /* * BSM defines the family field as 16 bits, but many operating * systems have an 8-bit sin_family field. Extend to 16 bits before * writing into the token. Assume that both the port and the address * in the sockaddr_in are already in network byte order, but family * is in local byte order. * * XXXRW: Should a name space conversion be taking place on the value * of sin_family? */ family = so->sin_family; ADD_U_INT16(dptr, family); ADD_MEM(dptr, &so->sin_port, sizeof(uint16_t)); ADD_MEM(dptr, &so->sin_addr.s_addr, sizeof(uint32_t)); return (t); } token_t * au_to_sock_inet128(struct sockaddr_in6 *so) { token_t *t; u_char *dptr = NULL; GET_TOKEN_AREA(t, dptr, 3 * sizeof(u_char) + sizeof(u_int16_t) + 4 * sizeof(u_int32_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_SOCKINET128); /* * In BSD, sin6_family is one octet, but BSM defines the token to * store two. So we copy in a 0 first. XXXRW: Possibly should be * conditionally compiled. */ ADD_U_CHAR(dptr, 0); ADD_U_CHAR(dptr, so->sin6_family); ADD_U_INT16(dptr, so->sin6_port); ADD_MEM(dptr, &so->sin6_addr, 4 * sizeof(uint32_t)); return (t); } token_t * au_to_sock_inet(struct sockaddr_in *so) { return (au_to_sock_inet32(so)); } /* * token ID 1 byte * audit ID 4 bytes * effective user ID 4 bytes * effective group ID 4 bytes * real user ID 4 bytes * real group ID 4 bytes * process ID 4 bytes * session ID 4 bytes * terminal ID * port ID 4 bytes/8 bytes (32-bit/64-bit value) * machine address 4 bytes */ token_t * au_to_subject32(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_t *tid) { token_t *t; u_char *dptr = NULL; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 9 * sizeof(u_int32_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_SUBJECT32); ADD_U_INT32(dptr, auid); ADD_U_INT32(dptr, euid); ADD_U_INT32(dptr, egid); ADD_U_INT32(dptr, ruid); ADD_U_INT32(dptr, rgid); ADD_U_INT32(dptr, pid); ADD_U_INT32(dptr, sid); ADD_U_INT32(dptr, tid->port); ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t)); return (t); } token_t * au_to_subject64(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_t *tid) { token_t *t; u_char *dptr = NULL; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 7 * sizeof(u_int32_t) + sizeof(u_int64_t) + sizeof(u_int32_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_SUBJECT64); ADD_U_INT32(dptr, auid); ADD_U_INT32(dptr, euid); ADD_U_INT32(dptr, egid); ADD_U_INT32(dptr, ruid); ADD_U_INT32(dptr, rgid); ADD_U_INT32(dptr, pid); ADD_U_INT32(dptr, sid); ADD_U_INT64(dptr, tid->port); ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t)); return (t); } token_t * au_to_subject(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_t *tid) { return (au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid, tid)); } /* * token ID 1 byte * audit ID 4 bytes * effective user ID 4 bytes * effective group ID 4 bytes * real user ID 4 bytes * real group ID 4 bytes * process ID 4 bytes * session ID 4 bytes * terminal ID * port ID 4 bytes/8 bytes (32-bit/64-bit value) * address type/length 4 bytes * machine address 16 bytes */ token_t * au_to_subject32_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid) { token_t *t; u_char *dptr = NULL; if (tid->at_type == AU_IPv4) GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 10 * sizeof(u_int32_t)); else if (tid->at_type == AU_IPv6) GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 13 * sizeof(u_int32_t)); else { errno = EINVAL; return (NULL); } if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_SUBJECT32_EX); ADD_U_INT32(dptr, auid); ADD_U_INT32(dptr, euid); ADD_U_INT32(dptr, egid); ADD_U_INT32(dptr, ruid); ADD_U_INT32(dptr, rgid); ADD_U_INT32(dptr, pid); ADD_U_INT32(dptr, sid); ADD_U_INT32(dptr, tid->at_port); ADD_U_INT32(dptr, tid->at_type); if (tid->at_type == AU_IPv6) ADD_MEM(dptr, &tid->at_addr[0], 4 * sizeof(u_int32_t)); else ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t)); return (t); } token_t * au_to_subject64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid) { token_t *t; u_char *dptr = NULL; if (tid->at_type == AU_IPv4) GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 7 * sizeof(u_int32_t) + sizeof(u_int64_t) + 2 * sizeof(u_int32_t)); else if (tid->at_type == AU_IPv6) GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 7 * sizeof(u_int32_t) + sizeof(u_int64_t) + 5 * sizeof(u_int32_t)); else { errno = EINVAL; return (NULL); } if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_SUBJECT64_EX); ADD_U_INT32(dptr, auid); ADD_U_INT32(dptr, euid); ADD_U_INT32(dptr, egid); ADD_U_INT32(dptr, ruid); ADD_U_INT32(dptr, rgid); ADD_U_INT32(dptr, pid); ADD_U_INT32(dptr, sid); ADD_U_INT64(dptr, tid->at_port); ADD_U_INT32(dptr, tid->at_type); if (tid->at_type == AU_IPv6) ADD_MEM(dptr, &tid->at_addr[0], 4 * sizeof(u_int32_t)); else ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t)); return (t); } token_t * au_to_subject_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid) { return (au_to_subject32_ex(auid, euid, egid, ruid, rgid, pid, sid, tid)); } #if !defined(_KERNEL) && !defined(KERNEL) && defined(HAVE_AUDIT_SYSCALLS) /* * Collects audit information for the current process and creates a subject * token from it. */ token_t * au_to_me(void) { auditinfo_t auinfo; auditinfo_addr_t aia; /* * Try to use getaudit_addr(2) first. If this kernel does not support * it, then fall back on to getaudit(2). */ if (getaudit_addr(&aia, sizeof(aia)) != 0) { if (errno == ENOSYS) { if (getaudit(&auinfo) != 0) return (NULL); return (au_to_subject32(auinfo.ai_auid, geteuid(), getegid(), getuid(), getgid(), getpid(), auinfo.ai_asid, &auinfo.ai_termid)); } else { /* getaudit_addr(2) failed for some other reason. */ return (NULL); } } return (au_to_subject32_ex(aia.ai_auid, geteuid(), getegid(), getuid(), getgid(), getpid(), aia.ai_asid, &aia.ai_termid)); } #endif /* * token ID 1 byte * count 4 bytes * text count null-terminated strings */ token_t * au_to_exec_args(char **argv) { token_t *t; u_char *dptr = NULL; const char *nextarg; int i, count = 0; size_t totlen = 0; nextarg = *argv; while (nextarg != NULL) { int nextlen; nextlen = strlen(nextarg); totlen += nextlen + 1; count++; nextarg = *(argv + count); } GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + totlen); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_EXEC_ARGS); ADD_U_INT32(dptr, count); for (i = 0; i < count; i++) { nextarg = *(argv + i); ADD_MEM(dptr, nextarg, strlen(nextarg) + 1); } return (t); } /* * token ID 1 byte * count 4 bytes * text count null-terminated strings */ token_t * au_to_exec_env(char **envp) { token_t *t; u_char *dptr = NULL; int i, count = 0; size_t totlen = 0; const char *nextenv; nextenv = *envp; while (nextenv != NULL) { int nextlen; nextlen = strlen(nextenv); totlen += nextlen + 1; count++; nextenv = *(envp + count); } GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + totlen); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_EXEC_ENV); ADD_U_INT32(dptr, count); for (i = 0; i < count; i++) { nextenv = *(envp + i); ADD_MEM(dptr, nextenv, strlen(nextenv) + 1); } return (t); } /* * token ID 1 byte * zonename length 2 bytes * zonename N bytes + 1 terminating NULL byte */ token_t * au_to_zonename(const char *zonename) { u_char *dptr = NULL; u_int16_t textlen; token_t *t; textlen = strlen(zonename) + 1; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_ZONENAME); ADD_U_INT16(dptr, textlen); ADD_STRING(dptr, zonename, textlen); return (t); } /* * token ID 1 byte * record byte count 4 bytes * version # 1 byte [2] * event type 2 bytes * event modifier 2 bytes * seconds of time 4 bytes/8 bytes (32-bit/64-bit value) * milliseconds of time 4 bytes/8 bytes (32-bit/64-bit value) */ token_t * au_to_header32_tm(int rec_size, au_event_t e_type, au_emod_t e_mod, struct timeval tm) { token_t *t; u_char *dptr = NULL; u_int32_t timems; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + sizeof(u_char) + 2 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_HEADER32); ADD_U_INT32(dptr, rec_size); ADD_U_CHAR(dptr, AUDIT_HEADER_VERSION_OPENBSM); ADD_U_INT16(dptr, e_type); ADD_U_INT16(dptr, e_mod); timems = tm.tv_usec/1000; /* Add the timestamp */ ADD_U_INT32(dptr, tm.tv_sec); ADD_U_INT32(dptr, timems); /* We need time in ms. */ return (t); } /* * token ID 1 byte * record byte count 4 bytes * version # 1 byte [2] * event type 2 bytes * event modifier 2 bytes * address type/length 4 bytes * machine address 4 bytes/16 bytes (IPv4/IPv6 address) * seconds of time 4 bytes/8 bytes (32-bit/64-bit value) * milliseconds of time 4 bytes/8 bytes (32-bit/64-bit value) */ token_t * au_to_header32_ex_tm(int rec_size, au_event_t e_type, au_emod_t e_mod, struct timeval tm, struct auditinfo_addr *aia) { token_t *t; u_char *dptr = NULL; u_int32_t timems; au_tid_addr_t *tid; tid = &aia->ai_termid; if (tid->at_type != AU_IPv4 && tid->at_type != AU_IPv6) return (NULL); GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + sizeof(u_char) + 2 * sizeof(u_int16_t) + 3 * sizeof(u_int32_t) + tid->at_type); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_HEADER32_EX); ADD_U_INT32(dptr, rec_size); ADD_U_CHAR(dptr, AUDIT_HEADER_VERSION_OPENBSM); ADD_U_INT16(dptr, e_type); ADD_U_INT16(dptr, e_mod); ADD_U_INT32(dptr, tid->at_type); if (tid->at_type == AU_IPv6) ADD_MEM(dptr, &tid->at_addr[0], 4 * sizeof(u_int32_t)); else ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t)); timems = tm.tv_usec/1000; /* Add the timestamp */ ADD_U_INT32(dptr, tm.tv_sec); ADD_U_INT32(dptr, timems); /* We need time in ms. */ return (t); } token_t * au_to_header64_tm(int rec_size, au_event_t e_type, au_emod_t e_mod, struct timeval tm) { token_t *t; u_char *dptr = NULL; u_int32_t timems; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + sizeof(u_char) + 2 * sizeof(u_int16_t) + 2 * sizeof(u_int64_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_HEADER64); ADD_U_INT32(dptr, rec_size); ADD_U_CHAR(dptr, AUDIT_HEADER_VERSION_OPENBSM); ADD_U_INT16(dptr, e_type); ADD_U_INT16(dptr, e_mod); timems = tm.tv_usec/1000; /* Add the timestamp */ ADD_U_INT64(dptr, tm.tv_sec); ADD_U_INT64(dptr, timems); /* We need time in ms. */ return (t); } #if !defined(KERNEL) && !defined(_KERNEL) #ifdef HAVE_AUDIT_SYSCALLS token_t * au_to_header32_ex(int rec_size, au_event_t e_type, au_emod_t e_mod) { struct timeval tm; struct auditinfo_addr aia; if (gettimeofday(&tm, NULL) == -1) return (NULL); if (audit_get_kaudit(&aia, sizeof(aia)) != 0) { if (errno != ENOSYS) return (NULL); return (au_to_header32_tm(rec_size, e_type, e_mod, tm)); } return (au_to_header32_ex_tm(rec_size, e_type, e_mod, tm, &aia)); } #endif /* HAVE_AUDIT_SYSCALLS */ token_t * au_to_header32(int rec_size, au_event_t e_type, au_emod_t e_mod) { struct timeval tm; if (gettimeofday(&tm, NULL) == -1) return (NULL); return (au_to_header32_tm(rec_size, e_type, e_mod, tm)); } token_t * au_to_header64(__unused int rec_size, __unused au_event_t e_type, __unused au_emod_t e_mod) { struct timeval tm; if (gettimeofday(&tm, NULL) == -1) return (NULL); return (au_to_header64_tm(rec_size, e_type, e_mod, tm)); } token_t * au_to_header(int rec_size, au_event_t e_type, au_emod_t e_mod) { return (au_to_header32(rec_size, e_type, e_mod)); } #ifdef HAVE_AUDIT_SYSCALLS token_t * au_to_header_ex(int rec_size, au_event_t e_type, au_emod_t e_mod) { return (au_to_header32_ex(rec_size, e_type, e_mod)); } #endif /* HAVE_AUDIT_SYSCALLS */ #endif /* !defined(KERNEL) && !defined(_KERNEL) */ /* * token ID 1 byte * trailer magic number 2 bytes * record byte count 4 bytes */ token_t * au_to_trailer(int rec_size) { token_t *t; u_char *dptr = NULL; u_int16_t magic = AUT_TRAILER_MAGIC; GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + sizeof(u_int32_t)); if (t == NULL) return (NULL); ADD_U_CHAR(dptr, AUT_TRAILER); ADD_U_INT16(dptr, magic); ADD_U_INT32(dptr, rec_size); return (t); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_user.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_user.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_user.c (revision 292449) @@ -1,296 +1,294 @@ /*- * Copyright (c) 2004 Apple Inc. * Copyright (c) 2006 Robert N. M. Watson * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_user.c#20 $ */ #include #include #include #ifdef HAVE_PTHREAD_MUTEX_LOCK #include #endif #include #include #ifndef HAVE_STRLCPY #include #endif /* * Parse the contents of the audit_user file into au_user_ent structures. */ static FILE *fp = NULL; static char linestr[AU_LINE_MAX]; static const char *user_delim = ":"; #ifdef HAVE_PTHREAD_MUTEX_LOCK static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; #endif /* * Parse one line from the audit_user file into the au_user_ent structure. */ static struct au_user_ent * userfromstr(char *str, struct au_user_ent *u) { char *username, *always, *never; char *last; username = strtok_r(str, user_delim, &last); always = strtok_r(NULL, user_delim, &last); never = strtok_r(NULL, user_delim, &last); if ((username == NULL) || (always == NULL) || (never == NULL)) return (NULL); if (strlen(username) >= AU_USER_NAME_MAX) return (NULL); strlcpy(u->au_name, username, AU_USER_NAME_MAX); if (getauditflagsbin(always, &(u->au_always)) == -1) return (NULL); if (getauditflagsbin(never, &(u->au_never)) == -1) return (NULL); return (u); } /* * Rewind to beginning of the file */ static void setauuser_locked(void) { if (fp != NULL) fseek(fp, 0, SEEK_SET); } void setauuser(void) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif setauuser_locked(); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif } /* * Close the file descriptor */ void endauuser(void) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif if (fp != NULL) { fclose(fp); fp = NULL; } #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif } /* * Enumerate the au_user_ent structures from the file */ static struct au_user_ent * getauuserent_r_locked(struct au_user_ent *u) { char *nl; if ((fp == NULL) && ((fp = fopen(AUDIT_USER_FILE, "r")) == NULL)) return (NULL); while (1) { if (fgets(linestr, AU_LINE_MAX, fp) == NULL) return (NULL); /* Remove new lines. */ if ((nl = strrchr(linestr, '\n')) != NULL) *nl = '\0'; /* Skip comments. */ if (linestr[0] == '#') continue; /* Get the next structure. */ if (userfromstr(linestr, u) == NULL) return (NULL); break; } return (u); } struct au_user_ent * getauuserent_r(struct au_user_ent *u) { struct au_user_ent *up; #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif up = getauuserent_r_locked(u); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (up); } struct au_user_ent * getauuserent(void) { static char user_ent_name[AU_USER_NAME_MAX]; static struct au_user_ent u; bzero(&u, sizeof(u)); bzero(user_ent_name, sizeof(user_ent_name)); u.au_name = user_ent_name; return (getauuserent_r(&u)); } /* * Find a au_user_ent structure matching the given user name. */ struct au_user_ent * getauusernam_r(struct au_user_ent *u, const char *name) { struct au_user_ent *up; if (name == NULL) return (NULL); #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_lock(&mutex); #endif setauuser_locked(); while ((up = getauuserent_r_locked(u)) != NULL) { if (strcmp(name, u->au_name) == 0) { #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (up); } } #ifdef HAVE_PTHREAD_MUTEX_LOCK pthread_mutex_unlock(&mutex); #endif return (NULL); } struct au_user_ent * getauusernam(const char *name) { static char user_ent_name[AU_USER_NAME_MAX]; static struct au_user_ent u; bzero(&u, sizeof(u)); bzero(user_ent_name, sizeof(user_ent_name)); u.au_name = user_ent_name; return (getauusernam_r(&u, name)); } /* * Read the default system wide audit classes from audit_control, combine with * the per-user audit class and update the binary preselection mask. */ int au_user_mask(char *username, au_mask_t *mask_p) { char auditstring[MAX_AUDITSTRING_LEN + 1]; char user_ent_name[AU_USER_NAME_MAX]; struct au_user_ent u, *up; bzero(&u, sizeof(u)); bzero(user_ent_name, sizeof(user_ent_name)); u.au_name = user_ent_name; /* Get user mask. */ if ((up = getauusernam_r(&u, username)) != NULL) { if (-1 == getfauditflags(&up->au_always, &up->au_never, mask_p)) return (-1); return (0); } /* Read the default system mask. */ if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) { if (-1 == getauditflagsbin(auditstring, mask_p)) return (-1); return (0); } /* No masks defined. */ return (-1); } /* * Generate the process audit state by combining the audit masks passed as * parameters with the system audit masks. */ int getfauditflags(au_mask_t *usremask, au_mask_t *usrdmask, au_mask_t *lastmask) { char auditstring[MAX_AUDITSTRING_LEN + 1]; if ((usremask == NULL) || (usrdmask == NULL) || (lastmask == NULL)) return (-1); lastmask->am_success = 0; lastmask->am_failure = 0; /* Get the system mask. */ if (getacflg(auditstring, MAX_AUDITSTRING_LEN) == 0) { if (getauditflagsbin(auditstring, lastmask) != 0) return (-1); } ADDMASK(lastmask, usremask); SUBMASK(lastmask, usrdmask); return (0); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_wrappers.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_wrappers.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/bsm_wrappers.c (revision 292449) @@ -1,823 +1,821 @@ /*- * Copyright (c) 2004-2009 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/libbsm/bsm_wrappers.c#32 $ */ #ifdef __APPLE__ #define _SYS_AUDIT_H /* Prevent include of sys/audit.h. */ #endif #include #include #ifdef __APPLE__ #include /* Our bsm/audit.h doesn't include queue.h. */ #endif #include #include #include #include #include #include #include /* These are not advertised in libbsm.h */ int audit_set_terminal_port(dev_t *p); int audit_set_terminal_host(uint32_t *m); /* * General purpose audit submission mechanism for userspace. */ int audit_submit(short au_event, au_id_t auid, char status, int reterr, const char *fmt, ...) { char text[MAX_AUDITSTRING_LEN]; token_t *token; int acond; va_list ap; pid_t pid; int error, afd, subj_ex; struct auditinfo ai; struct auditinfo_addr aia; au_tid_t atid; if (audit_get_cond(&acond) != 0) { /* * If auditon(2) returns ENOSYS, then audit has not been * compiled into the kernel, so just return. */ if (errno == ENOSYS) return (0); error = errno; syslog(LOG_AUTH | LOG_ERR, "audit: auditon failed: %s", strerror(errno)); errno = error; return (-1); } if (acond == AUC_NOAUDIT) return (0); afd = au_open(); if (afd < 0) { error = errno; syslog(LOG_AUTH | LOG_ERR, "audit: au_open failed: %s", strerror(errno)); errno = error; return (-1); } /* * Try to use getaudit_addr(2) first. If this kernel does not support * it, then fall back on to getaudit(2). */ subj_ex = 0; error = getaudit_addr(&aia, sizeof(aia)); if (error < 0 && errno == ENOSYS) { error = getaudit(&ai); if (error < 0) { error = errno; syslog(LOG_AUTH | LOG_ERR, "audit: getaudit failed: %s", strerror(errno)); errno = error; return (-1); } /* * Convert this auditinfo_t to an auditinfo_addr_t to make the * following code less complicated wrt to preselection and * subject token generation. */ aia.ai_auid = ai.ai_auid; aia.ai_mask = ai.ai_mask; aia.ai_asid = ai.ai_asid; aia.ai_termid.at_type = AU_IPv4; aia.ai_termid.at_addr[0] = ai.ai_termid.machine; aia.ai_termid.at_port = ai.ai_termid.port; } else if (error < 0) { error = errno; syslog(LOG_AUTH | LOG_ERR, "audit: getaudit_addr failed: %s", strerror(errno)); errno = error; return (-1); } /* * NB: We should be performing pre-selection here now that we have the * masks for this process. */ if (aia.ai_termid.at_type == AU_IPv6) subj_ex = 1; pid = getpid(); if (subj_ex == 0) { atid.port = aia.ai_termid.at_port; atid.machine = aia.ai_termid.at_addr[0]; token = au_to_subject32(auid, geteuid(), getegid(), getuid(), getgid(), pid, pid, &atid); } else token = au_to_subject_ex(auid, geteuid(), getegid(), getuid(), getgid(), pid, pid, &aia.ai_termid); if (token == NULL) { syslog(LOG_AUTH | LOG_ERR, "audit: unable to build subject token"); (void) au_close(afd, AU_TO_NO_WRITE, au_event); errno = EPERM; return (-1); } if (au_write(afd, token) < 0) { error = errno; syslog(LOG_AUTH | LOG_ERR, "audit: au_write failed: %s", strerror(errno)); (void) au_close(afd, AU_TO_NO_WRITE, au_event); errno = error; return (-1); } if (fmt != NULL) { va_start(ap, fmt); (void) vsnprintf(text, MAX_AUDITSTRING_LEN, fmt, ap); va_end(ap); token = au_to_text(text); if (token == NULL) { syslog(LOG_AUTH | LOG_ERR, "audit: failed to generate text token"); (void) au_close(afd, AU_TO_NO_WRITE, au_event); errno = EPERM; return (-1); } if (au_write(afd, token) < 0) { error = errno; syslog(LOG_AUTH | LOG_ERR, "audit: au_write failed: %s", strerror(errno)); (void) au_close(afd, AU_TO_NO_WRITE, au_event); errno = error; return (-1); } } token = au_to_return32(au_errno_to_bsm(status), reterr); if (token == NULL) { syslog(LOG_AUTH | LOG_ERR, "audit: unable to build return token"); (void) au_close(afd, AU_TO_NO_WRITE, au_event); errno = EPERM; return (-1); } if (au_write(afd, token) < 0) { error = errno; syslog(LOG_AUTH | LOG_ERR, "audit: au_write failed: %s", strerror(errno)); (void) au_close(afd, AU_TO_NO_WRITE, au_event); errno = error; return (-1); } if (au_close(afd, AU_TO_WRITE, au_event) < 0) { error = errno; syslog(LOG_AUTH | LOG_ERR, "audit: record not committed"); errno = error; return (-1); } return (0); } int audit_set_terminal_port(dev_t *p) { struct stat st; if (p == NULL) return (kAUBadParamErr); #ifdef NODEV *p = NODEV; #else *p = -1; #endif /* for /usr/bin/login, try fstat() first */ if (fstat(STDIN_FILENO, &st) != 0) { if (errno != EBADF) { syslog(LOG_ERR, "fstat() failed (%s)", strerror(errno)); return (kAUStatErr); } if (stat("/dev/console", &st) != 0) { syslog(LOG_ERR, "stat() failed (%s)", strerror(errno)); return (kAUStatErr); } } *p = st.st_rdev; return (kAUNoErr); } int audit_set_terminal_host(uint32_t *m) { #ifdef KERN_HOSTID int name[2] = { CTL_KERN, KERN_HOSTID }; size_t len; if (m == NULL) return (kAUBadParamErr); *m = 0; len = sizeof(*m); if (sysctl(name, 2, m, &len, NULL, 0) != 0) { syslog(LOG_ERR, "sysctl() failed (%s)", strerror(errno)); return (kAUSysctlErr); } return (kAUNoErr); #else *m = -1; return (kAUNoErr); #endif } int audit_set_terminal_id(au_tid_t *tid) { int ret; if (tid == NULL) return (kAUBadParamErr); if ((ret = audit_set_terminal_port(&tid->port)) != kAUNoErr) return (ret); return (audit_set_terminal_host(&tid->machine)); } /* * This is OK for those callers who have only one token to write. If you have * multiple tokens that logically form part of the same audit record, you need * to use the existing au_open()/au_write()/au_close() API: * * aufd = au_open(); * tok = au_to_random_token_1(...); * au_write(aufd, tok); * tok = au_to_random_token_2(...); * au_write(aufd, tok); * ... * au_close(aufd, AU_TO_WRITE, AUE_your_event_type); * * Assumes, like all wrapper calls, that the caller has previously checked * that auditing is enabled via the audit_get_state() call. * * XXX: Should be more robust against bad arguments. */ int audit_write(short event_code, token_t *subject, token_t *misctok, char retval, int errcode) { int aufd; char *func = "audit_write()"; token_t *rettok; if ((aufd = au_open()) == -1) { au_free_token(subject); au_free_token(misctok); syslog(LOG_ERR, "%s: au_open() failed", func); return (kAUOpenErr); } /* Save subject. */ if (subject && au_write(aufd, subject) == -1) { au_free_token(subject); au_free_token(misctok); (void)au_close(aufd, AU_TO_NO_WRITE, event_code); syslog(LOG_ERR, "%s: write of subject failed", func); return (kAUWriteSubjectTokErr); } /* Save the event-specific token. */ if (misctok && au_write(aufd, misctok) == -1) { au_free_token(misctok); (void)au_close(aufd, AU_TO_NO_WRITE, event_code); syslog(LOG_ERR, "%s: write of caller token failed", func); return (kAUWriteCallerTokErr); } /* Tokenize and save the return value. */ if ((rettok = au_to_return32(retval, errcode)) == NULL) { (void)au_close(aufd, AU_TO_NO_WRITE, event_code); syslog(LOG_ERR, "%s: au_to_return32() failed", func); return (kAUMakeReturnTokErr); } if (au_write(aufd, rettok) == -1) { au_free_token(rettok); (void)au_close(aufd, AU_TO_NO_WRITE, event_code); syslog(LOG_ERR, "%s: write of return code failed", func); return (kAUWriteReturnTokErr); } /* * We assume the caller wouldn't have bothered with this * function if it hadn't already decided to keep the record. */ if (au_close(aufd, AU_TO_WRITE, event_code) < 0) { syslog(LOG_ERR, "%s: au_close() failed", func); return (kAUCloseErr); } return (kAUNoErr); } /* * Same caveats as audit_write(). In addition, this function explicitly * assumes success; use audit_write_failure() on error. */ int audit_write_success(short event_code, token_t *tok, au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_t *tid) { char *func = "audit_write_success()"; token_t *subject = NULL; /* Tokenize and save subject. */ subject = au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid, tid); if (subject == NULL) { syslog(LOG_ERR, "%s: au_to_subject32() failed", func); return kAUMakeSubjectTokErr; } return (audit_write(event_code, subject, tok, 0, 0)); } /* * Same caveats as audit_write(). In addition, this function explicitly * assumes success; use audit_write_failure_self() on error. */ int audit_write_success_self(short event_code, token_t *tok) { token_t *subject; char *func = "audit_write_success_self()"; if ((subject = au_to_me()) == NULL) { syslog(LOG_ERR, "%s: au_to_me() failed", func); return (kAUMakeSubjectTokErr); } return (audit_write(event_code, subject, tok, 0, 0)); } /* * Same caveats as audit_write(). In addition, this function explicitly * assumes failure; use audit_write_success() otherwise. * * XXX This should let the caller pass an error return value rather than * hard-coding -1. */ int audit_write_failure(short event_code, char *errmsg, int errcode, au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_t *tid) { char *func = "audit_write_failure()"; token_t *subject, *errtok; subject = au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid, tid); if (subject == NULL) { syslog(LOG_ERR, "%s: au_to_subject32() failed", func); return (kAUMakeSubjectTokErr); } /* tokenize and save the error message */ if ((errtok = au_to_text(errmsg)) == NULL) { au_free_token(subject); syslog(LOG_ERR, "%s: au_to_text() failed", func); return (kAUMakeTextTokErr); } return (audit_write(event_code, subject, errtok, -1, errcode)); } /* * Same caveats as audit_write(). In addition, this function explicitly * assumes failure; use audit_write_success_self() otherwise. * * XXX This should let the caller pass an error return value rather than * hard-coding -1. */ int audit_write_failure_self(short event_code, char *errmsg, int errret) { char *func = "audit_write_failure_self()"; token_t *subject, *errtok; if ((subject = au_to_me()) == NULL) { syslog(LOG_ERR, "%s: au_to_me() failed", func); return (kAUMakeSubjectTokErr); } /* tokenize and save the error message */ if ((errtok = au_to_text(errmsg)) == NULL) { au_free_token(subject); syslog(LOG_ERR, "%s: au_to_text() failed", func); return (kAUMakeTextTokErr); } return (audit_write(event_code, subject, errtok, -1, errret)); } /* * For auditing errors during login. Such errors are implicitly * non-attributable (i.e., not ascribable to any user). * * Assumes, like all wrapper calls, that the caller has previously checked * that auditing is enabled via the audit_get_state() call. */ int audit_write_failure_na(short event_code, char *errmsg, int errret, uid_t euid, uid_t egid, pid_t pid, au_tid_t *tid) { return (audit_write_failure(event_code, errmsg, errret, -1, euid, egid, -1, -1, pid, -1, tid)); } /* END OF au_write() WRAPPERS */ #ifdef __APPLE__ void audit_token_to_au32(audit_token_t atoken, uid_t *auidp, uid_t *euidp, gid_t *egidp, uid_t *ruidp, gid_t *rgidp, pid_t *pidp, au_asid_t *asidp, au_tid_t *tidp) { if (auidp != NULL) *auidp = (uid_t)atoken.val[0]; if (euidp != NULL) *euidp = (uid_t)atoken.val[1]; if (egidp != NULL) *egidp = (gid_t)atoken.val[2]; if (ruidp != NULL) *ruidp = (uid_t)atoken.val[3]; if (rgidp != NULL) *rgidp = (gid_t)atoken.val[4]; if (pidp != NULL) *pidp = (pid_t)atoken.val[5]; if (asidp != NULL) *asidp = (au_asid_t)atoken.val[6]; if (tidp != NULL) { audit_set_terminal_host(&tidp->machine); tidp->port = (dev_t)atoken.val[7]; } } #endif /* !__APPLE__ */ int audit_get_cond(int *cond) { int ret; ret = auditon(A_GETCOND, cond, sizeof(*cond)); #ifdef A_OLDGETCOND if ((0 != ret) && EINVAL == errno) { long lcond = *cond; ret = auditon(A_OLDGETCOND, &lcond, sizeof(lcond)); *cond = (int)lcond; } #endif return (ret); } int audit_set_cond(int *cond) { int ret; ret = auditon(A_SETCOND, cond, sizeof(*cond)); #ifdef A_OLDSETCOND if ((0 != ret) && (EINVAL == errno)) { long lcond = (long)*cond; ret = auditon(A_OLDSETCOND, &lcond, sizeof(lcond)); *cond = (int)lcond; } #endif return (ret); } int audit_get_policy(int *policy) { int ret; ret = auditon(A_GETPOLICY, policy, sizeof(*policy)); #ifdef A_OLDGETPOLICY if ((0 != ret) && (EINVAL == errno)){ long lpolicy = (long)*policy; ret = auditon(A_OLDGETPOLICY, &lpolicy, sizeof(lpolicy)); *policy = (int)lpolicy; } #endif return (ret); } int audit_set_policy(int *policy) { int ret; ret = auditon(A_SETPOLICY, policy, sizeof(*policy)); #ifdef A_OLDSETPOLICY if ((0 != ret) && (EINVAL == errno)){ long lpolicy = (long)*policy; ret = auditon(A_OLDSETPOLICY, &lpolicy, sizeof(lpolicy)); *policy = (int)lpolicy; } #endif return (ret); } int audit_get_qctrl(au_qctrl_t *qctrl, size_t sz) { int ret; if (sizeof(*qctrl) != sz) { errno = EINVAL; return (-1); } ret = auditon(A_GETQCTRL, qctrl, sizeof(*qctrl)); #ifdef A_OLDGETQCTRL if ((0 != ret) && (EINVAL == errno)){ struct old_qctrl { size_t oq_hiwater; size_t oq_lowater; size_t oq_bufsz; clock_t oq_delay; int oq_minfree; } oq; oq.oq_hiwater = (size_t)qctrl->aq_hiwater; oq.oq_lowater = (size_t)qctrl->aq_lowater; oq.oq_bufsz = (size_t)qctrl->aq_bufsz; oq.oq_delay = (clock_t)qctrl->aq_delay; oq.oq_minfree = qctrl->aq_minfree; ret = auditon(A_OLDGETQCTRL, &oq, sizeof(oq)); qctrl->aq_hiwater = (int)oq.oq_hiwater; qctrl->aq_lowater = (int)oq.oq_lowater; qctrl->aq_bufsz = (int)oq.oq_bufsz; qctrl->aq_delay = (int)oq.oq_delay; qctrl->aq_minfree = oq.oq_minfree; } #endif /* A_OLDGETQCTRL */ return (ret); } int audit_set_qctrl(au_qctrl_t *qctrl, size_t sz) { int ret; if (sizeof(*qctrl) != sz) { errno = EINVAL; return (-1); } ret = auditon(A_SETQCTRL, qctrl, sz); #ifdef A_OLDSETQCTRL if ((0 != ret) && (EINVAL == errno)) { struct old_qctrl { size_t oq_hiwater; size_t oq_lowater; size_t oq_bufsz; clock_t oq_delay; int oq_minfree; } oq; oq.oq_hiwater = (size_t)qctrl->aq_hiwater; oq.oq_lowater = (size_t)qctrl->aq_lowater; oq.oq_bufsz = (size_t)qctrl->aq_bufsz; oq.oq_delay = (clock_t)qctrl->aq_delay; oq.oq_minfree = qctrl->aq_minfree; ret = auditon(A_OLDSETQCTRL, &oq, sizeof(oq)); qctrl->aq_hiwater = (int)oq.oq_hiwater; qctrl->aq_lowater = (int)oq.oq_lowater; qctrl->aq_bufsz = (int)oq.oq_bufsz; qctrl->aq_delay = (int)oq.oq_delay; qctrl->aq_minfree = oq.oq_minfree; } #endif /* A_OLDSETQCTRL */ return (ret); } int audit_send_trigger(int *trigger) { return (auditon(A_SENDTRIGGER, trigger, sizeof(*trigger))); } int audit_get_kaudit(auditinfo_addr_t *aia, size_t sz) { if (sizeof(*aia) != sz) { errno = EINVAL; return (-1); } return (auditon(A_GETKAUDIT, aia, sz)); } int audit_set_kaudit(auditinfo_addr_t *aia, size_t sz) { if (sizeof(*aia) != sz) { errno = EINVAL; return (-1); } return (auditon(A_SETKAUDIT, aia, sz)); } int audit_get_class(au_evclass_map_t *evc_map, size_t sz) { if (sizeof(*evc_map) != sz) { errno = EINVAL; return (-1); } return (auditon(A_GETCLASS, evc_map, sz)); } int audit_set_class(au_evclass_map_t *evc_map, size_t sz) { if (sizeof(*evc_map) != sz) { errno = EINVAL; return (-1); } return (auditon(A_SETCLASS, evc_map, sz)); } int audit_get_kmask(au_mask_t *kmask, size_t sz) { if (sizeof(*kmask) != sz) { errno = EINVAL; return (-1); } return (auditon(A_GETKMASK, kmask, sz)); } int audit_set_kmask(au_mask_t *kmask, size_t sz) { if (sizeof(*kmask) != sz) { errno = EINVAL; return (-1); } return (auditon(A_SETKMASK, kmask, sz)); } int audit_get_fsize(au_fstat_t *fstat, size_t sz) { if (sizeof(*fstat) != sz) { errno = EINVAL; return (-1); } return (auditon(A_GETFSIZE, fstat, sz)); } int audit_set_fsize(au_fstat_t *fstat, size_t sz) { if (sizeof(*fstat) != sz) { errno = EINVAL; return (-1); } return (auditon(A_SETFSIZE, fstat, sz)); } int audit_set_pmask(auditpinfo_t *api, size_t sz) { if (sizeof(*api) != sz) { errno = EINVAL; return (-1); } return (auditon(A_SETPMASK, api, sz)); } int audit_get_pinfo(auditpinfo_t *api, size_t sz) { if (sizeof(*api) != sz) { errno = EINVAL; return (-1); } return (auditon(A_GETPINFO, api, sz)); } int audit_get_pinfo_addr(auditpinfo_addr_t *apia, size_t sz) { if (sizeof(*apia) != sz) { errno = EINVAL; return (-1); } return (auditon(A_GETPINFO_ADDR, apia, sz)); } int audit_get_sinfo_addr(auditinfo_addr_t *aia, size_t sz) { if (sizeof(*aia) != sz) { errno = EINVAL; return (-1); } return (auditon(A_GETSINFO_ADDR, aia, sz)); } int audit_get_stat(au_stat_t *stats, size_t sz) { if (sizeof(*stats) != sz) { errno = EINVAL; return (-1); } return (auditon(A_GETSTAT, stats, sz)); } int audit_set_stat(au_stat_t *stats, size_t sz) { if (sizeof(*stats) != sz) { errno = EINVAL; return (-1); } return (auditon(A_GETSTAT, stats, sz)); } int audit_get_cwd(char *path, size_t sz) { return (auditon(A_GETCWD, path, sz)); } int audit_get_car(char *path, size_t sz) { return (auditon(A_GETCAR, path, sz)); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/libbsm.3 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/libbsm.3 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/libbsm/libbsm.3 (revision 292449) @@ -1,250 +1,248 @@ .\"- .\" Copyright (c) 2005-2007 Robert N. M. Watson .\" Copyright (c) 2008-2009 Apple Inc. .\" 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 AUTHORS 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 AUTHORS 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. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/libbsm/libbsm.3#17 $ -.\" .Dd March 5, 2009 .Dt LIBBSM 3 .Os .Sh NAME .Nm libbsm .Nd "Basic Security Module (BSM) Audit API" .Sh LIBRARY .Lb libbsm .Sh SYNOPSIS .In bsm/libbsm.h .Sh DESCRIPTION The .Nm library routines provide an interface to BSM audit record streams, allowing both the parsing of existing audit streams, as well as the creation of new audit records and streams. .Sh INTERFACES The .Nm library provides a large number of Audit programming interfaces in several classes: event stream interfaces, class interfaces, control interfaces, event interfaces, I/O interfaces, mask interfaces, notification interfaces, token interfaces, and user interfaces. These are described respectively in the .Xr au_class 3 , .Xr au_control 3 , .Xr au_event 3 , .Xr au_mask 3 , .Xr au_notify 3 , .Xr au_stream 3 , .Xr au_token 3 , and .Xr au_user 3 manual pages. .Ss Audit Event Stream Interfaces Audit event stream interfaces support interaction with file-backed audit event streams: .Xr au_close 3 , .Xr au_close_buffer 3 , .Xr au_free_token 3 , .Xr au_open 3 , .Xr au_write 3 , .Xr audit_submit 3 . .Ss Audit Class Interfaces Audit class interfaces support the look up of information from the .Xr audit_class 5 database: .Xr endauclass 3 , .Xr getauclassent 3 , .Xr getauclassent_r 3 , .Xr getauclassnam 3 , .Xr getauclassnam_r 3 , .Xr setauclass 3 . .Ss Audit Control Interfaces Audit control interfaces support the look up of information from the .Xr audit_control 5 database: .Xr endac 3 , .Xr setac 3 , .Xr getacdir 3 , .Xr getacfilesz 3 , .Xr getacflg 3 , .Xr getacmin 3 , .Xr getacna 3 , .Xr getacpol 3 , .Xr au_poltostr 3 , .Xr au_strtopol 3 . .Ss Audit Event Interfaces Audit event interfaces support the look up of information from the .Xr audit_event 5 database: .Xr endauevent 3 , .Xr setauevent 3 , .Xr getauevent 3 , .Xr getauevent_r 3 , .Xr getauevnam 3 , .Xr getauevnam_r 3 , .Xr getauevnonam 3 , .Xr getauevnonam_r 3 , .Xr getauevnum 3 , .Xr getauevnum_r 3 . .Ss Audit I/O Interfaces Audit I/O interfaces support the processing and printing of tokens, as well as the reading of audit records: .Xr au_fetch_tok 3 , .Xr au_print_tok 3 , .Xr au_read_rec 3 . .Ss Audit Mask Interfaces Audit mask interfaces convert support the conversion between strings and .Vt au_mask_t values. They may also be used to determine if a particular audit event is matched by a mask: .Xr au_preselect 3 , .Xr getauditflagsbin 3 , .Xr getauditflagschar 3 . .Ss Audit Notification Interfaces Audit notification routines track audit state in a form permitting efficient update, avoiding frequent system calls to check the kernel audit state: .Xr au_get_state 3 , .Xr au_notify_initialize 3 , .Xr au_notify_terminate 3 . These interfaces are implemented only for Darwin/Mac OS X. .Ss Audit Token Interface Audit token interfaces permit the creation of tokens for use in creating audit records for submission to event streams. Each interface converts a C type to its .Vt token_t representation: .Xr au_to_arg 3 , .Xr au_to_arg32 3 , .Xr au_to_arg64 3 , .Xr au_to_attr64 3 , .Xr au_to_data 3 , .Xr au_to_exec_args 3 , .Xr au_to_exec_env 3 , .Xr au_to_exit 3 , .Xr au_to_file 3 , .Xr au_to_groups 3 , .Xr au_to_header32 3 , .Xr au_to_header64 3 , .Xr au_to_in_addr 3 , .Xr au_to_in_addr_ex 3 , .Xr au_to_ip 3 , .Xr au_to_ipc 3 , .Xr au_to_ipc_perm 3 , .Xr au_to_iport 3 , .Xr au_to_me 3 , .Xr au_to_newgroups 3 , .Xr au_to_opaque 3 , .Xr au_to_path 3 , .Xr au_to_process 3 , .Xr au_to_process32 3 , .Xr au_to_process64 3 , .Xr au_to_process_ex 3 , .Xr au_to_process32_ex 3 , .Xr au_to_process64_ex 3 , .Xr au_to_return 3 , .Xr au_to_return32 3 , .Xr au_to_return64 3 , .Xr au_to_seq 3 , .Xr au_to_sock_inet 3 , .Xr au_to_sock_inet32 3 , .Xr au_to_sock_inet128 3 , .Xr au_to_socket_ex 3 , .Xr au_to_subject 3 , .Xr au_to_subject32 3 , .Xr au_to_subject64 3 , .Xr au_to_subject_ex 3 , .Xr au_to_subject32_ex 3 , .Xr au_to_subject64_ex 3 , .Xr au_to_text 3 , .Xr au_to_trailer 3 , .Xr au_to_zonename 3 . .Ss Audit User Interfaces Audit user interfaces support the look up of information from the .Xr audit_user 5 database: .Xr au_user_mask 3 , .Xr endauuser 3 , .Xr setauuser 3 , .Xr getauuserent 3 , .Xr getauuserent_r 3 , .Xr getauusernam 3 , .Xr getauusernam_r 3 , .Xr getfauditflags 3 . .Ss Audit Constant Conversion Interfaces These functions convert between BSM and local constants, including the .Xr errno 2 number, socket type, and protocol famil spaces, and must be used to generate and interpret BSM return and extended socket tokens: .Xr au_bsm_to_domain 3 , .Xr au_bsm_to_errno 3 , .Xr au_bsm_to_fcntl_cmd 3 , .Xr au_bsm_to_socket_type 3 , .Xr au_domain_to_bsm 3 , .Xr au_errno_to_bsm 3 , .Xr au_fcntl_cmd_to_bsm 3 , .Xr au_socket_type_to_bsm 3 . .Sh SEE ALSO .Xr au_class 3 , .Xr au_domain 3 , .Xr au_errno 3 , .Xr au_mask 3 , .Xr au_notify 3 , .Xr au_socket_type 3 , .Xr au_stream 3 , .Xr au_token 3 , .Xr au_user 3 , .Xr audit_submit 3 , .Xr audit_class 5 , .Xr audit_control 5 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer, Inc., in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by .An Robert Watson , .An Wayne Salamon , and .An Suresh Krishnaswamy for McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer, Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. .Sh BUGS Bugs would not be unlikely. .Pp The .Nm library implementations are generally thread-safe, but not reentrant. .Pp The assignment of routines to classes could use some work, as it is decidely ad hoc. For example, .Fn au_read_rec should probably be considered a stream routine. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/man/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/man/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/man/Makefile.am (revision 292449) @@ -1,24 +1,21 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/man/Makefile.am#2 $ -## - man2_MANS = \ audit.2 \ auditctl.2 \ auditon.2 \ getaudit.2 \ getauid.2 \ setaudit.2 \ setauid.2 man5_MANS = \ audit.log.5 \ audit_class.5 \ audit_control.5 \ audit_event.5 \ audit_user.5 \ audit_warn.5 -# How to do MLINKS in automake? -# MLINKS= getaudit.2 getaudit_addr.2 \ -# setaudit.2 setaudit_addr.2 +install-exec-hook: + cd $(DESTDIR)$(mandir) && \ + $(LN_S) -f getaudit.2 getaudit_addr.2 && \ + $(LN_S) -f setaudit.2 setaudit_addr.2 Index: user/alc/PQ_LAUNDRY/contrib/openbsm/man/Makefile.in =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/man/Makefile.in (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/man/Makefile.in (revision 292449) @@ -1,539 +1,541 @@ # Makefile.in generated by automake 1.12.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 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__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } 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 = man DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = 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; }; \ } man2dir = $(mandir)/man2 am__installdirs = "$(DESTDIR)$(man2dir)" "$(DESTDIR)$(man5dir)" man5dir = $(mandir)/man5 NROFF = nroff MANS = $(man2_MANS) $(man5_MANS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ 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@ 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@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MIG = @MIG@ 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@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ 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_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@ 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@ 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@ man2_MANS = \ audit.2 \ auditctl.2 \ auditon.2 \ getaudit.2 \ getauid.2 \ setaudit.2 \ setauid.2 man5_MANS = \ audit.log.5 \ audit_class.5 \ audit_control.5 \ audit_event.5 \ audit_user.5 \ audit_warn.5 all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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 man/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign man/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(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-man2: $(man2_MANS) @$(NORMAL_INSTALL) @list1='$(man2_MANS)'; \ list2=''; \ test -n "$(man2dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man2dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man2dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.2[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^2][0-9a-z]*$$,2,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man2dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man2dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man2dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man2dir)" || exit $$?; }; \ done; } uninstall-man2: @$(NORMAL_UNINSTALL) @list='$(man2_MANS)'; test -n "$(man2dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^2][0-9a-z]*$$,2,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man2dir)'; $(am__uninstall_files_from_dir) install-man5: $(man5_MANS) @$(NORMAL_INSTALL) @list1='$(man5_MANS)'; \ list2=''; \ test -n "$(man5dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.5[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ done; } uninstall-man5: @$(NORMAL_UNINSTALL) @list='$(man5_MANS)'; test -n "$(man5dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) tags: TAGS TAGS: ctags: CTAGS CTAGS: cscope cscopelist: distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically 'make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @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 $(MANS) installdirs: for dir in "$(DESTDIR)$(man2dir)" "$(DESTDIR)$(man5dir)"; 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." 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-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: - + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man2 install-man5 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-man uninstall-man: uninstall-man2 uninstall-man5 -.MAKE: install-am install-strip +.MAKE: install-am install-exec-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ 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-man2 \ - install-man5 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 uninstall uninstall-am uninstall-man uninstall-man2 \ - uninstall-man5 + install-exec install-exec-am install-exec-hook install-html \ + install-html-am install-info install-info-am install-man \ + install-man2 install-man5 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 uninstall uninstall-am \ + uninstall-man uninstall-man2 uninstall-man5 -# How to do MLINKS in automake? -# MLINKS= getaudit.2 getaudit_addr.2 \ -# setaudit.2 setaudit_addr.2 +install-exec-hook: + cd $(DESTDIR)$(mandir) && \ + $(LN_S) -f getaudit.2 getaudit_addr.2 && \ + $(LN_S) -f setaudit.2 setaudit_addr.2 # 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: Index: user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit.2 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit.2 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit.2 (revision 292449) @@ -1,104 +1,102 @@ .\"- .\" Copyright (c) 2005 Tom Rhodes .\" Copyright (c) 2005 Robert N. M. Watson .\" 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/man/audit.2#9 $ -.\" .Dd April 19, 2005 .Dt AUDIT 2 .Os .Sh NAME .Nm audit .Nd "commit BSM audit record to audit log" .Sh SYNOPSIS .In bsm/audit.h .Ft int .Fn audit "const char *record" "u_int length" .Sh DESCRIPTION The .Fn audit system call submits a completed BSM audit record to the system audit log. .Pp The .Fa record argument is a pointer to the specific event to be recorded and .Fa length is the size in bytes of the data to be written. .Sh RETURN VALUES .Rv -std .Sh ERRORS The .Fn audit system call will fail and the data never written if: .Bl -tag -width Er .It Bq Er EFAULT The .Fa record argument is beyond the allocated address space of the process. .It Bq Er EINVAL The token ID is invalid or .Va length is larger than .Dv MAXAUDITDATA . .It Bq Er EPERM The process does not have sufficient permission to complete the operation. .El .Sh SEE ALSO .Xr auditon 2 , .Xr getaudit 2 , .Xr getaudit_addr 2 , .Xr getauid 2 , .Xr setaudit 2 , .Xr setaudit_addr 2 , .Xr setauid 2 , .Xr libbsm 3 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer Inc. Additional authors include .An Wayne Salamon , .An Robert Watson , and SPARTA Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. .Pp This manual page was written by .An Tom Rhodes Aq trhodes@FreeBSD.org . .Sh BUGS The .Fx kernel does not fully validate that the argument passed is syntactically valid BSM. Submitting invalid audit records may corrupt the audit log. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit.log.5 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit.log.5 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit.log.5 (revision 292449) @@ -1,672 +1,670 @@ .\"- .\" Copyright (c) 2005-2006 Robert N. M. Watson .\" Copyright (c) 2008 Apple Inc. .\" 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/man/audit.log.5#26 $ -.\" .Dd November 5, 2006 .Dt AUDIT.LOG 5 .Os .Sh NAME .Nm audit .Nd "Basic Security Module (BSM) file format" .Sh DESCRIPTION The .Nm file format is based on Sun's Basic Security Module (BSM) file format, a token-based record stream to represent system audit data. This file format is both flexible and extensible, able to describe a broad range of data types, and easily extended to describe new data types in a moderately backward and forward compatible way. .Pp BSM token streams typically begin and end with a .Dq file token, which provides time stamp and file name information for the stream; when processing a BSM token stream from a stream as opposed to a single file source, file tokens may be seen at any point between ordinary records identifying when particular parts of the stream begin and end. All other tokens will appear in the context of a complete BSM audit record, which begins with a .Dq header token, and ends with a .Dq trailer token, which describe the audit record. Between these two tokens will appear a variety of data tokens, such as process information, file path names, IPC object information, MAC labels, socket information, and so on. .Pp The BSM file format defines specific token orders for each record event type; however, some variation may occur depending on the operating system in use, what system options, such as mandatory access control, are present. .Pp This manual page documents the common token types and their binary format, and is intended for reference purposes only. It is recommended that application programmers use the .Xr libbsm 3 interface to read and write tokens, rather than parsing or constructing records by hand. .Ss File Token The .Dq file token is used at the beginning and end of an audit log file to indicate when the audit log begins and ends. It includes a pathname so that, if concatenated together, original file boundaries are still observable, and gaps in the audit log can be identified. A .Dq file token can be created using .Xr au_to_file 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Seconds 4 bytes File time stamp" .It "Microseconds 4 bytes File time stamp" .It "File name length 2 bytes File name of audit trail" .It "File pathname N bytes + 1 NUL File name of audit trail" .El .Ss Header Token The .Dq header token is used to mark the beginning of a complete audit record, and includes the length of the total record in bytes, a version number for the record layout, the event type and subtype, and the time at which the event occurred. A 32-bit .Dq header token can be created using .Xr au_to_header32 3 ; a 64-bit .Dq header token can be created using .Xr au_to_header64 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Record Byte Count 4 bytes Number of bytes in record" .It "Version Number 2 bytes Record version number" .It "Event Type 2 bytes Event type" .It "Event Modifier 2 bytes Event sub-type" .It "Seconds 4/8 bytes Record time stamp (32/64-bits)" .It "Nanoseconds 4/8 bytes Record time stamp (32/64-bits)" .El .Ss Expanded Header Token The .Dq expanded header token is an expanded version of the .Dq header token, with the addition of a machine IPv4 or IPv6 address. A 32-bit extended .Dq header token can be created using .Xr au_to_header32_ex 3 ; a 64-bit extended .Dq header token can be created using .Xr au_to_header64_ex 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Record Byte Count 4 bytes Number of bytes in record" .It "Version Number 2 bytes Record version number" .It "Event Type 2 bytes Event type" .It "Event Modifier 2 bytes Event sub-type" .It "Address Type/Length 1 byte Host address type and length" .It "Machine Address 4/16 bytes IPv4 or IPv6 address" .It "Seconds 4/8 bytes Record time stamp (32/64-bits)" .It "Nanoseconds 4/8 bytes Record time stamp (32/64-bits)" .El .Ss Trailer Token The .Dq trailer terminates a BSM audit record, and contains a magic number, .Dv AUT_TRAILER_MAGIC and length that can be used to validate that the record was read properly. A .Dq trailer token can be created using .Xr au_to_trailer 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Trailer Magic 2 bytes Trailer magic number" .It "Record Byte Count 4 bytes Number of bytes in record" .El .Ss Arbitrary Data Token The .Dq arbitrary data token contains a byte stream of opaque (untyped) data. The size of the data is calculated as the size of each unit of data multiplied by the number of units of data. A .Dq How to print field is present to specify how to print the data, but interpretation of that field is not currently defined. An .Dq arbitrary data token can be created using .Xr au_to_data 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "How to Print 1 byte User-defined printing information" .It "Basic Unit 1 byte Size of a unit in bytes" .It "Unit Count 1 byte Number of units of data present" .It "Data Items Variable User data" .El .Ss in_addr Token The .Dq in_addr token holds a network byte order IPv4 address. An .Dq in_addr token can be created using .Xr au_to_in_addr 3 for an IPv4 address. .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "IP Address 4 bytes IPv4 address" .El .Ss Expanded in_addr Token The .Dq in_addr_ex token holds a network byte order IPv4 or IPv6 address. An .Dq in_addr_ex token can be created using .Xr au_to_in_addr_ex 3 for an IPv6 address. .Pp See the .Sx BUGS section for information on the storage of this token. .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "IP Address Type 1 byte Type of address" .It "IP Address 4/16 bytes IPv4 or IPv6 address" .El .Ss ip Token The .Dq ip token contains an IP packet header in network byte order. An .Dq ip token can be created using .Xr au_to_ip 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Version and IHL 1 byte Version and IP header length" .It "Type of Service 1 byte IP TOS field" .It "Length 2 bytes IP packet length in network byte order" .It "ID 2 bytes IP header ID for reassembly" .It "Offset 2 bytes IP fragment offset and flags, network byte order" .It "TTL 1 byte IP Time-to-Live" .It "Protocol 1 byte IP protocol number" .It "Checksum 2 bytes IP header checksum, network byte order" .It "Source Address 4 bytes IPv4 source address" .It "Destination Address 4 bytes IPv4 destination address" .El .Ss iport Token The .Dq iport token stores an IP port number in network byte order. An .Dq iport token can be created using .Xr au_to_iport 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Port Number 2 bytes Port number in network byte order" .El .Ss Path Token The .Dq path token contains a pathname. A .Dq path token can be created using .Xr au_to_path 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Path Length 2 bytes Length of path in bytes" .It "Path N bytes + 1 NUL Path name" .El .Ss path_attr Token The .Dq path_attr token contains a set of NUL-terminated path names. The .Xr libbsm 3 API cannot currently create a .Dq path_attr token. .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Count 2 bytes Number of NUL-terminated string(s) in token" .It "Path Variable count NUL-terminated string(s)" .El .Ss Process Token The .Dq process token contains a description of the security properties of a process involved as the target of an auditable event, such as the destination for signal delivery. It should not be confused with the .Dq subject token, which describes the subject performing an auditable event. This includes both the traditional .Ux security properties, such as user IDs and group IDs, but also audit information such as the audit user ID and session. A .Dq process token can be created using .Xr au_to_process32 3 or .Xr au_to_process64 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Audit ID 4 bytes Audit user ID" .It "Effective User ID 4 bytes Effective user ID" .It "Effective Group ID 4 bytes Effective group ID" .It "Real User ID 4 bytes Real user ID" .It "Real Group ID 4 bytes Real group ID" .It "Process ID 4 bytes Process ID" .It "Session ID 4 bytes Audit session ID" .It "Terminal Port ID 4/8 bytes Terminal port ID (32/64-bits)" .It "Terminal Machine Address 4 bytes IP address of machine" .El .Ss Expanded Process Token The .Dq expanded process token contains the contents of the .Dq process token, with the addition of a machine address type and variable length address storage capable of containing IPv6 addresses. An .Dq expanded process token can be created using .Xr au_to_process32_ex 3 or .Xr au_to_process64_ex 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Audit ID 4 bytes Audit user ID" .It "Effective User ID 4 bytes Effective user ID" .It "Effective Group ID 4 bytes Effective group ID" .It "Real User ID 4 bytes Real user ID" .It "Real Group ID 4 bytes Real group ID" .It "Process ID 4 bytes Process ID" .It "Session ID 4 bytes Audit session ID" .It "Terminal Port ID 4/8 bytes Terminal port ID (32/64-bits)" .It "Terminal Address Type/Length 1 byte Length of machine address" .It "Terminal Machine Address 4 bytes IPv4 or IPv6 address of machine" .El .Ss Return Token The .Dq return token contains a system call or library function return condition, including return value and error number associated with the global variable .Er errno . A .Dq return token can be created using .Xr au_to_return32 3 or .Xr au_to_return64 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Error Number 1 byte Errno value, or 0 if undefined" .It "Return Value 4/8 bytes Return value (32/64-bits)" .El .Ss Subject Token The .Dq subject token contains information on the subject performing the operation described by an audit record, and includes similar information to that found in the .Dq process and .Dq expanded process tokens. However, those tokens are used where the process being described is the target of the operation, not the authorizing party. A .Dq subject token can be created using .Xr au_to_subject32 3 and .Xr au_to_subject64 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Audit ID 4 bytes Audit user ID" .It "Effective User ID 4 bytes Effective user ID" .It "Effective Group ID 4 bytes Effective group ID" .It "Real User ID 4 bytes Real user ID" .It "Real Group ID 4 bytes Real group ID" .It "Process ID 4 bytes Process ID" .It "Session ID 4 bytes Audit session ID" .It "Terminal Port ID 4/8 bytes Terminal port ID (32/64-bits)" .It "Terminal Machine Address 4 bytes IP address of machine" .El .Ss Expanded Subject Token The .Dq expanded subject token consists of the same elements as the .Dq subject token, with the addition of type/length and variable size machine address information in the terminal ID. An .Dq expanded subject token can be created using .Xr au_to_subject32_ex 3 or .Xr au_to_subject64_ex 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Audit ID 4 bytes Audit user ID" .It "Effective User ID 4 bytes Effective user ID" .It "Effective Group ID 4 bytes Effective group ID" .It "Real User ID 4 bytes Real user ID" .It "Real Group ID 4 bytes Real group ID" .It "Process ID 4 bytes Process ID" .It "Session ID 4 bytes Audit session ID" .It "Terminal Port ID 4/8 bytes Terminal port ID (32/64-bits)" .It "Terminal Address Type/Length 1 byte Length of machine address" .It "Terminal Machine Address 4 bytes IPv4 or IPv6 address of machine" .El .Ss System V IPC Token The .Dq System V IPC token contains the System V IPC message handle, semaphore handle or shared memory handle. A System V IPC token may be created using +.Xr au_to_ipc 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Object ID type 1 byte Object ID" .It "Object ID 4 bytes Object ID" .El .Ss Text Token The .Dq text token contains a single NUL-terminated text string. A .Dq text token may be created using .Xr au_to_text 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Text Length 2 bytes Length of text string including NUL" .It "Text N bytes + 1 NUL Text string including NUL" .El .Ss Attribute Token The .Dq attribute token describes the attributes of a file associated with the audit event. As files may be identified by 0, 1, or many path names, a path name is not included with the attribute block for a file; optional .Dq path tokens may also be present in an audit record indicating which path, if any, was used to reach the object. An .Dq attribute token can be created using .Xr au_to_attr32 3 or .Xr au_to_attr64 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "File Access Mode 1 byte mode_t associated with file" .It "Owner User ID 4 bytes uid_t associated with file" .It "Owner Group ID 4 bytes gid_t associated with file" .It "File System ID 4 bytes fsid_t associated with file" .It "File System Node ID 8 bytes ino_t associated with file" .It "Device 4/8 bytes Device major/minor number (32/64-bit)" .El .Ss Groups Token The .Dq groups token contains a list of group IDs associated with the audit event. A .Dq groups token can be created using .Xr au_to_groups 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Number of Groups 2 bytes Number of groups in token" .It "Group List N * 4 bytes List of N group IDs" .El .Ss System V IPC Permission Token The .Dq System V IPC permission token contains a System V IPC access permissions. A System V IPC permission token may be created using .Xr au_to_ipc_perm 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It Li "Owner user ID" Ta "4 bytes" Ta "User ID of IPC owner" .It Li "Owner group ID" Ta "4 bytes" Ta "Group ID of IPC owner" .It Li "Creator user ID" Ta "4 bytes" Ta "User ID of IPC creator" .It Li "Creator group ID" Ta "4 bytes" Ta "Group ID of IPC creator" .It Li "Access mode" Ta "4 bytes" Ta "Access mode" .It Li "Sequence number" Ta "4 bytes" Ta "Sequence number" .It Li "Key" Ta "4 bytes" Ta "IPC key" .El .Ss Arg Token The .Dq arg token contains information about arguments of the system call. Depending on the size of the desired argument value, an Arg token may be created using .Xr au_to_arg32 3 or .Xr au_to_arg64 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It Li "Argument ID" Ta "1 byte" Ta "Argument ID" .It Li "Argument value" Ta "4/8 bytes" Ta "Argument value" .It Li "Length" Ta "2 bytes" Ta "Length of the text" .It Li "Text" Ta "N bytes + 1 nul" Ta "The string including nul" .El .Ss exec_args Token The .Dq exec_args token contains information about arguments of the exec() system call. An exec_args token may be created using .Xr au_to_exec_args 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It Li "Count" Ta "4 bytes" Ta "Number of arguments" .It Li "Text" Ta "* bytes" Ta "Count nul-terminated strings" .El .Ss exec_env Token The .Dq exec_env token contains current environment variables to an exec() system call. An exec_args token may be created using .Xr au_to_exec_env 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It Li "Count ID" Ta "4 bytes" Ta "Number of variables" .It Li "Text" Ta "* bytes" Ta "Count nul-terminated strings" .El .Ss Exit Token The .Dq exit token contains process exit/return code information. An .Dq exit token can be created using .Xr au_to_exit 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Status 4 bytes Process status on exit" .It "Return Value 4 bytes Process return value on exit" .El .Ss Socket Token The .Dq socket token contains information about UNIX domain and Internet sockets. Each token has four or eight fields. Depending on the type of socket, a socket token may be created using .Xr au_to_sock_unix 3 , .Xr au_to_sock_inet32 3 or .Xr au_to_sock_inet128 3 . .Bl -column -offset 3n ".Sy Field Name Width XX" ".Sy XX Bytes XXXX" ".Sy Description" .It Sy "Field" Ta Sy Bytes Ta Sy Description .It Li "Token ID" Ta "1 byte" Ta "Token ID" .It Li "Socket family" Ta "2 bytes" Ta "Socket family" .It Li "Local port" Ta "2 bytes" Ta "Local port" .It Li "Socket address" Ta "4 bytes" Ta "Socket address" .El .Ss Expanded Socket Token The .Dq expanded socket token contains information about IPv4 and IPv6 sockets. A .Dq expanded socket token can be created using .Xr au_to_socket_ex 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It Li "Token ID" Ta "1 byte" Ta "Token ID" .It Li "Socket domain" Ta "2 bytes" Ta "Socket domain" .It Li "Socket type" Ta "2 bytes" Ta "Socket type" .It Li "Address type" Ta "2 byte" Ta "Address type (IPv4/IPv6)" .It Li "Local port" Ta "2 bytes" Ta "Local port" .It Li "Local IP address" Ta "4/16 bytes" Ta "Local IP address" .It Li "Remote port" Ta "2 bytes" Ta "Remote port" .It Li "Remote IP address" Ta "4/16 bytes" Ta "Remote IP address" .El .Ss Seq Token The .Dq seq token contains a unique and monotonically increasing audit event sequence ID. Due to the limited range of 32 bits, serial number arithmetic and caution should be used when comparing sequence numbers. .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Sequence Number 4 bytes Audit event sequence number" .El .Ss privilege Token The .Dq privilege token ... .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .El .Ss Use-of-auth Token The .Dq use-of-auth token ... .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .El .Ss Command Token The .Dq command token ... .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .El .Ss ACL Token The .Dq ACL token ... .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .El .Ss Zonename Token The .Dq zonename token holds a NUL-terminated string with the name of the zone or jail from which the record originated. A .Dq zonename token can be created using .Xr au_to_zonename 3 . .Bl -column -offset 3n ".No Terminal Address Type/Length" ".No N bytes + 1 NUL" .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Zonename length 2 bytes Length of zonename string including NUL" .It "Zonename N bytes + 1 NUL Zonename string including NUL" .El .Sh SEE ALSO .Xr auditreduce 1 , .Xr praudit 1 , .Xr libbsm 3 , .Xr audit 4 , .Xr auditpipe 4 , .Xr audit 8 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. .Pp This manual page was written by .An Robert Watson Aq rwatson@FreeBSD.org . .Sh BUGS The .Dq How to print field in the .Dq arbitrary data token has undefined values. .Pp The .Dq in_addr and .Dq in_addr_ex token layout documented here appears to be in conflict with the .Xr libbsm 3 implementation of .Xr au_to_in_addr_ex 3 . Index: user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit_class.5 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit_class.5 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit_class.5 (revision 292449) @@ -1,80 +1,78 @@ .\" Copyright (c) 2004 Apple Inc. .\" 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR .\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/man/audit_class.5#11 $ -.\" .Dd January 24, 2004 .Dt AUDIT_CLASS 5 .Os .Sh NAME .Nm audit_class .Nd "audit event class descriptions" .Sh DESCRIPTION The .Nm file contains descriptions of the auditable event classes on the system. Each auditable event is a member of an event class. Each line maps an audit event mask (bitmap) to a class and a description. Entries are of the form: .Pp .D1 Ar classmask Ns : Ns Ar eventclass Ns : Ns Ar description .Pp Example entries in this file are: .Bd -literal -offset indent 0x00000000:no:invalid class 0x00000001:fr:file read 0x00000002:fw:file write 0x00000004:fa:file attribute access 0x00000080:pc:process 0xffffffff:all:all flags set .Ed .Sh FILES .Bl -tag -width ".Pa /etc/security/audit_class" -compact .It Pa /etc/security/audit_class .El .Sh SEE ALSO .Xr audit 4 , .Xr audit_control 5 , .Xr audit_event 5 , .Xr audit_user 5 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer Inc. Additional authors include .An Wayne Salamon , .An Robert Watson , and SPARTA Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit_control.5 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit_control.5 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit_control.5 (revision 292449) @@ -1,297 +1,295 @@ .\" Copyright (c) 2004-2009 Apple Inc. .\" Copyright (c) 2006 Robert N. M. Watson .\" 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR .\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/man/audit_control.5#26 $ -.\" .Dd May 14, 2009 .Dt AUDIT_CONTROL 5 .Os .Sh NAME .Nm audit_control .Nd "audit system parameters" .Sh DESCRIPTION The .Nm file contains several audit system parameters. Each line of this file is of the form: .Pp .D1 Ar parameter Ns : Ns Ar value .Pp The parameters are: .Bl -tag -width indent .It Va dir The directory where audit log files are stored. There may be more than one of these entries. Changes to this entry can only be enacted by restarting the audit system. See .Xr audit 8 for a description of how to restart the audit system. .It Va dist When set to .Va on or .Va yes , .Xr auditd 8 will be creating hardlinks to all trail files in .Pa /var/audit/dist directory. Those hardlinks will be consumed by the .Xr auditdistd 8 daemon. .It Va flags Specifies which audit event classes are audited for all users. .Xr audit_user 5 describes how to audit events for individual users. See the information below for the format of the audit flags. .It Va host Specify the hostname or IP address to be used when setting the local systems's audit host information. This hostname will be converted into an IP or IPv6 address and will be included in the header of each audit record. Due to the possibility of transient errors coupled with the security issues in the DNS protocol itself, the use of DNS should be avoided. Instead, it is strongly recommended that the hostname be specified in the /etc/hosts file. For more information see .Xr hosts 5 . .It Va naflags Contains the audit flags that define what classes of events are audited when an action cannot be attributed to a specific user. .It Va minfree The minimum free space required on the file system audit logs are being written to. When the free space falls below this limit a warning will be issued. If no value for the minimum free space is set, the default of 20 percent is applied by the kernel. .It Va policy A list of global audit policy flags specifying various behaviors, such as fail stop, auditing of paths and arguments, etc. .It Va filesz Maximum trail size in bytes; if set to a non-0 value, the audit daemon will rotate the audit trail file at around this size. Sizes less than the minimum trail size (default of 512K) will be rejected as invalid. If 0, trail files will not be automatically rotated based on file size. For convenience, the trail size may be expressed with suffix letters: B (Bytes), K (Kilobytes), M (Megabytes), or G (Gigabytes). For example, 2M is the same as 2097152. .It Va expire-after Specifies when audit log files will expire and be removed. This may be after a time period has passed since the file was last written to or when the aggregate of all the trail files have reached a specified size or a combination of both. If no expire-after parameter is given then audit log files will not expire and be removed by the audit control system. See the information below for the format of the expiration specification. .El .Sh AUDIT FLAGS Audit flags are a comma-delimited list of audit classes as defined in the .Xr audit_class 5 file. Event classes may be preceded by a prefix which changes their interpretation. The following prefixes may be used for each class: .Pp .Bl -tag -width indent -compact -offset indent .It (none) Record both successful and failed events. .It Li + Record successful events. .It Li - Record failed events. .It Li ^ Record neither successful nor failed events. .It Li ^+ Do not record successful events. .It Li ^- Do not record failed events. .El .Sh AUDIT POLICY FLAGS The policy flags field is a comma-delimited list of policy flags from the following list: .Pp .Bl -tag -width ".Cm zonename" -compact -offset indent .It Cm cnt Allow processes to continue running even though events are not being audited. If not set, processes will be suspended when the audit store space is exhausted. Currently, this is not a recoverable state. .It Cm ahlt Fail stop the system if unable to audit an event\[em]this consists of first draining pending records to disk, and then halting the operating system. .It Cm argv Audit command line arguments to .Xr execve 2 . .It Cm arge Audit environmental variable arguments to .Xr execve 2 . .It Cm seq Include a unique audit sequence number token in generated audit records (not implemented on .Fx or Darwin). .It Cm group Include supplementary groups list in generated audit records (not implemented on .Fx or Darwin; supplementary groups are never included in records on these systems). .It Cm trail Append a trailer token to each audit record (not implemented on .Fx or Darwin; trailers are always included in records on these systems). .It Cm path Include secondary file paths in audit records (not implemented on .Fx or Darwin; secondary paths are never included in records on these systems). .It Cm zonename Include a zone ID token with each audit record (not implemented on .Fx or Darwin; .Fx audit records do not currently include the jail ID or name). .It Cm perzone Enable auditing for each local zone (not implemented on .Fx or Darwin; on .Fx , audit records are collected from all jails and placed in a single global trail, and only limited audit controls are permitted within a jail). .El .Pp It is recommended that installations set the .Cm cnt flag but not .Cm ahlt flag unless it is intended that audit logs exceeding available disk space halt the system. .Sh AUDIT LOG EXPIRATION SPECIFICATION The expiration specification can be one value or two values with the logical conjunction of AND/OR between them. Values for the audit log file age are numbers with the following suffixes: .Pp .Bl -tag -width "(space) or" -compact -offset indent .It Li s Log file age in seconds. .It Li h Log file age in hours. .It Li d Log file age in days. .It Li y Log file age in years. .El .Pp Values for the disk space used are numbers with the following suffixes: .Pp .Bl -tag -width "(space) or" -compact -offset indent .It (space) or .It Li B Disk space used in Bytes. .It Li K Disk space used in Kilobytes. .It Li M Disk space used in Megabytes. .It Li G Disk space used in Gigabytes. .El .Pp The suffixes on the values are case sensitive. If both an age and disk space value are used they are separated by AND or OR and both values are used to determine when audit log files expire. In the case of AND, both the age and disk space conditions must be met before the log file is removed. In the case of OR, either condition may expire the log file. For example: .Bd -literal -offset indent expire-after: 60d AND 1G .Ed .Pp will expire files that are older than 60 days but only if 1 gigabyte of disk space total is being used by the audit logs. .Sh DEFAULT The following settings appear in the default .Nm file: .Bd -literal -offset indent dir:/var/audit flags:lo,aa minfree:5 naflags:lo,aa policy:cnt,argv filesz:2M expire-after:10M .Ed .Pp The .Va flags parameter above specifies the system-wide mask corresponding to login/logout as well as authentication and authorization events. The .Va policy parameter specifies that the system should neither fail stop nor suspend processes when the audit store fills and that command line arguments should be audited for .Dv AUE_EXECVE events. The trail file will be automatically rotated by the audit daemon when the file size reaches approximately 2MB. Trail files will expire when their aggregate size exceeds 10MB. .Sh FILES .Bl -tag -width ".Pa /etc/security/audit_control" -compact .It Pa /etc/security/audit_control .El .Sh SEE ALSO .Xr auditon 2 , .Xr audit 4 , .Xr audit_class 5 , .Xr audit_event 5 , .Xr audit_user 5 , .Xr audit 8 , .Xr auditd 8 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer Inc. Additional authors include .An Wayne Salamon , .An Robert Watson , and SPARTA Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit_event.5 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit_event.5 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit_event.5 (revision 292449) @@ -1,84 +1,82 @@ .\" Copyright (c) 2004 Apple Inc. .\" 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR .\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/man/audit_event.5#12 $ -.\" .Dd January 24, 2004 .Dt AUDIT_EVENT 5 .Os .Sh NAME .Nm audit_event .Nd "audit event descriptions" .Sh DESCRIPTION The .Nm file contains descriptions of the auditable events on the system. Each line maps an audit event number to a name, a description, and a class. Entries are of the form: .Pp .Sm off .D1 Ar eventnum : eventname : description : eventclass .Sm on .Pp Each .Ar eventclass should have a corresponding entry in the .Xr audit_class 5 file. .Pp Example entries in this file are: .Bd -literal -offset indent 0:AUE_NULL:indir system call:no 1:AUE_EXIT:exit(2):pc 2:AUE_FORK:fork(2):pc 3:AUE_OPEN:open(2):fa .Ed .Sh FILES .Bl -tag -width ".Pa /etc/security/audit_event" -compact .It Pa /etc/security/audit_event .El .Sh SEE ALSO .Xr audit 4 , .Xr audit_class 5 , .Xr audit_control 5 , .Xr audit_user 5 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer Inc. Additional authors include .An Wayne Salamon , .An Robert Watson , and SPARTA Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit_user.5 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit_user.5 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit_user.5 (revision 292449) @@ -1,120 +1,118 @@ .\" Copyright (c) 2004 Apple Inc. .\" 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR .\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/man/audit_user.5#14 $ -.\" .Dd January 4, 2008 .Dt AUDIT_USER 5 .Os .Sh NAME .Nm audit_user .Nd "events to be audited for given users" .Sh DESCRIPTION The .Nm file specifies which audit event classes are to be audited for the given users. If specified, these flags are combined with the system-wide audit flags in the .Xr audit_control 5 file to determine which classes of events to audit for that user. These settings take effect when the user logs in. .Pp Each line maps a user name to a list of classes that should be audited and a list of classes that should not be audited. Entries are of the form: .Pp .D1 Ar username Ns : Ns Ar alwaysaudit Ns : Ns Ar neveraudit .Pp In the format above, .Ar alwaysaudit is a set of event classes that are always audited, and .Ar neveraudit is a set of event classes that should not be audited. These sets can indicate the inclusion or exclusion of multiple classes, and whether to audit successful or failed events. See .Xr audit_control 5 for more information about audit flags. .Pp Example entries in this file are: .Bd -literal -offset indent root:lo,ad:no jdoe:-fc,ad:+fw .Ed .Pp These settings would cause login/logout and administrative events that are performed on behalf of user .Dq Li root to be audited. No failure events are audited. For the user .Dq Li jdoe , failed file creation events are audited, administrative events are audited, and successful file write events are never audited. .Sh IMPLEMENTATION NOTES Per-user and global audit preselection configuration are evaluated at time of login, so users must log out and back in again for audit changes relating to preselection to take effect. .Pp Audit record preselection occurs with respect to the audit identifier associated with a process, rather than with respect to the UNIX user or group ID. The audit identifier is set as part of the user credential context as part of login, and typically does not change as a result of running setuid or setgid applications, such as .Xr su 1 . This has the advantage that events that occur after running .Xr su 1 can be audited to the original authenticated user, as required by CAPP, but may be surprising if not expected. .Sh FILES .Bl -tag -width ".Pa /etc/security/audit_user" -compact .It Pa /etc/security/audit_user .El .Sh SEE ALSO .Xr login 1 , .Xr su 1 , .Xr audit 4 , .Xr audit_class 5 , .Xr audit_control 5 , .Xr audit_event 5 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer Inc. Additional authors include .An Wayne Salamon , .An Robert Watson , and SPARTA Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit_warn.5 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit_warn.5 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/man/audit_warn.5 (revision 292449) @@ -1,76 +1,74 @@ .\" Copyright (c) 2004 Apple Inc. .\" 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR .\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, .\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/man/audit_warn.5#10 $ -.\" .Dd March 17, 2004 .Dt AUDIT_WARN 5 .Os .Sh NAME .Nm audit_warn .Nd "alert when audit daemon issues warnings" .Sh DESCRIPTION The .Nm script runs when .Xr auditd 8 generates warning messages. .Pp The default .Nm is a script whose first parameter is the type of warning; the script appends its arguments to .Pa /etc/security/audit_messages . Administrators may replace this script: a more comprehensive one would take different actions based on the type of warning. For example, a low-space warning could result in an email message being sent to the administrator. .Sh FILES .Bl -tag -width ".Pa /etc/security/audit_messages" -compact .It Pa /etc/security/audit_warn .It Pa /etc/security/audit_messages .El .Sh SEE ALSO .Xr audit 4 , .Xr auditd 8 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer Inc. Additional authors include .An Wayne Salamon , .An Robert Watson , and SPARTA Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. Index: user/alc/PQ_LAUNDRY/contrib/openbsm/man/auditctl.2 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/man/auditctl.2 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/man/auditctl.2 (revision 292449) @@ -1,85 +1,83 @@ .\"- .\" Copyright (c) 2005-2006 Robert N. M. Watson .\" Copyright (c) 2008 Apple Inc. .\" 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/man/auditctl.2#9 $ -.\" .Dd April 19, 2005 .Dt AUDITCTL 2 .Os .Sh NAME .Nm auditctl .Nd "configure system audit parameters" .Sh SYNOPSIS .In bsm/audit.h .Ft int .Fn auditctl "const char *path" .Sh DESCRIPTION The .Fn auditctl system call directs the kernel to open a new audit trail log file. It requires an appropriate privilege. The .Fn auditctl system call opens new files, but .Xr auditon 2 is used to disable the audit log. .Sh RETURN VALUES .Rv -std .Sh ERRORS The .Fn auditctl system call will fail if: .Bl -tag -width Er .It Bq Er EINVAL The path is invalid. .It Bq Er EPERM The process does not have sufficient permission to complete the operation. .El .Sh SEE ALSO .Xr auditon 2 , .Xr libbsm 3 , .Xr auditd 8 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer Inc. Additional authors include .An Wayne Salamon , .An Robert Watson , and SPARTA Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. .Pp This manual page was written by .An Robert Watson Aq rwatson@FreeBSD.org . Index: user/alc/PQ_LAUNDRY/contrib/openbsm/man/auditon.2 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/man/auditon.2 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/man/auditon.2 (revision 292449) @@ -1,506 +1,504 @@ .\"- .\" Copyright (c) 2008-2009 Apple Inc. .\" Copyright (c) 2005 Robert N. M. Watson .\" Copyright (c) 2005 Tom Rhodes .\" Copyright (c) 2005 Wayne J. Salamon .\" 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/man/auditon.2#18 $ -.\" .Dd January 29, 2009 .Dt AUDITON 2 .Os .Sh NAME .Nm auditon .Nd "configure system audit parameters" .Sh SYNOPSIS .In bsm/audit.h .Ft int .Fn auditon "int cmd" "void *data" "u_int length" .Sh DESCRIPTION The .Fn auditon system call is used to manipulate various audit control operations. The .Fa data argument should point to a structure whose type depends on the command. The .Fa length argument specifies the size of .Fa *data in bytes. The .Fa cmd argument may be any of the following: .Bl -tag -width ".It Dv A_GETPINFO_ADDR" .It Dv A_SETPOLICY Set audit policy flags. The .Fa data argument must point to a .Vt int value set to one or more the following audit policy control values bitwise OR'ed together: .Dv AUDIT_CNT , .Dv AUDIT_AHLT , .Dv AUDIT_ARGV , and .Dv AUDIT_ARGE . If .Dv AUDIT_CNT is set, the system will continue even if it becomes low on space and discontinue logging events until the low space condition is remedied. If it is not set, audited events will block until the low space condition is remedied. Unaudited events, however, are unaffected. If .Dv AUDIT_AHLT is set, a .Xr panic 9 if it cannot write an event to the global audit log file. If .Dv AUDIT_ARGV is set, then the argument list passed to the .Xr execve 2 system call will be audited. If .Dv AUDIT_ARGE is set, then the environment variables passed to the .Xr execve 2 system call will be audited. The default policy is none of the audit policy control flags set. .It Dv A_SETKAUDIT Set the host information. The .Fa data argument must point to a .Vt auditinfo_addr_t structure containing the host IP address information. After setting, audit records that are created as a result of kernel events will contain this information. .It Dv A_SETKMASK Set the kernel preselection masks (success and failure). The .Fa data argument must point to a .Vt au_mask_t structure containing the mask values as defined in .In bsm/audit.h . These masks are used for non-attributable audit event preselection. The field .Fa am_success specifies which classes of successful audit events are to be logged to the audit trail. The field .Fa am_failure specifies which classes of failed audit events are to be logged. The value of both fields is the bitwise OR'ing of the audit event classes specified in .Fa bsm/audit.h . The various audit classes are described more fully in .Xr audit_class 5 . .It Dv A_SETQCTRL Set kernel audit queue parameters. The .Fa data argument must point to a .Vt au_qctrl_t structure (defined in .In bsm/audit.h ) containing the kernel audit queue control settings: .Fa aq_hiwater , .Fa aq_lowater , .Fa aq_bufsz , .Fa aq_delay , and .Fa aq_minfree . The field .Fa aq_hiwater defines the maximum number of audit record entries in the queue used to store the audit records ready for delivery to disk. New records are inserted at the tail of the queue and removed from the head. For new records which would exceed the high water mark, the calling thread is inserted into the wait queue, waiting for the audit queue to have enough space available as defined with the field .Fa aq_lowater . The field .Fa aq_bufsz defines the maximum length of the audit record that can be supplied with .Xr audit 2 . The field .Fa aq_delay is unused. The field .Fa aq_minfree specifies the minimum amount of free blocks on the disk device used to store audit records. If the value of free blocks falls below the configured minimum amount, the kernel informs the audit daemon about low disk space. The value is to be specified in percent of free file system blocks. A value of 0 results in a disabling of the check. The default and maximum values (default/maximum) for the audit queue control parameters are: .Pp .Bl -column aq_hiwater -offset indent -compact .It aq_hiwater Ta 100/10000 (audit records) .It aq_lowater Ta 10/aq_hiwater (audit records) .It aq_bufsz Ta 32767/1048576 (bytes) .It aq_delay Ta (Not currently used.) .El .It Dv A_SETSTAT Return .Er ENOSYS . (Not implemented.) .It Dv A_SETUMASK Return .Er ENOSYS . (Not implemented.) .It Dv A_SETSMASK Return .Er ENOSYS . (Not implemented.) .It Dv A_SETCOND Set the current auditing condition. The .Fa data argument must point to a .Vt int value containing the new audit condition, one of .Dv AUC_AUDITING , .Dv AUC_NOAUDIT , or .Dv AUC_DISABLED . If .Dv AUC_NOAUDIT is set, then auditing is temporarily suspended. If .Dv AUC_AUDITING is set, auditing is resumed. If .Dv AUC_DISABLED is set, the auditing system will shutdown, draining all audit records and closing out the audit trail file. .It Dv A_SETCLASS Set the event class preselection mask for an audit event. The .Fa data argument must point to a .Vt au_evclass_map_t structure containing the audit event and mask. The field .Fa ec_number is the audit event and .Fa ec_class is the audit class mask. See .Xr audit_event 5 for more information on audit event to class mapping. .It Dv A_SETPMASK Set the preselection masks for a process. The .Fa data argument must point to a .Vt auditpinfo_t structure that contains the given process's audit preselection masks for both success and failure. The field .Fa ap_pid is the process id of the target process. The field .Fa ap_mask must point to a .Fa au_mask_t structure which holds the preselection masks as described in the .Dv A_SETKMASK section above. .It Dv A_SETFSIZE Set the maximum size of the audit log file. The .Fa data argument must point to a .Vt au_fstat_t structure with the .Va af_filesz field set to the maximum audit log file size. A value of 0 indicates no limit to the size. .It Dv A_GETCLASS Return the event to class mapping for the designated audit event. The .Fa data argument must point to a .Vt au_evclass_map_t structure. See the .Dv A_SETCLASS section above for more information. .It Dv A_GETKAUDIT Get the current host information. The .Fa data argument must point to a .Vt auditinfo_addr_t structure. .It Dv A_GETPINFO Return the audit settings for a process. The .Fa data argument must point to a .Vt auditpinfo_t structure which will be set to contain .Fa ap_auid (the audit ID), .Fa ap_mask (the preselection mask), .Fa ap_termid (the terminal ID), and .Fa ap_asid (the audit session ID) of the given target process. The process ID of the target process is passed into the kernel using the .Fa ap_pid field. See the section .Dv A_SETPMASK above and .Xr getaudit 2 for more information. .It Dv A_GETPINFO_ADDR Return the extended audit settings for a process. The .Fa data argument must point to a .Vt auditpinfo_addr_t structure which is similar to the .Vt auditpinfo_addr_t structure described above. The exception is the .Fa ap_termid (the terminal ID) field which points to a .Vt au_tid_addr_t structure can hold much a larger terminal address and an address type. The process ID of the target process is passed into the kernel using the .Fa ap_pid field. See the section .Dv A_SETPMASK above and .Xr getaudit 2 for more information. .It Dv A_GETSINFO_ADDR Return the extended audit settings for a session. The .Fa data argument must point to a .Vt auditinfo_addr_t structure. The audit session ID of the target session is passed into the kernel using the .Fa ai_asid field. See .Xr getaudit_addr 2 for more information about the .Vt auditinfo_addr_t structure. .It Dv A_GETKMASK Return the current kernel preselection masks. The .Fa data argument must point to a .Vt au_mask_t structure which will be set to the current kernel preselection masks for non-attributable events. .It Dv A_GETPOLICY Return the current audit policy setting. The .Fa data argument must point to a .Vt int value which will be set to one of the current audit policy flags. The audit policy flags are described in the .Dv A_SETPOLICY section above. .It Dv A_GETQCTRL Return the current kernel audit queue control parameters. The .Fa data argument must point to a .Vt au_qctrl_t structure which will be set to the current kernel audit queue control parameters. See the .Dv A_SETQCTL section above for more information. .It Dv A_GETFSIZE Returns the maximum size of the audit log file. The .Fa data argument must point to a .Vt au_fstat_t structure. The .Va af_filesz field will be set to the maximum audit log file size. A value of 0 indicates no limit to the size. The .Va af_currsz field will be set to the current audit log file size. .It Dv A_GETCWD .\" [COMMENTED OUT]: Valid description, not yet implemented. .\" Return the current working directory as stored in the audit subsystem. Return .Er ENOSYS . (Not implemented.) .It Dv A_GETCAR .\" [COMMENTED OUT]: Valid description, not yet implemented. .\"Stores and returns the current active root as stored in the audit .\"subsystem. Return .Er ENOSYS . (Not implemented.) .It Dv A_GETSTAT .\" [COMMENTED OUT]: Valid description, not yet implemented. .\"Return the statistics stored in the audit system. Return .Er ENOSYS . (Not implemented.) .It Dv A_GETCOND Return the current auditing condition. The .Fa data argument must point to a .Vt int value which will be set to the current audit condition, one of .Dv AUC_AUDITING , .Dv AUC_NOAUDIT or .Dv AUC_DISABLED . See the .Dv A_SETCOND section above for more information. .It Dv A_SENDTRIGGER Send a trigger to the audit daemon. The .Fa data argument must point to a .Vt int value set to one of the acceptable trigger values: .Dv AUDIT_TRIGGER_LOW_SPACE (low disk space where the audit log resides), .Dv AUDIT_TRIGGER_OPEN_NEW (open a new audit log file), .Dv AUDIT_TRIGGER_READ_FILE (read the .Pa audit_control file), .Dv AUDIT_TRIGGER_CLOSE_AND_DIE (close the current log file and exit), .Dv AUDIT_TRIGGER_NO_SPACE (no disk space left for audit log file). .Dv AUDIT_TRIGGER_ROTATE_USER (request audit log file rotation). .Dv AUDIT_TRIGGER_INITIALIZE (initialize audit subsystem for Mac OS X only). or .Dv AUDIT_TRIGGER_EXPIRE_TRAILS (request audit log file expiration). .El .Sh RETURN VALUES .Rv -std .Sh ERRORS The .Fn auditon function will fail if: .Bl -tag -width Er .It Bq Er ENOSYS Returned by options not yet implemented. .It Bq Er EFAULT A failure occurred while data transferred to or from the kernel failed. .It Bq Er EINVAL Illegal argument was passed by a system call. .It Bq Er EPERM The process does not have sufficient permission to complete the operation. .El .Pp The .Dv A_SENDTRIGGER command is specific to the .Fx and Mac OS X implementations, and is not present in Solaris. .Sh SEE ALSO .Xr audit 2 , .Xr auditctl 2 , .Xr getaudit 2 , .Xr getaudit_addr 2 , .Xr getauid 2 , .Xr setaudit 2 , .Xr setaudit_addr 2 , .Xr setauid 2 , .Xr libbsm 3 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer Inc. Additional authors include .An Wayne Salamon , .An Robert Watson , and SPARTA Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. .Pp This manual page was written by .An Tom Rhodes Aq trhodes@FreeBSD.org , .An Robert Watson Aq rwatson@FreeBSD.org , and .An Wayne Salamon Aq wsalamon@FreeBSD.org . Index: user/alc/PQ_LAUNDRY/contrib/openbsm/man/getaudit.2 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/man/getaudit.2 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/man/getaudit.2 (revision 292449) @@ -1,188 +1,186 @@ .\"- .\" Copyright (c) 2005 Robert N. M. Watson .\" Copyright (c) 2008 Apple Inc. .\" 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/man/getaudit.2#11 $ -.\" .Dd October 19, 2008 .Dt GETAUDIT 2 .Os .Sh NAME .Nm getaudit , .Nm getaudit_addr .Nd "retrieve audit session state" .Sh SYNOPSIS .In bsm/audit.h .Ft int .Fn getaudit "auditinfo_t *auditinfo" .Ft int .Fn getaudit_addr "auditinfo_addr_t *auditinfo_addr" "u_int length" .Sh DESCRIPTION The .Fn getaudit system call retrieves the active audit session state for the current process via the .Vt auditinfo_t pointed to by .Fa auditinfo . The .Fn getaudit_addr system call retrieves extended state via .Fa auditinfo_addr and .Fa length . .Pp The .Fa auditinfo_t data structure is defined as follows: .Bd -literal -offset indent struct auditinfo { au_id_t ai_auid; /* Audit user ID */ au_mask_t ai_mask; /* Audit masks */ au_tid_t ai_termid; /* Terminal ID */ au_asid_t ai_asid; /* Audit session ID */ }; typedef struct auditinfo auditinfo_t; .Ed .Pp The .Fa ai_auid variable contains the audit identifier which is recorded in the audit log for each event the process caused. .Pp The .Fa au_mask_t data structure defines the bit mask for auditing successful and failed events out of the predefined list of event classes. It is defined as follows: .Bd -literal -offset indent struct au_mask { unsigned int am_success; /* success bits */ unsigned int am_failure; /* failure bits */ }; typedef struct au_mask au_mask_t; .Ed .Pp The .Fa au_termid_t data structure defines the Terminal ID recorded with every event caused by the process. It is defined as follows: .Bd -literal -offset indent struct au_tid { dev_t port; u_int32_t machine; }; typedef struct au_tid au_tid_t; .Ed .Pp The .Fa ai_asid variable contains the audit session ID which is recorded with every event caused by the process. .Pp The .Fn getaudit_addr system call uses the expanded .Fa auditinfo_addr_t data structure and supports Terminal IDs with larger addresses such as those used in IP version 6. It is defined as follows: .Bd -literal -offset indent struct auditinfo_addr { au_id_t ai_auid; /* Audit user ID. */ au_mask_t ai_mask; /* Audit masks. */ au_tid_addr_t ai_termid; /* Terminal ID. */ au_asid_t ai_asid; /* Audit session ID. */ }; typedef struct auditinfo_addr auditinfo_addr_t; .Ed .Pp The .Fa au_tid_addr_t data structure which includes a larger address storage field and an additional field with the type of address stored: .Bd -literal -offset indent struct au_tid_addr { dev_t at_port; u_int32_t at_type; u_int32_t at_addr[4]; }; typedef struct au_tid_addr au_tid_addr_t; .Ed .Pp These system calls require an appropriate privilege to complete. .Sh RETURN VALUES .Rv -std getaudit getaudit_addr .Sh ERRORS The .Fn getaudit function will fail if: .Bl -tag -width Er .It Bq Er EFAULT A failure occurred while data transferred to or from the kernel failed. .It Bq Er EINVAL Illegal argument was passed by a system call. .It Bq Er EPERM The process does not have sufficient permission to complete the operation. .It Bq Er EOVERFLOW The .Fa length argument indicates an overflow condition will occur. .It Bq Er E2BIG The address is too big and, therefore, .Fn getaudit_addr should be used instead. .El .Sh SEE ALSO .Xr audit 2 , .Xr auditon 2 , .Xr getauid 2 , .Xr setaudit 2 , .Xr setauid 2 , .Xr libbsm 3 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer Inc. Additional authors include .An Wayne Salamon , .An Robert Watson , and SPARTA Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. .Pp This manual page was written by .An Robert Watson Aq rwatson@FreeBSD.org . Index: user/alc/PQ_LAUNDRY/contrib/openbsm/man/getauid.2 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/man/getauid.2 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/man/getauid.2 (revision 292449) @@ -1,90 +1,88 @@ .\"- .\" Copyright (c) 2005 Robert N. M. Watson .\" Copyright (c) 2008 Apple Inc. .\" 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/man/getauid.2#9 $ -.\" .Dd April 19, 2005 .Dt GETAUID 2 .Os .Sh NAME .Nm getauid .Nd "retrieve audit session ID" .Sh SYNOPSIS .In bsm/audit.h .Ft int .Fn getauid "au_id_t *auid" .Sh DESCRIPTION The .Fn getauid system call retrieves the active audit session ID for the current process via the .Vt au_id_t pointed to by .Fa auid . .Pp This system call requires an appropriate privilege to complete. .Sh RETURN VALUES .Rv -std .Sh ERRORS The .Fn getauid function will fail if: .Bl -tag -width Er .It Bq Er EFAULT A failure occurred while data transferred from the kernel failed. .It Bq Er EPERM The process does not have sufficient permission to complete the operation. .El .Sh SEE ALSO .Xr audit 2 , .Xr auditon 2 , .Xr getaudit 2 , .Xr getaudit_addr 2 , .Xr setaudit 2 , .Xr setaudit_addr 2 , .Xr setauid 2 , .Xr libbsm 3 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer Inc. Additional authors include .An Wayne Salamon , .An Robert Watson , and SPARTA Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. .Pp This manual page was written by .An Robert Watson Aq rwatson@FreeBSD.org . Index: user/alc/PQ_LAUNDRY/contrib/openbsm/man/setaudit.2 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/man/setaudit.2 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/man/setaudit.2 (revision 292449) @@ -1,174 +1,172 @@ .\"- .\" Copyright (c) 2005 Robert N. M. Watson .\" Copyright (c) 2008 Apple Inc. .\" 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/man/setaudit.2#12 $ -.\" .Dd April 19, 2005 .Dt SETAUDIT 2 .Os .Sh NAME .Nm setaudit , .Nm setaudit_addr .Nd "set audit session state" .Sh SYNOPSIS .In bsm/audit.h .Ft int .Fn setaudit "auditinfo_t *auditinfo" .Ft int .Fn setaudit_addr "auditinfo_addr_t *auditinfo_addr" "u_int length" .Sh DESCRIPTION The .Fn setaudit system call sets the active audit session state for the current process via the .Vt auditinfo_t pointed to by .Fa auditinfo . The .Fn setaudit_addr system call sets extended state via .Fa auditinfo_addr and .Fa length . .Pp The .Fa auditinfo_t data structure is defined as follows: .Bd -literal -offset 4n struct auditinfo { au_id_t ai_auid; /* Audit user ID */ au_mask_t ai_mask; /* Audit masks */ au_tid_t ai_termid; /* Terminal ID */ au_asid_t ai_asid; /* Audit session ID */ }; typedef struct auditinfo auditinfo_t; .Ed .Pp The .Fa ai_auid variable contains the audit identifier which is recorded in the audit log for each event the process caused. .Pp The .Fa au_mask_t data structure defines the bit mask for auditing successful and failed events out of the predefined list of event classes. It is defined as follows: .Bd -literal -offset 4n struct au_mask { unsigned int am_success; /* success bits */ unsigned int am_failure; /* failure bits */ }; typedef struct au_mask au_mask_t; .Ed .Pp The .Fa au_termid_t data structure defines the Terminal ID recorded with every event caused by the process. It is defined as follows: .Bd -literal -offset 4n struct au_tid { dev_t port; u_int32_t machine; }; typedef struct au_tid au_tid_t; .Ed .Pp The .Fa ai_asid variable contains the audit session ID which is recorded with every event caused by the process. .Pp The .Fn setaudit_addr system call uses the expanded .Fa auditinfo_addr_t data structure supports Terminal IDs with larger addresses such as those used in IP version 6. It is defined as follows: .Bd -literal -offset 4n struct auditinfo_addr { au_id_t ai_auid; /* Audit user ID. */ au_mask_t ai_mask; /* Audit masks. */ au_tid_addr_t ai_termid; /* Terminal ID. */ au_asid_t ai_asid; /* Audit session ID. */ }; typedef struct auditinfo_addr auditinfo_addr_t; .Ed .Pp The .Fa au_tid_addr_t data structure which includes a larger address storage field and an additional field with the type of address stored: .Bd -literal -offset 4n struct au_tid_addr { dev_t at_port; u_int32_t at_type; u_int32_t at_addr[4]; }; typedef struct au_tid_addr au_tid_addr_t; .Ed .Pp These system calls require an appropriate privilege to complete. .Sh RETURN VALUES .Rv -std setaudit setaudit_addr .Sh ERRORS .Bl -tag -width Er .It Bq Er EFAULT A failure occurred while data transferred to or from the kernel failed. .It Bq Er EINVAL Illegal argument was passed by a system call. .It Bq Er EPERM The process does not have sufficient permission to complete the operation. .El .Sh SEE ALSO .Xr audit 2 , .Xr auditon 2 , .Xr getaudit 2 , .Xr getauid 2 , .Xr setauid 2 , .Xr libbsm 3 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer Inc. Additional authors include .An Wayne Salamon , .An Robert Watson , and SPARTA Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. .Pp This manual page was written by .An Robert Watson Aq rwatson@FreeBSD.org . Index: user/alc/PQ_LAUNDRY/contrib/openbsm/man/setauid.2 =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/man/setauid.2 (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/man/setauid.2 (revision 292449) @@ -1,90 +1,88 @@ .\"- .\" Copyright (c) 2005 Robert N. M. Watson .\" Copyright (c) 2008 Apple Inc. .\" 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $P4: //depot/projects/trustedbsd/openbsm/man/setauid.2#9 $ -.\" .Dd April 19, 2005 .Dt SETAUID 2 .Os .Sh NAME .Nm setauid .Nd "set audit session ID" .Sh SYNOPSIS .In bsm/audit.h .Ft int .Fn setauid "au_id_t *auid" .Sh DESCRIPTION The .Fn setauid system call sets the active audit session ID for the current process from the .Vt au_id_t pointed to by .Fa auid . .Pp This system call requires an appropriate privilege to complete. .Sh RETURN VALUES .Rv -std .Sh ERRORS The .Fn setauid function will fail if: .Bl -tag -width Er .It Bq Er EFAULT A failure occurred while data transferred to the kernel failed. .It Bq Er EPERM The process does not have sufficient permission to complete the operation. .El .Sh SEE ALSO .Xr audit 2 , .Xr auditon 2 , .Xr getaudit 2 , .Xr getaudit_addr 2 , .Xr getauid 2 , .Xr setaudit 2 , .Xr setaudit_addr 2 , .Xr libbsm 3 .Sh HISTORY The OpenBSM implementation was created by McAfee Research, the security division of McAfee Inc., under contract to Apple Computer Inc.\& in 2004. It was subsequently adopted by the TrustedBSD Project as the foundation for the OpenBSM distribution. .Sh AUTHORS .An -nosplit This software was created by McAfee Research, the security research division of McAfee, Inc., under contract to Apple Computer Inc. Additional authors include .An Wayne Salamon , .An Robert Watson , and SPARTA Inc. .Pp The Basic Security Module (BSM) interface to audit records and audit event stream format were defined by Sun Microsystems. .Pp This manual page was written by .An Robert Watson Aq rwatson@FreeBSD.org . Index: user/alc/PQ_LAUNDRY/contrib/openbsm/modules/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/modules/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/modules/Makefile.am (revision 292449) @@ -1,7 +1,3 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/modules/Makefile.am#2 $ -## - SUBDIRS = \ auditfilter_noop Index: user/alc/PQ_LAUNDRY/contrib/openbsm/modules/auditfilter_noop/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/modules/auditfilter_noop/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/modules/auditfilter_noop/Makefile.am (revision 292449) @@ -1,14 +1,10 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/modules/auditfilter_noop/Makefile.am#4 $ -## - if USE_NATIVE_INCLUDES INCLUDES = -I$(top_builddir) -I$(top_srcdir) else INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys endif lib_LTLIBRARIES = auditfilter_noop.la auditfilter_noop_la_SOURCE = auditfilter_noop.c auditfilter_noop_la_LDFLAGS = -module Index: user/alc/PQ_LAUNDRY/contrib/openbsm/modules/auditfilter_noop/auditfilter_noop.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/modules/auditfilter_noop/auditfilter_noop.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/modules/auditfilter_noop/auditfilter_noop.c (revision 292449) @@ -1,79 +1,77 @@ /*- * Copyright (c) 2006 Robert N. M. Watson * All rights reserved. * * This software was developed by Robert Watson for the TrustedBSD Project. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/modules/auditfilter_noop/auditfilter_noop.c#6 $ */ /* * Sample audit filter: no-op which sinks audit records in both BSM and * parsed formats, but does nothing with them. */ #include #include #include #ifndef __unused #define __unused #endif int AUDIT_FILTER_ATTACH(void *instance __unused, int argc __unused, char *argv[] __unused) { return (0); } int AUDIT_FILTER_REINIT(void *instance __unused, int argc __unused, char *argv[] __unused) { return (0); } void AUDIT_FILTER_RECORD(void *instance __unused, struct timespec *ts __unused, int token_count __unused, const tokenstr_t *tok[] __unused) { } void AUDIT_FILTER_RAWRECORD(void *instance __unused, struct timespec *ts __unused, u_char *data __unused, u_int len __unused) { } void AUDIT_FILTER_DETACH(void *instance __unused) { } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/sys/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/sys/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/sys/Makefile.am (revision 292449) @@ -1,7 +1,3 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/sys/Makefile.am#2 $ -## - SUBDIRS = \ bsm Index: user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/Makefile.am (revision 292449) @@ -1,18 +1,13 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/sys/bsm/Makefile.am#5 $ -## - - if ! USE_NATIVE_INCLUDES openbsmdir = $(includedir)/bsm openbsm_HEADERS = \ audit.h \ audit_domain.h \ audit_errno.h \ audit_fcntl.h \ audit_internal.h \ audit_kevents.h \ audit_record.h \ audit_socket_type.h endif Index: user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit.h (revision 292449) @@ -1,327 +1,325 @@ /*- * Copyright (c) 2005-2009 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/sys/bsm/audit.h#10 $ */ #ifndef _BSM_AUDIT_H #define _BSM_AUDIT_H #include #include #define AUDIT_RECORD_MAGIC 0x828a0f1b #define MAX_AUDIT_RECORDS 20 #define MAXAUDITDATA (0x8000 - 1) #define MAX_AUDIT_RECORD_SIZE MAXAUDITDATA #define MIN_AUDIT_FILE_SIZE (512 * 1024) /* * Minimum noumber of free blocks on the filesystem containing the audit * log necessary to avoid a hard log rotation. DO NOT SET THIS VALUE TO 0 * as the kernel does an unsigned compare, plus we want to leave a few blocks * free so userspace can terminate the log, etc. */ #define AUDIT_HARD_LIMIT_FREE_BLOCKS 4 /* * Triggers for the audit daemon. */ #define AUDIT_TRIGGER_MIN 1 #define AUDIT_TRIGGER_LOW_SPACE 1 /* Below low watermark. */ #define AUDIT_TRIGGER_ROTATE_KERNEL 2 /* Kernel requests rotate. */ #define AUDIT_TRIGGER_READ_FILE 3 /* Re-read config file. */ #define AUDIT_TRIGGER_CLOSE_AND_DIE 4 /* Terminate audit. */ #define AUDIT_TRIGGER_NO_SPACE 5 /* Below min free space. */ #define AUDIT_TRIGGER_ROTATE_USER 6 /* User requests rotate. */ #define AUDIT_TRIGGER_INITIALIZE 7 /* User initialize of auditd. */ #define AUDIT_TRIGGER_EXPIRE_TRAILS 8 /* User expiration of trails. */ #define AUDIT_TRIGGER_MAX 8 /* * The special device filename (FreeBSD). */ #define AUDITDEV_FILENAME "audit" #define AUDIT_TRIGGER_FILE ("/dev/" AUDITDEV_FILENAME) /* * Pre-defined audit IDs */ #define AU_DEFAUDITID (uid_t)(-1) #define AU_DEFAUDITSID 0 #define AU_ASSIGN_ASID -1 /* * IPC types. */ #define AT_IPC_MSG ((u_char)1) /* Message IPC id. */ #define AT_IPC_SEM ((u_char)2) /* Semaphore IPC id. */ #define AT_IPC_SHM ((u_char)3) /* Shared mem IPC id. */ /* * Audit conditions. */ #define AUC_UNSET 0 #define AUC_AUDITING 1 #define AUC_NOAUDIT 2 #define AUC_DISABLED -1 /* * auditon(2) commands. */ #define A_OLDGETPOLICY 2 #define A_OLDSETPOLICY 3 #define A_GETKMASK 4 #define A_SETKMASK 5 #define A_OLDGETQCTRL 6 #define A_OLDSETQCTRL 7 #define A_GETCWD 8 #define A_GETCAR 9 #define A_GETSTAT 12 #define A_SETSTAT 13 #define A_SETUMASK 14 #define A_SETSMASK 15 #define A_OLDGETCOND 20 #define A_OLDSETCOND 21 #define A_GETCLASS 22 #define A_SETCLASS 23 #define A_GETPINFO 24 #define A_SETPMASK 25 #define A_SETFSIZE 26 #define A_GETFSIZE 27 #define A_GETPINFO_ADDR 28 #define A_GETKAUDIT 29 #define A_SETKAUDIT 30 #define A_SENDTRIGGER 31 #define A_GETSINFO_ADDR 32 #define A_GETPOLICY 33 #define A_SETPOLICY 34 #define A_GETQCTRL 35 #define A_SETQCTRL 36 #define A_GETCOND 37 #define A_SETCOND 38 /* * Audit policy controls. */ #define AUDIT_CNT 0x0001 #define AUDIT_AHLT 0x0002 #define AUDIT_ARGV 0x0004 #define AUDIT_ARGE 0x0008 #define AUDIT_SEQ 0x0010 #define AUDIT_WINDATA 0x0020 #define AUDIT_USER 0x0040 #define AUDIT_GROUP 0x0080 #define AUDIT_TRAIL 0x0100 #define AUDIT_PATH 0x0200 #define AUDIT_SCNT 0x0400 #define AUDIT_PUBLIC 0x0800 #define AUDIT_ZONENAME 0x1000 #define AUDIT_PERZONE 0x2000 /* * Default audit queue control parameters. */ #define AQ_HIWATER 100 #define AQ_MAXHIGH 10000 #define AQ_LOWATER 10 #define AQ_BUFSZ MAXAUDITDATA #define AQ_MAXBUFSZ 1048576 /* * Default minimum percentage free space on file system. */ #define AU_FS_MINFREE 20 /* * Type definitions used indicating the length of variable length addresses * in tokens containing addresses, such as header fields. */ #define AU_IPv4 4 #define AU_IPv6 16 __BEGIN_DECLS typedef uid_t au_id_t; typedef pid_t au_asid_t; typedef u_int16_t au_event_t; typedef u_int16_t au_emod_t; typedef u_int32_t au_class_t; typedef u_int64_t au_asflgs_t __attribute__ ((aligned (8))); struct au_tid { dev_t port; u_int32_t machine; }; typedef struct au_tid au_tid_t; struct au_tid_addr { dev_t at_port; u_int32_t at_type; u_int32_t at_addr[4]; }; typedef struct au_tid_addr au_tid_addr_t; struct au_mask { unsigned int am_success; /* Success bits. */ unsigned int am_failure; /* Failure bits. */ }; typedef struct au_mask au_mask_t; struct auditinfo { au_id_t ai_auid; /* Audit user ID. */ au_mask_t ai_mask; /* Audit masks. */ au_tid_t ai_termid; /* Terminal ID. */ au_asid_t ai_asid; /* Audit session ID. */ }; typedef struct auditinfo auditinfo_t; struct auditinfo_addr { au_id_t ai_auid; /* Audit user ID. */ au_mask_t ai_mask; /* Audit masks. */ au_tid_addr_t ai_termid; /* Terminal ID. */ au_asid_t ai_asid; /* Audit session ID. */ au_asflgs_t ai_flags; /* Audit session flags. */ }; typedef struct auditinfo_addr auditinfo_addr_t; struct auditpinfo { pid_t ap_pid; /* ID of target process. */ au_id_t ap_auid; /* Audit user ID. */ au_mask_t ap_mask; /* Audit masks. */ au_tid_t ap_termid; /* Terminal ID. */ au_asid_t ap_asid; /* Audit session ID. */ }; typedef struct auditpinfo auditpinfo_t; struct auditpinfo_addr { pid_t ap_pid; /* ID of target process. */ au_id_t ap_auid; /* Audit user ID. */ au_mask_t ap_mask; /* Audit masks. */ au_tid_addr_t ap_termid; /* Terminal ID. */ au_asid_t ap_asid; /* Audit session ID. */ au_asflgs_t ap_flags; /* Audit session flags. */ }; typedef struct auditpinfo_addr auditpinfo_addr_t; struct au_session { auditinfo_addr_t *as_aia_p; /* Ptr to full audit info. */ au_mask_t as_mask; /* Process Audit Masks. */ }; typedef struct au_session au_session_t; /* * Contents of token_t are opaque outside of libbsm. */ typedef struct au_token token_t; /* * Kernel audit queue control parameters: * Default: Maximum: * aq_hiwater: AQ_HIWATER (100) AQ_MAXHIGH (10000) * aq_lowater: AQ_LOWATER (10) mach_port_name_t audit_session_self(void); au_asid_t audit_session_join(mach_port_name_t port); #endif /* __APPLE_API_PRIVATE */ #endif /* defined(_KERNEL) || defined(KERNEL) */ __END_DECLS #endif /* !_BSM_AUDIT_H */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_domain.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_domain.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_domain.h (revision 292449) @@ -1,114 +1,112 @@ /*- * Copyright (c) 2008 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/sys/bsm/audit_domain.h#2 $ */ #ifndef _BSM_AUDIT_DOMAIN_H_ #define _BSM_AUDIT_DOMAIN_H_ /* * BSM protocol domain constants - protocol domains defined in Solaris. */ #define BSM_PF_UNSPEC 0 #define BSM_PF_LOCAL 1 #define BSM_PF_INET 2 #define BSM_PF_IMPLINK 3 #define BSM_PF_PUP 4 #define BSM_PF_CHAOS 5 #define BSM_PF_NS 6 #define BSM_PF_NBS 7 /* Solaris-specific. */ #define BSM_PF_ECMA 8 #define BSM_PF_DATAKIT 9 #define BSM_PF_CCITT 10 #define BSM_PF_SNA 11 #define BSM_PF_DECnet 12 #define BSM_PF_DLI 13 #define BSM_PF_LAT 14 #define BSM_PF_HYLINK 15 #define BSM_PF_APPLETALK 16 #define BSM_PF_NIT 17 /* Solaris-specific. */ #define BSM_PF_802 18 /* Solaris-specific. */ #define BSM_PF_OSI 19 #define BSM_PF_X25 20 /* Solaris/Linux-specific. */ #define BSM_PF_OSINET 21 /* Solaris-specific. */ #define BSM_PF_GOSIP 22 /* Solaris-specific. */ #define BSM_PF_IPX 23 #define BSM_PF_ROUTE 24 #define BSM_PF_LINK 25 #define BSM_PF_INET6 26 #define BSM_PF_KEY 27 #define BSM_PF_NCA 28 /* Solaris-specific. */ #define BSM_PF_POLICY 29 /* Solaris-specific. */ #define BSM_PF_INET_OFFLOAD 30 /* Solaris-specific. */ /* * BSM protocol domain constants - protocol domains not defined in Solaris. */ #define BSM_PF_NETBIOS 500 /* FreeBSD/Darwin-specific. */ #define BSM_PF_ISO 501 /* FreeBSD/Darwin-specific. */ #define BSM_PF_XTP 502 /* FreeBSD/Darwin-specific. */ #define BSM_PF_COIP 503 /* FreeBSD/Darwin-specific. */ #define BSM_PF_CNT 504 /* FreeBSD/Darwin-specific. */ #define BSM_PF_RTIP 505 /* FreeBSD/Darwin-specific. */ #define BSM_PF_SIP 506 /* FreeBSD/Darwin-specific. */ #define BSM_PF_PIP 507 /* FreeBSD/Darwin-specific. */ #define BSM_PF_ISDN 508 /* FreeBSD/Darwin-specific. */ #define BSM_PF_E164 509 /* FreeBSD/Darwin-specific. */ #define BSM_PF_NATM 510 /* FreeBSD/Darwin-specific. */ #define BSM_PF_ATM 511 /* FreeBSD/Darwin-specific. */ #define BSM_PF_NETGRAPH 512 /* FreeBSD/Darwin-specific. */ #define BSM_PF_SLOW 513 /* FreeBSD-specific. */ #define BSM_PF_SCLUSTER 514 /* FreeBSD-specific. */ #define BSM_PF_ARP 515 /* FreeBSD-specific. */ #define BSM_PF_BLUETOOTH 516 /* FreeBSD-specific. */ /* 517: unallocated. */ #define BSM_PF_AX25 518 /* Linux-specific. */ #define BSM_PF_ROSE 519 /* Linux-specific. */ #define BSM_PF_NETBEUI 520 /* Linux-specific. */ #define BSM_PF_SECURITY 521 /* Linux-specific. */ #define BSM_PF_PACKET 522 /* Linux-specific. */ #define BSM_PF_ASH 523 /* Linux-specific. */ #define BSM_PF_ECONET 524 /* Linux-specific. */ #define BSM_PF_ATMSVC 525 /* Linux-specific. */ #define BSM_PF_IRDA 526 /* Linux-specific. */ #define BSM_PF_PPPOX 527 /* Linux-specific. */ #define BSM_PF_WANPIPE 528 /* Linux-specific. */ #define BSM_PF_LLC 529 /* Linux-specific. */ #define BSM_PF_CAN 530 /* Linux-specific. */ #define BSM_PF_TIPC 531 /* Linux-specific. */ #define BSM_PF_IUCV 532 /* Linux-specific. */ #define BSM_PF_RXRPC 533 /* Linux-specific. */ #define BSM_PF_PHONET 534 /* Linux-specific. */ /* * Used when there is no mapping from a local to BSM protocol domain. */ #define BSM_PF_UNKNOWN 700 /* OpenBSM-specific. */ #endif /* !_BSM_AUDIT_DOMAIN_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_errno.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_errno.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_errno.h (revision 292449) @@ -1,216 +1,214 @@ /*- * Copyright (c) 2008 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/sys/bsm/audit_errno.h#7 $ */ #ifndef _BSM_AUDIT_ERRNO_H_ #define _BSM_AUDIT_ERRNO_H_ /* * For the purposes of portable encoding, we convert between local error * numbers and Solaris error numbers (as well as some extensions for error * numbers that don't exist in Solaris). Although the first 35 or so * constants are the same across all OS's, we don't handle that in any * special way. * * When adding constants here, also add them to bsm_errno.c. */ #define BSM_ERRNO_ESUCCESS 0 #define BSM_ERRNO_EPERM 1 #define BSM_ERRNO_ENOENT 2 #define BSM_ERRNO_ESRCH 3 #define BSM_ERRNO_EINTR 4 #define BSM_ERRNO_EIO 5 #define BSM_ERRNO_ENXIO 6 #define BSM_ERRNO_E2BIG 7 #define BSM_ERRNO_ENOEXEC 8 #define BSM_ERRNO_EBADF 9 #define BSM_ERRNO_ECHILD 10 #define BSM_ERRNO_EAGAIN 11 #define BSM_ERRNO_ENOMEM 12 #define BSM_ERRNO_EACCES 13 #define BSM_ERRNO_EFAULT 14 #define BSM_ERRNO_ENOTBLK 15 #define BSM_ERRNO_EBUSY 16 #define BSM_ERRNO_EEXIST 17 #define BSM_ERRNO_EXDEV 18 #define BSM_ERRNO_ENODEV 19 #define BSM_ERRNO_ENOTDIR 20 #define BSM_ERRNO_EISDIR 21 #define BSM_ERRNO_EINVAL 22 #define BSM_ERRNO_ENFILE 23 #define BSM_ERRNO_EMFILE 24 #define BSM_ERRNO_ENOTTY 25 #define BSM_ERRNO_ETXTBSY 26 #define BSM_ERRNO_EFBIG 27 #define BSM_ERRNO_ENOSPC 28 #define BSM_ERRNO_ESPIPE 29 #define BSM_ERRNO_EROFS 30 #define BSM_ERRNO_EMLINK 31 #define BSM_ERRNO_EPIPE 32 #define BSM_ERRNO_EDOM 33 #define BSM_ERRNO_ERANGE 34 #define BSM_ERRNO_ENOMSG 35 #define BSM_ERRNO_EIDRM 36 #define BSM_ERRNO_ECHRNG 37 /* Solaris/Linux-specific. */ #define BSM_ERRNO_EL2NSYNC 38 /* Solaris/Linux-specific. */ #define BSM_ERRNO_EL3HLT 39 /* Solaris/Linux-specific. */ #define BSM_ERRNO_EL3RST 40 /* Solaris/Linux-specific. */ #define BSM_ERRNO_ELNRNG 41 /* Solaris/Linux-specific. */ #define BSM_ERRNO_EUNATCH 42 /* Solaris/Linux-specific. */ #define BSM_ERRNO_ENOCSI 43 /* Solaris/Linux-specific. */ #define BSM_ERRNO_EL2HLT 44 /* Solaris/Linux-specific. */ #define BSM_ERRNO_EDEADLK 45 #define BSM_ERRNO_ENOLCK 46 #define BSM_ERRNO_ECANCELED 47 #define BSM_ERRNO_ENOTSUP 48 #define BSM_ERRNO_EDQUOT 49 #define BSM_ERRNO_EBADE 50 /* Solaris/Linux-specific. */ #define BSM_ERRNO_EBADR 51 /* Solaris/Linux-specific. */ #define BSM_ERRNO_EXFULL 52 /* Solaris/Linux-specific. */ #define BSM_ERRNO_ENOANO 53 /* Solaris/Linux-specific. */ #define BSM_ERRNO_EBADRQC 54 /* Solaris/Linux-specific. */ #define BSM_ERRNO_EBADSLT 55 /* Solaris/Linux-specific. */ #define BSM_ERRNO_EDEADLOCK 56 /* Solaris-specific. */ #define BSM_ERRNO_EBFONT 57 /* Solaris/Linux-specific. */ #define BSM_ERRNO_EOWNERDEAD 58 /* Solaris/Linux-specific. */ #define BSM_ERRNO_ENOTRECOVERABLE 59 /* Solaris/Linux-specific. */ #define BSM_ERRNO_ENOSTR 60 /* Solaris/Darwin/Linux-specific. */ #define BSM_ERRNO_ENODATA 61 /* Solaris/Darwin/Linux-specific. */ #define BSM_ERRNO_ETIME 62 /* Solaris/Darwin/Linux-specific. */ #define BSM_ERRNO_ENOSR 63 /* Solaris/Darwin/Linux-specific. */ #define BSM_ERRNO_ENONET 64 /* Solaris/Linux-specific. */ #define BSM_ERRNO_ENOPKG 65 /* Solaris/Linux-specific. */ #define BSM_ERRNO_EREMOTE 66 #define BSM_ERRNO_ENOLINK 67 #define BSM_ERRNO_EADV 68 /* Solaris/Linux-specific. */ #define BSM_ERRNO_ESRMNT 69 /* Solaris/Linux-specific. */ #define BSM_ERRNO_ECOMM 70 /* Solaris/Linux-specific. */ #define BSM_ERRNO_EPROTO 71 #define BSM_ERRNO_ELOCKUNMAPPED 72 /* Solaris-specific. */ #define BSM_ERRNO_ENOTACTIVE 73 /* Solaris-specific. */ #define BSM_ERRNO_EMULTIHOP 74 #define BSM_ERRNO_EBADMSG 77 #define BSM_ERRNO_ENAMETOOLONG 78 #define BSM_ERRNO_EOVERFLOW 79 #define BSM_ERRNO_ENOTUNIQ 80 /* Solaris/Linux-specific. */ #define BSM_ERRNO_EBADFD 81 /* Solaris/Linux-specific. */ #define BSM_ERRNO_EREMCHG 82 /* Solaris/Linux-specific. */ #define BSM_ERRNO_ELIBACC 83 /* Solaris/Linux-specific. */ #define BSM_ERRNO_ELIBBAD 84 /* Solaris/Linux-specific. */ #define BSM_ERRNO_ELIBSCN 85 /* Solaris/Linux-specific. */ #define BSM_ERRNO_ELIBMAX 86 /* Solaris/Linux-specific. */ #define BSM_ERRNO_ELIBEXEC 87 /* Solaris/Linux-specific. */ #define BSM_ERRNO_EILSEQ 88 #define BSM_ERRNO_ENOSYS 89 #define BSM_ERRNO_ELOOP 90 #define BSM_ERRNO_ERESTART 91 #define BSM_ERRNO_ESTRPIPE 92 /* Solaris/Linux-specific. */ #define BSM_ERRNO_ENOTEMPTY 93 #define BSM_ERRNO_EUSERS 94 #define BSM_ERRNO_ENOTSOCK 95 #define BSM_ERRNO_EDESTADDRREQ 96 #define BSM_ERRNO_EMSGSIZE 97 #define BSM_ERRNO_EPROTOTYPE 98 #define BSM_ERRNO_ENOPROTOOPT 99 #define BSM_ERRNO_EPROTONOSUPPORT 120 #define BSM_ERRNO_ESOCKTNOSUPPORT 121 #define BSM_ERRNO_EOPNOTSUPP 122 #define BSM_ERRNO_EPFNOSUPPORT 123 #define BSM_ERRNO_EAFNOSUPPORT 124 #define BSM_ERRNO_EADDRINUSE 125 #define BSM_ERRNO_EADDRNOTAVAIL 126 #define BSM_ERRNO_ENETDOWN 127 #define BSM_ERRNO_ENETUNREACH 128 #define BSM_ERRNO_ENETRESET 129 #define BSM_ERRNO_ECONNABORTED 130 #define BSM_ERRNO_ECONNRESET 131 #define BSM_ERRNO_ENOBUFS 132 #define BSM_ERRNO_EISCONN 133 #define BSM_ERRNO_ENOTCONN 134 #define BSM_ERRNO_ESHUTDOWN 143 #define BSM_ERRNO_ETOOMANYREFS 144 #define BSM_ERRNO_ETIMEDOUT 145 #define BSM_ERRNO_ECONNREFUSED 146 #define BSM_ERRNO_EHOSTDOWN 147 #define BSM_ERRNO_EHOSTUNREACH 148 #define BSM_ERRNO_EALREADY 149 #define BSM_ERRNO_EINPROGRESS 150 #define BSM_ERRNO_ESTALE 151 /* * OpenBSM constants for error numbers not defined in Solaris. In the event * that these errors are added to Solaris, we will deprecate the OpenBSM * numbers in the same way we do for audit event constants. * * ELAST doesn't get a constant in the BSM space. */ #define BSM_ERRNO_EPROCLIM 190 /* FreeBSD/Darwin-specific. */ #define BSM_ERRNO_EBADRPC 191 /* FreeBSD/Darwin-specific. */ #define BSM_ERRNO_ERPCMISMATCH 192 /* FreeBSD/Darwin-specific. */ #define BSM_ERRNO_EPROGUNAVAIL 193 /* FreeBSD/Darwin-specific. */ #define BSM_ERRNO_EPROGMISMATCH 194 /* FreeBSD/Darwin-specific. */ #define BSM_ERRNO_EPROCUNAVAIL 195 /* FreeBSD/Darwin-specific. */ #define BSM_ERRNO_EFTYPE 196 /* FreeBSD/Darwin-specific. */ #define BSM_ERRNO_EAUTH 197 /* FreeBSD/Darwin-specific. */ #define BSM_ERRNO_ENEEDAUTH 198 /* FreeBSD/Darwin-specific. */ #define BSM_ERRNO_ENOATTR 199 /* FreeBSD/Darwin-specific. */ #define BSM_ERRNO_EDOOFUS 200 /* FreeBSD-specific. */ #define BSM_ERRNO_EJUSTRETURN 201 /* FreeBSD-specific. */ #define BSM_ERRNO_ENOIOCTL 202 /* FreeBSD-specific. */ #define BSM_ERRNO_EDIRIOCTL 203 /* FreeBSD-specific. */ #define BSM_ERRNO_EPWROFF 204 /* Darwin-specific. */ #define BSM_ERRNO_EDEVERR 205 /* Darwin-specific. */ #define BSM_ERRNO_EBADEXEC 206 /* Darwin-specific. */ #define BSM_ERRNO_EBADARCH 207 /* Darwin-specific. */ #define BSM_ERRNO_ESHLIBVERS 208 /* Darwin-specific. */ #define BSM_ERRNO_EBADMACHO 209 /* Darwin-specific. */ #define BSM_ERRNO_EPOLICY 210 /* Darwin-specific. */ #define BSM_ERRNO_EDOTDOT 211 /* Linux-specific. */ #define BSM_ERRNO_EUCLEAN 212 /* Linux-specific. */ #define BSM_ERRNO_ENOTNAM 213 /* Linux(Xenix?)-specific. */ #define BSM_ERRNO_ENAVAIL 214 /* Linux(Xenix?)-specific. */ #define BSM_ERRNO_EISNAM 215 /* Linux(Xenix?)-specific. */ #define BSM_ERRNO_EREMOTEIO 216 /* Linux-specific. */ #define BSM_ERRNO_ENOMEDIUM 217 /* Linux-specific. */ #define BSM_ERRNO_EMEDIUMTYPE 218 /* Linux-specific. */ #define BSM_ERRNO_ENOKEY 219 /* Linux-specific. */ #define BSM_ERRNO_EKEYEXPIRED 220 /* Linux-specific. */ #define BSM_ERRNO_EKEYREVOKED 221 /* Linux-specific. */ #define BSM_ERRNO_EKEYREJECTED 222 /* Linux-specific. */ #define BSM_ERRNO_ENOTCAPABLE 223 /* FreeBSD-specific. */ #define BSM_ERRNO_ECAPMODE 224 /* FreeBSD-specific. */ /* * In the event that OpenBSM doesn't have a file representation of a local * error number, use this. */ #define BSM_ERRNO_UNKNOWN 250 /* OpenBSM-specific. */ #endif /* !_BSM_AUDIT_ERRNO_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_fcntl.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_fcntl.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_fcntl.h (revision 292449) @@ -1,140 +1,138 @@ /*- * Copyright (c) 2009 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/sys/bsm/audit_fcntl.h#2 $ */ #ifndef _BSM_AUDIT_FCNTL_H_ #define _BSM_AUDIT_FCNTL_H_ /* * Shared and Solaris-specific: (0-99). */ #define BSM_F_DUPFD 0 #define BSM_F_GETFD 1 #define BSM_F_SETFD 2 #define BSM_F_GETFL 3 #define BSM_F_SETFL 4 #define BSM_F_O_GETLK 5 /* Solaris-specific. */ #define BSM_F_SETLK 6 #define BSM_F_SETLKW 7 #define BSM_F_CHKFL 8 /* Solaris-specific. */ #define BSM_F_DUP2FD 9 /* FreeBSD/Solaris-specific. */ #define BSM_F_ALLOCSP 10 /* Solaris-specific. */ #define BSM_F_FREESP 11 /* Solaris-specific. */ #define BSM_F_ISSTREAM 13 /* Solaris-specific. */ #define BSM_F_GETLK 14 #define BSM_F_PRIV 15 /* Solaris-specific. */ #define BSM_F_NPRIV 16 /* Solaris-specific. */ #define BSM_F_QUOTACTL 17 /* Solaris-specific. */ #define BSM_F_BLOCKS 18 /* Solaris-specific. */ #define BSM_F_BLKSIZE 19 /* Solaris-specific. */ #define BSM_F_GETOWN 23 #define BSM_F_SETOWN 24 #define BSM_F_REVOKE 25 /* Solaris-specific. */ #define BSM_F_HASREMOTELOCKS 26 /* Solaris-specific. */ #define BSM_F_FREESP64 27 /* Solaris-specific. */ #define BSM_F_ALLOCSP64 28 /* Solaris-specific. */ #define BSM_F_GETLK64 33 /* Solaris-specific. */ #define BSM_F_SETLK64 34 /* Solaris-specific. */ #define BSM_F_SETLKW64 35 /* Solaris-specific. */ #define BSM_F_SHARE 40 /* Solaris-specific. */ #define BSM_F_UNSHARE 41 /* Solaris-specific. */ #define BSM_F_SETLK_NBMAND 42 /* Solaris-specific. */ #define BSM_F_SHARE_NBMAND 43 /* Solaris-specific. */ #define BSM_F_SETLK64_NBMAND 44 /* Solaris-specific. */ #define BSM_F_GETXFL 45 /* Solaris-specific. */ #define BSM_F_BADFD 46 /* Solaris-specific. */ /* * FreeBSD-specific (100-199). */ #define BSM_F_OGETLK 107 /* FreeBSD-specific. */ #define BSM_F_OSETLK 108 /* FreeBSD-specific. */ #define BSM_F_OSETLKW 109 /* FreeBSD-specific. */ #define BSM_F_SETLK_REMOTE 114 /* FreeBSD-specific. */ /* * Linux-specific (200-299). */ #define BSM_F_SETSIG 210 /* Linux-specific. */ #define BSM_F_GETSIG 211 /* Linux-specific. */ /* * Darwin-specific (300-399). */ #define BSM_F_CHKCLEAN 341 /* Darwin-specific. */ #define BSM_F_PREALLOCATE 342 /* Darwin-specific. */ #define BSM_F_SETSIZE 343 /* Darwin-specific. */ #define BSM_F_RDADVISE 344 /* Darwin-specific. */ #define BSM_F_RDAHEAD 345 /* Darwin-specific. */ #define BSM_F_READBOOTSTRAP 346 /* Darwin-specific. */ #define BSM_F_WRITEBOOTSTRAP 347 /* Darwin-specific. */ #define BSM_F_NOCACHE 348 /* Darwin-specific. */ #define BSM_F_LOG2PHYS 349 /* Darwin-specific. */ #define BSM_F_GETPATH 350 /* Darwin-specific. */ #define BSM_F_FULLFSYNC 351 /* Darwin-specific. */ #define BSM_F_PATHPKG_CHECK 352 /* Darwin-specific. */ #define BSM_F_FREEZE_FS 353 /* Darwin-specific. */ #define BSM_F_THAW_FS 354 /* Darwin-specific. */ #define BSM_F_GLOBAL_NOCACHE 355 /* Darwin-specific. */ #define BSM_F_OPENFROM 356 /* Darwin-specific. */ #define BSM_F_UNLINKFROM 357 /* Darwin-specific. */ #define BSM_F_CHECK_OPENEVT 358 /* Darwin-specific. */ #define BSM_F_ADDSIGS 359 /* Darwin-specific. */ #define BSM_F_MARKDEPENDENCY 360 /* Darwin-specific. */ /* * Darwin file system specific (400-499). */ #define BSM_F_FS_SPECIFIC_0 400 /* Darwin-fs-specific. */ #define BSM_F_FS_SPECIFIC_1 401 /* Darwin-fs-specific. */ #define BSM_F_FS_SPECIFIC_2 402 /* Darwin-fs-specific. */ #define BSM_F_FS_SPECIFIC_3 403 /* Darwin-fs-specific. */ #define BSM_F_FS_SPECIFIC_4 404 /* Darwin-fs-specific. */ #define BSM_F_FS_SPECIFIC_5 405 /* Darwin-fs-specific. */ #define BSM_F_FS_SPECIFIC_6 406 /* Darwin-fs-specific. */ #define BSM_F_FS_SPECIFIC_7 407 /* Darwin-fs-specific. */ #define BSM_F_FS_SPECIFIC_8 408 /* Darwin-fs-specific. */ #define BSM_F_FS_SPECIFIC_9 409 /* Darwin-fs-specific. */ #define BSM_F_FS_SPECIFIC_10 410 /* Darwin-fs-specific. */ #define BSM_F_FS_SPECIFIC_11 411 /* Darwin-fs-specific. */ #define BSM_F_FS_SPECIFIC_12 412 /* Darwin-fs-specific. */ #define BSM_F_FS_SPECIFIC_13 413 /* Darwin-fs-specific. */ #define BSM_F_FS_SPECIFIC_14 414 /* Darwin-fs-specific. */ #define BSM_F_FS_SPECIFIC_15 415 /* Darwin-fs-specific. */ #define BSM_F_UNKNOWN 0xFFFF #endif /* !_BSM_AUDIT_FCNTL_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_internal.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_internal.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_internal.h (revision 292449) @@ -1,117 +1,115 @@ /*- * Copyright (c) 2005-2008 Apple Inc. * Copyright (c) 2005 SPARTA, Inc. * All rights reserved. * * This code was developed in part by Robert N. M. Watson, Senior Principal * Scientist, SPARTA, Inc. * * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/sys/bsm/audit_internal.h#6 $ */ #ifndef _AUDIT_INTERNAL_H #define _AUDIT_INTERNAL_H #if defined(__linux__) && !defined(__unused) #define __unused #endif /* * audit_internal.h contains private interfaces that are shared by user space * and the kernel for the purposes of assembling audit records. Applications * should not include this file or use the APIs found within, or it may be * broken with future releases of OpenBSM, which may delete, modify, or * otherwise break these interfaces or the assumptions they rely on. */ struct au_token { u_char *t_data; size_t len; TAILQ_ENTRY(au_token) tokens; }; struct au_record { char used; /* Record currently in use? */ int desc; /* Descriptor for record. */ TAILQ_HEAD(, au_token) token_q; /* Queue of BSM tokens. */ u_char *data; size_t len; LIST_ENTRY(au_record) au_rec_q; }; typedef struct au_record au_record_t; /* * We could determined the header and trailer sizes by defining appropriate * structures. We hold off that approach until we have a consistent way of * using structures for all tokens. This is not straightforward since these * token structures may contain pointers of whose contents we do not know the * size (e.g text tokens). */ #define AUDIT_HEADER_EX_SIZE(a) ((a)->ai_termid.at_type+18+sizeof(u_int32_t)) #define AUDIT_HEADER_SIZE 18 #define MAX_AUDIT_HEADER_SIZE (5*sizeof(u_int32_t)+18) #define AUDIT_TRAILER_SIZE 7 /* * BSM token streams store fields in big endian byte order, so as to be * portable; when encoding and decoding, we must convert byte orders for * typed values. */ #define ADD_U_CHAR(loc, val) \ do { \ *(loc) = (val); \ (loc) += sizeof(u_char); \ } while(0) #define ADD_U_INT16(loc, val) \ do { \ be16enc((loc), (val)); \ (loc) += sizeof(u_int16_t); \ } while(0) #define ADD_U_INT32(loc, val) \ do { \ be32enc((loc), (val)); \ (loc) += sizeof(u_int32_t); \ } while(0) #define ADD_U_INT64(loc, val) \ do { \ be64enc((loc), (val)); \ (loc) += sizeof(u_int64_t); \ } while(0) #define ADD_MEM(loc, data, size) \ do { \ memcpy((loc), (data), (size)); \ (loc) += size; \ } while(0) #define ADD_STRING(loc, data, size) ADD_MEM(loc, data, size) #endif /* !_AUDIT_INTERNAL_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_kevents.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_kevents.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_kevents.h (revision 292449) @@ -1,799 +1,806 @@ /*- * Copyright (c) 2005-2009 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/sys/bsm/audit_kevents.h#10 $ */ #ifndef _BSM_AUDIT_KEVENTS_H_ #define _BSM_AUDIT_KEVENTS_H_ /* - * The reserved event numbers for kernel events are 1...2047 and 43001..44900. + * The reserved event numbers for kernel events are 1...2047 and 43001..44999. */ -#define AUE_IS_A_KEVENT(e) (((e) > 0 && (e) < 2048) || \ - ((e) > 43000 && (e) < 45000)) +#define AUE_IS_A_KEVENT(e) (((e) > 0 && (e) < 2048) || \ + ((e) > 43000 && (e) < 45000)) /* * Values marked as AUE_NULL are not required to be audited as per CAPP. * * Some conflicts exist in the assignment of name to event number mappings * between BSM implementations. In general, we prefer the OpenSolaris * definition as we consider Solaris BSM to be authoritative. _DARWIN_ has * been inserted for the Darwin variants. If necessary, other tags will be * added in the future. */ #define AUE_NULL 0 #define AUE_EXIT 1 #define AUE_FORK 2 #define AUE_FORKALL AUE_FORK /* Solaris-specific. */ #define AUE_OPEN 3 #define AUE_CREAT 4 #define AUE_LINK 5 #define AUE_UNLINK 6 #define AUE_DELETE AUE_UNLINK /* Darwin-specific. */ #define AUE_EXEC 7 #define AUE_CHDIR 8 #define AUE_MKNOD 9 #define AUE_CHMOD 10 #define AUE_CHOWN 11 #define AUE_UMOUNT 12 #define AUE_JUNK 13 /* Solaris-specific. */ #define AUE_ACCESS 14 #define AUE_KILL 15 #define AUE_STAT 16 #define AUE_LSTAT 17 #define AUE_ACCT 18 #define AUE_MCTL 19 /* Solaris-specific. */ #define AUE_REBOOT 20 /* XXX: Darwin conflict. */ #define AUE_SYMLINK 21 #define AUE_READLINK 22 #define AUE_EXECVE 23 #define AUE_CHROOT 24 #define AUE_VFORK 25 #define AUE_SETGROUPS 26 #define AUE_SETPGRP 27 #define AUE_SWAPON 28 #define AUE_SETHOSTNAME 29 /* XXX: Darwin conflict. */ #define AUE_FCNTL 30 #define AUE_SETPRIORITY 31 /* XXX: Darwin conflict. */ #define AUE_CONNECT 32 #define AUE_ACCEPT 33 #define AUE_BIND 34 #define AUE_SETSOCKOPT 35 #define AUE_VTRACE 36 /* Solaris-specific. */ #define AUE_SETTIMEOFDAY 37 /* XXX: Darwin conflict. */ #define AUE_FCHOWN 38 #define AUE_FCHMOD 39 #define AUE_SETREUID 40 #define AUE_SETREGID 41 #define AUE_RENAME 42 #define AUE_TRUNCATE 43 /* XXX: Darwin conflict. */ #define AUE_FTRUNCATE 44 /* XXX: Darwin conflict. */ #define AUE_FLOCK 45 /* XXX: Darwin conflict. */ #define AUE_SHUTDOWN 46 #define AUE_MKDIR 47 #define AUE_RMDIR 48 #define AUE_UTIMES 49 #define AUE_ADJTIME 50 #define AUE_SETRLIMIT 51 #define AUE_KILLPG 52 #define AUE_NFS_SVC 53 /* XXX: Darwin conflict. */ #define AUE_STATFS 54 #define AUE_FSTATFS 55 #define AUE_UNMOUNT 56 /* XXX: Darwin conflict. */ #define AUE_ASYNC_DAEMON 57 #define AUE_NFS_GETFH 58 /* XXX: Darwin conflict. */ #define AUE_SETDOMAINNAME 59 #define AUE_QUOTACTL 60 /* XXX: Darwin conflict. */ #define AUE_EXPORTFS 61 #define AUE_MOUNT 62 #define AUE_SEMSYS 63 #define AUE_MSGSYS 64 #define AUE_SHMSYS 65 #define AUE_BSMSYS 66 /* Solaris-specific. */ #define AUE_RFSSYS 67 /* Solaris-specific. */ #define AUE_FCHDIR 68 #define AUE_FCHROOT 69 #define AUE_VPIXSYS 70 /* Solaris-specific. */ #define AUE_PATHCONF 71 #define AUE_OPEN_R 72 #define AUE_OPEN_RC 73 #define AUE_OPEN_RT 74 #define AUE_OPEN_RTC 75 #define AUE_OPEN_W 76 #define AUE_OPEN_WC 77 #define AUE_OPEN_WT 78 #define AUE_OPEN_WTC 79 #define AUE_OPEN_RW 80 #define AUE_OPEN_RWC 81 #define AUE_OPEN_RWT 82 #define AUE_OPEN_RWTC 83 #define AUE_MSGCTL 84 #define AUE_MSGCTL_RMID 85 #define AUE_MSGCTL_SET 86 #define AUE_MSGCTL_STAT 87 #define AUE_MSGGET 88 #define AUE_MSGRCV 89 #define AUE_MSGSND 90 #define AUE_SHMCTL 91 #define AUE_SHMCTL_RMID 92 #define AUE_SHMCTL_SET 93 #define AUE_SHMCTL_STAT 94 #define AUE_SHMGET 95 #define AUE_SHMAT 96 #define AUE_SHMDT 97 #define AUE_SEMCTL 98 #define AUE_SEMCTL_RMID 99 #define AUE_SEMCTL_SET 100 #define AUE_SEMCTL_STAT 101 #define AUE_SEMCTL_GETNCNT 102 #define AUE_SEMCTL_GETPID 103 #define AUE_SEMCTL_GETVAL 104 #define AUE_SEMCTL_GETALL 105 #define AUE_SEMCTL_GETZCNT 106 #define AUE_SEMCTL_SETVAL 107 #define AUE_SEMCTL_SETALL 108 #define AUE_SEMGET 109 #define AUE_SEMOP 110 #define AUE_CORE 111 /* Solaris-specific, currently. */ #define AUE_CLOSE 112 #define AUE_SYSTEMBOOT 113 /* Solaris-specific. */ #define AUE_ASYNC_DAEMON_EXIT 114 /* Solaris-specific. */ #define AUE_NFSSVC_EXIT 115 /* Solaris-specific. */ #define AUE_WRITEL 128 /* Solaris-specific. */ #define AUE_WRITEVL 129 /* Solaris-specific. */ #define AUE_GETAUID 130 #define AUE_SETAUID 131 #define AUE_GETAUDIT 132 #define AUE_SETAUDIT 133 #define AUE_GETUSERAUDIT 134 /* Solaris-specific. */ #define AUE_SETUSERAUDIT 135 /* Solaris-specific. */ #define AUE_AUDITSVC 136 /* Solaris-specific. */ #define AUE_AUDITUSER 137 /* Solaris-specific. */ #define AUE_AUDITON 138 #define AUE_AUDITON_GTERMID 139 /* Solaris-specific. */ #define AUE_AUDITON_STERMID 140 /* Solaris-specific. */ #define AUE_AUDITON_GPOLICY 141 #define AUE_AUDITON_SPOLICY 142 #define AUE_AUDITON_GQCTRL 145 #define AUE_AUDITON_SQCTRL 146 #define AUE_GETKERNSTATE 147 /* Solaris-specific. */ #define AUE_SETKERNSTATE 148 /* Solaris-specific. */ #define AUE_GETPORTAUDIT 149 /* Solaris-specific. */ #define AUE_AUDITSTAT 150 /* Solaris-specific. */ #define AUE_REVOKE 151 #define AUE_MAC 152 /* Solaris-specific. */ #define AUE_ENTERPROM 153 /* Solaris-specific. */ #define AUE_EXITPROM 154 /* Solaris-specific. */ #define AUE_IFLOAT 155 /* Solaris-specific. */ #define AUE_PFLOAT 156 /* Solaris-specific. */ #define AUE_UPRIV 157 /* Solaris-specific. */ #define AUE_IOCTL 158 #define AUE_SOCKET 183 #define AUE_SENDTO 184 #define AUE_PIPE 185 #define AUE_SOCKETPAIR 186 /* XXX: Darwin conflict. */ #define AUE_SEND 187 #define AUE_SENDMSG 188 #define AUE_RECV 189 #define AUE_RECVMSG 190 #define AUE_RECVFROM 191 #define AUE_READ 192 #define AUE_GETDENTS 193 #define AUE_LSEEK 194 #define AUE_WRITE 195 #define AUE_WRITEV 196 #define AUE_NFS 197 /* Solaris-specific. */ #define AUE_READV 198 #define AUE_OSTAT 199 /* Solaris-specific. */ #define AUE_SETUID 200 /* XXXRW: Solaris old setuid? */ #define AUE_STIME 201 /* XXXRW: Solaris old stime? */ #define AUE_UTIME 202 /* XXXRW: Solaris old utime? */ #define AUE_NICE 203 /* XXXRW: Solaris old nice? */ #define AUE_OSETPGRP 204 /* Solaris-specific. */ #define AUE_SETGID 205 #define AUE_READL 206 /* Solaris-specific. */ #define AUE_READVL 207 /* Solaris-specific. */ #define AUE_FSTAT 208 #define AUE_DUP2 209 #define AUE_MMAP 210 #define AUE_AUDIT 211 #define AUE_PRIOCNTLSYS 212 /* Solaris-specific. */ #define AUE_MUNMAP 213 #define AUE_SETEGID 214 #define AUE_SETEUID 215 #define AUE_PUTMSG 216 /* Solaris-specific. */ #define AUE_GETMSG 217 /* Solaris-specific. */ #define AUE_PUTPMSG 218 /* Solaris-specific. */ #define AUE_GETPMSG 219 /* Solaris-specific. */ #define AUE_AUDITSYS 220 /* Solaris-specific. */ #define AUE_AUDITON_GETKMASK 221 #define AUE_AUDITON_SETKMASK 222 #define AUE_AUDITON_GETCWD 223 #define AUE_AUDITON_GETCAR 224 #define AUE_AUDITON_GETSTAT 225 #define AUE_AUDITON_SETSTAT 226 #define AUE_AUDITON_SETUMASK 227 #define AUE_AUDITON_SETSMASK 228 #define AUE_AUDITON_GETCOND 229 #define AUE_AUDITON_SETCOND 230 #define AUE_AUDITON_GETCLASS 231 #define AUE_AUDITON_SETCLASS 232 #define AUE_FUSERS 233 /* Solaris-specific; also UTSSYS? */ #define AUE_STATVFS 234 #define AUE_XSTAT 235 /* Solaris-specific. */ #define AUE_LXSTAT 236 /* Solaris-specific. */ #define AUE_LCHOWN 237 #define AUE_MEMCNTL 238 /* Solaris-specific. */ #define AUE_SYSINFO 239 /* Solaris-specific. */ #define AUE_XMKNOD 240 /* Solaris-specific. */ #define AUE_FORK1 241 #define AUE_MODCTL 242 /* Solaris-specific. */ #define AUE_MODLOAD 243 #define AUE_MODUNLOAD 244 #define AUE_MODCONFIG 245 /* Solaris-specific. */ #define AUE_MODADDMAJ 246 /* Solaris-specific. */ #define AUE_SOCKACCEPT 247 /* Solaris-specific. */ #define AUE_SOCKCONNECT 248 /* Solaris-specific. */ #define AUE_SOCKSEND 249 /* Solaris-specific. */ #define AUE_SOCKRECEIVE 250 /* Solaris-specific. */ #define AUE_ACLSET 251 #define AUE_FACLSET 252 #define AUE_DOORFS 253 /* Solaris-specific. */ #define AUE_DOORFS_DOOR_CALL 254 /* Solaris-specific. */ #define AUE_DOORFS_DOOR_RETURN 255 /* Solaris-specific. */ #define AUE_DOORFS_DOOR_CREATE 256 /* Solaris-specific. */ #define AUE_DOORFS_DOOR_REVOKE 257 /* Solaris-specific. */ #define AUE_DOORFS_DOOR_INFO 258 /* Solaris-specific. */ #define AUE_DOORFS_DOOR_CRED 259 /* Solaris-specific. */ #define AUE_DOORFS_DOOR_BIND 260 /* Solaris-specific. */ #define AUE_DOORFS_DOOR_UNBIND 261 /* Solaris-specific. */ #define AUE_P_ONLINE 262 /* Solaris-specific. */ #define AUE_PROCESSOR_BIND 263 /* Solaris-specific. */ #define AUE_INST_SYNC 264 /* Solaris-specific. */ #define AUE_SOCKCONFIG 265 /* Solaris-specific. */ #define AUE_SETAUDIT_ADDR 266 #define AUE_GETAUDIT_ADDR 267 #define AUE_UMOUNT2 268 /* Solaris-specific. */ #define AUE_FSAT 269 /* Solaris-specific. */ #define AUE_OPENAT_R 270 #define AUE_OPENAT_RC 271 #define AUE_OPENAT_RT 272 #define AUE_OPENAT_RTC 273 #define AUE_OPENAT_W 274 #define AUE_OPENAT_WC 275 #define AUE_OPENAT_WT 276 #define AUE_OPENAT_WTC 277 #define AUE_OPENAT_RW 278 #define AUE_OPENAT_RWC 279 #define AUE_OPENAT_RWT 280 #define AUE_OPENAT_RWTC 281 #define AUE_RENAMEAT 282 #define AUE_FSTATAT 283 #define AUE_FCHOWNAT 284 #define AUE_FUTIMESAT 285 #define AUE_UNLINKAT 286 #define AUE_CLOCK_SETTIME 287 #define AUE_NTP_ADJTIME 288 #define AUE_SETPPRIV 289 /* Solaris-specific. */ #define AUE_MODDEVPLCY 290 /* Solaris-specific. */ #define AUE_MODADDPRIV 291 /* Solaris-specific. */ #define AUE_CRYPTOADM 292 /* Solaris-specific. */ #define AUE_CONFIGKSSL 293 /* Solaris-specific. */ #define AUE_BRANDSYS 294 /* Solaris-specific. */ #define AUE_PF_POLICY_ADDRULE 295 /* Solaris-specific. */ #define AUE_PF_POLICY_DELRULE 296 /* Solaris-specific. */ #define AUE_PF_POLICY_CLONE 297 /* Solaris-specific. */ #define AUE_PF_POLICY_FLIP 298 /* Solaris-specific. */ #define AUE_PF_POLICY_FLUSH 299 /* Solaris-specific. */ #define AUE_PF_POLICY_ALGS 300 /* Solaris-specific. */ #define AUE_PORTFS 301 /* Solaris-specific. */ /* * Events added for Apple Darwin that potentially collide with future Solaris * BSM events. These are assigned AUE_DARWIN prefixes, and are deprecated in * new trails. Systems generating these events should switch to the new * identifiers that avoid colliding with the Solaris identifier space. */ #define AUE_DARWIN_GETFSSTAT 301 #define AUE_DARWIN_PTRACE 302 #define AUE_DARWIN_CHFLAGS 303 #define AUE_DARWIN_FCHFLAGS 304 #define AUE_DARWIN_PROFILE 305 #define AUE_DARWIN_KTRACE 306 #define AUE_DARWIN_SETLOGIN 307 #define AUE_DARWIN_REBOOT 308 #define AUE_DARWIN_REVOKE 309 #define AUE_DARWIN_UMASK 310 #define AUE_DARWIN_MPROTECT 311 #define AUE_DARWIN_SETPRIORITY 312 #define AUE_DARWIN_SETTIMEOFDAY 313 #define AUE_DARWIN_FLOCK 314 #define AUE_DARWIN_MKFIFO 315 #define AUE_DARWIN_POLL 316 #define AUE_DARWIN_SOCKETPAIR 317 #define AUE_DARWIN_FUTIMES 318 #define AUE_DARWIN_SETSID 319 #define AUE_DARWIN_SETPRIVEXEC 320 /* Darwin-specific. */ #define AUE_DARWIN_NFSSVC 321 #define AUE_DARWIN_GETFH 322 #define AUE_DARWIN_QUOTACTL 323 #define AUE_DARWIN_ADDPROFILE 324 /* Darwin-specific. */ #define AUE_DARWIN_KDEBUGTRACE 325 /* Darwin-specific. */ #define AUE_DARWIN_KDBUGTRACE AUE_KDEBUGTRACE #define AUE_DARWIN_FSTAT 326 #define AUE_DARWIN_FPATHCONF 327 #define AUE_DARWIN_GETDIRENTRIES 328 #define AUE_DARWIN_TRUNCATE 329 #define AUE_DARWIN_FTRUNCATE 330 #define AUE_DARWIN_SYSCTL 331 #define AUE_DARWIN_MLOCK 332 #define AUE_DARWIN_MUNLOCK 333 #define AUE_DARWIN_UNDELETE 334 #define AUE_DARWIN_GETATTRLIST 335 /* Darwin-specific. */ #define AUE_DARWIN_SETATTRLIST 336 /* Darwin-specific. */ #define AUE_DARWIN_GETDIRENTRIESATTR 337 /* Darwin-specific. */ #define AUE_DARWIN_EXCHANGEDATA 338 /* Darwin-specific. */ #define AUE_DARWIN_SEARCHFS 339 /* Darwin-specific. */ #define AUE_DARWIN_MINHERIT 340 #define AUE_DARWIN_SEMCONFIG 341 #define AUE_DARWIN_SEMOPEN 342 #define AUE_DARWIN_SEMCLOSE 343 #define AUE_DARWIN_SEMUNLINK 344 #define AUE_DARWIN_SHMOPEN 345 #define AUE_DARWIN_SHMUNLINK 346 #define AUE_DARWIN_LOADSHFILE 347 /* Darwin-specific. */ #define AUE_DARWIN_RESETSHFILE 348 /* Darwin-specific. */ #define AUE_DARWIN_NEWSYSTEMSHREG 349 /* Darwin-specific. */ #define AUE_DARWIN_PTHREADKILL 350 /* Darwin-specific. */ #define AUE_DARWIN_PTHREADSIGMASK 351 /* Darwin-specific. */ #define AUE_DARWIN_AUDITCTL 352 #define AUE_DARWIN_RFORK 353 #define AUE_DARWIN_LCHMOD 354 #define AUE_DARWIN_SWAPOFF 355 #define AUE_DARWIN_INITPROCESS 356 /* Darwin-specific. */ #define AUE_DARWIN_MAPFD 357 /* Darwin-specific. */ #define AUE_DARWIN_TASKFORPID 358 /* Darwin-specific. */ #define AUE_DARWIN_PIDFORTASK 359 /* Darwin-specific. */ #define AUE_DARWIN_SYSCTL_NONADMIN 360 #define AUE_DARWIN_COPYFILE 361 /* Darwin-specific. */ /* * Audit event identifiers added as part of OpenBSM, generally corresponding * to events in FreeBSD, Darwin, and Linux that were not present in Solaris. * These often duplicate events added to the Solaris set by Darwin, but use * event identifiers in a higher range in order to avoid colliding with * future Solaris additions. * * If an event in this section is later added to Solaris, we prefer the * Solaris event identifier, and add _OPENBSM_ to the OpenBSM-specific * identifier so that old trails can still be processed, but new trails use * the Solaris identifier. */ #define AUE_GETFSSTAT 43001 #define AUE_PTRACE 43002 #define AUE_CHFLAGS 43003 #define AUE_FCHFLAGS 43004 #define AUE_PROFILE 43005 #define AUE_KTRACE 43006 #define AUE_SETLOGIN 43007 #define AUE_OPENBSM_REVOKE 43008 /* Solaris event now preferred. */ #define AUE_UMASK 43009 #define AUE_MPROTECT 43010 #define AUE_MKFIFO 43011 #define AUE_POLL 43012 #define AUE_FUTIMES 43013 #define AUE_SETSID 43014 #define AUE_SETPRIVEXEC 43015 /* Darwin-specific. */ #define AUE_ADDPROFILE 43016 /* Darwin-specific. */ #define AUE_KDEBUGTRACE 43017 /* Darwin-specific. */ #define AUE_KDBUGTRACE AUE_KDEBUGTRACE #define AUE_OPENBSM_FSTAT 43018 /* Solaris event now preferred. */ #define AUE_FPATHCONF 43019 #define AUE_GETDIRENTRIES 43020 #define AUE_SYSCTL 43021 #define AUE_MLOCK 43022 #define AUE_MUNLOCK 43023 #define AUE_UNDELETE 43024 #define AUE_GETATTRLIST 43025 /* Darwin-specific. */ #define AUE_SETATTRLIST 43026 /* Darwin-specific. */ #define AUE_GETDIRENTRIESATTR 43027 /* Darwin-specific. */ #define AUE_EXCHANGEDATA 43028 /* Darwin-specific. */ #define AUE_SEARCHFS 43029 /* Darwin-specific. */ #define AUE_MINHERIT 43030 #define AUE_SEMCONFIG 43031 #define AUE_SEMOPEN 43032 #define AUE_SEMCLOSE 43033 #define AUE_SEMUNLINK 43034 #define AUE_SHMOPEN 43035 #define AUE_SHMUNLINK 43036 #define AUE_LOADSHFILE 43037 /* Darwin-specific. */ #define AUE_RESETSHFILE 43038 /* Darwin-specific. */ #define AUE_NEWSYSTEMSHREG 43039 /* Darwin-specific. */ #define AUE_PTHREADKILL 43040 /* Darwin-specific. */ #define AUE_PTHREADSIGMASK 43041 /* Darwin-specific. */ #define AUE_AUDITCTL 43042 #define AUE_RFORK 43043 #define AUE_LCHMOD 43044 #define AUE_SWAPOFF 43045 #define AUE_INITPROCESS 43046 /* Darwin-specific. */ #define AUE_MAPFD 43047 /* Darwin-specific. */ #define AUE_TASKFORPID 43048 /* Darwin-specific. */ #define AUE_PIDFORTASK 43049 /* Darwin-specific. */ #define AUE_SYSCTL_NONADMIN 43050 #define AUE_COPYFILE 43051 /* Darwin-specific. */ /* * Events added to OpenBSM for FreeBSD and Linux; may also be used by Darwin * in the future. */ #define AUE_LUTIMES 43052 #define AUE_LCHFLAGS 43053 /* FreeBSD-specific. */ #define AUE_SENDFILE 43054 /* BSD/Linux-specific. */ #define AUE_USELIB 43055 /* Linux-specific. */ #define AUE_GETRESUID 43056 #define AUE_SETRESUID 43057 #define AUE_GETRESGID 43058 #define AUE_SETRESGID 43059 #define AUE_WAIT4 43060 /* FreeBSD-specific. */ #define AUE_LGETFH 43061 /* FreeBSD-specific. */ #define AUE_FHSTATFS 43062 /* FreeBSD-specific. */ #define AUE_FHOPEN 43063 /* FreeBSD-specific. */ #define AUE_FHSTAT 43064 /* FreeBSD-specific. */ #define AUE_JAIL 43065 /* FreeBSD-specific. */ #define AUE_EACCESS 43066 /* FreeBSD-specific. */ #define AUE_KQUEUE 43067 /* FreeBSD-specific. */ #define AUE_KEVENT 43068 /* FreeBSD-specific. */ #define AUE_FSYNC 43069 #define AUE_NMOUNT 43070 /* FreeBSD-specific. */ #define AUE_BDFLUSH 43071 /* Linux-specific. */ #define AUE_SETFSUID 43072 /* Linux-specific. */ #define AUE_SETFSGID 43073 /* Linux-specific. */ #define AUE_PERSONALITY 43074 /* Linux-specific. */ #define AUE_SCHED_GETSCHEDULER 43075 /* POSIX.1b. */ #define AUE_SCHED_SETSCHEDULER 43076 /* POSIX.1b. */ #define AUE_PRCTL 43077 /* Linux-specific. */ #define AUE_GETCWD 43078 /* FreeBSD/Linux-specific. */ #define AUE_CAPGET 43079 /* Linux-specific. */ #define AUE_CAPSET 43080 /* Linux-specific. */ #define AUE_PIVOT_ROOT 43081 /* Linux-specific. */ #define AUE_RTPRIO 43082 /* FreeBSD-specific. */ #define AUE_SCHED_GETPARAM 43083 /* POSIX.1b. */ #define AUE_SCHED_SETPARAM 43084 /* POSIX.1b. */ #define AUE_SCHED_GET_PRIORITY_MAX 43085 /* POSIX.1b. */ #define AUE_SCHED_GET_PRIORITY_MIN 43086 /* POSIX.1b. */ #define AUE_SCHED_RR_GET_INTERVAL 43087 /* POSIX.1b. */ #define AUE_ACL_GET_FILE 43088 /* FreeBSD. */ #define AUE_ACL_SET_FILE 43089 /* FreeBSD. */ #define AUE_ACL_GET_FD 43090 /* FreeBSD. */ #define AUE_ACL_SET_FD 43091 /* FreeBSD. */ #define AUE_ACL_DELETE_FILE 43092 /* FreeBSD. */ #define AUE_ACL_DELETE_FD 43093 /* FreeBSD. */ #define AUE_ACL_CHECK_FILE 43094 /* FreeBSD. */ #define AUE_ACL_CHECK_FD 43095 /* FreeBSD. */ #define AUE_ACL_GET_LINK 43096 /* FreeBSD. */ #define AUE_ACL_SET_LINK 43097 /* FreeBSD. */ #define AUE_ACL_DELETE_LINK 43098 /* FreeBSD. */ #define AUE_ACL_CHECK_LINK 43099 /* FreeBSD. */ #define AUE_SYSARCH 43100 /* FreeBSD. */ #define AUE_EXTATTRCTL 43101 /* FreeBSD. */ #define AUE_EXTATTR_GET_FILE 43102 /* FreeBSD. */ #define AUE_EXTATTR_SET_FILE 43103 /* FreeBSD. */ #define AUE_EXTATTR_LIST_FILE 43104 /* FreeBSD. */ #define AUE_EXTATTR_DELETE_FILE 43105 /* FreeBSD. */ #define AUE_EXTATTR_GET_FD 43106 /* FreeBSD. */ #define AUE_EXTATTR_SET_FD 43107 /* FreeBSD. */ #define AUE_EXTATTR_LIST_FD 43108 /* FreeBSD. */ #define AUE_EXTATTR_DELETE_FD 43109 /* FreeBSD. */ #define AUE_EXTATTR_GET_LINK 43110 /* FreeBSD. */ #define AUE_EXTATTR_SET_LINK 43111 /* FreeBSD. */ #define AUE_EXTATTR_LIST_LINK 43112 /* FreeBSD. */ #define AUE_EXTATTR_DELETE_LINK 43113 /* FreeBSD. */ #define AUE_KENV 43114 /* FreeBSD. */ #define AUE_JAIL_ATTACH 43115 /* FreeBSD. */ #define AUE_SYSCTL_WRITE 43116 /* FreeBSD. */ #define AUE_IOPERM 43117 /* Linux. */ #define AUE_READDIR 43118 /* Linux. */ #define AUE_IOPL 43119 /* Linux. */ #define AUE_VM86 43120 /* Linux. */ #define AUE_MAC_GET_PROC 43121 /* FreeBSD/Darwin. */ #define AUE_MAC_SET_PROC 43122 /* FreeBSD/Darwin. */ #define AUE_MAC_GET_FD 43123 /* FreeBSD/Darwin. */ #define AUE_MAC_GET_FILE 43124 /* FreeBSD/Darwin. */ #define AUE_MAC_SET_FD 43125 /* FreeBSD/Darwin. */ #define AUE_MAC_SET_FILE 43126 /* FreeBSD/Darwin. */ #define AUE_MAC_SYSCALL 43127 /* FreeBSD. */ #define AUE_MAC_GET_PID 43128 /* FreeBSD/Darwin. */ #define AUE_MAC_GET_LINK 43129 /* FreeBSD/Darwin. */ #define AUE_MAC_SET_LINK 43130 /* FreeBSD/Darwin. */ #define AUE_MAC_EXECVE 43131 /* FreeBSD/Darwin. */ #define AUE_GETPATH_FROMFD 43132 /* FreeBSD. */ #define AUE_GETPATH_FROMADDR 43133 /* FreeBSD. */ #define AUE_MQ_OPEN 43134 /* FreeBSD. */ #define AUE_MQ_SETATTR 43135 /* FreeBSD. */ #define AUE_MQ_TIMEDRECEIVE 43136 /* FreeBSD. */ #define AUE_MQ_TIMEDSEND 43137 /* FreeBSD. */ #define AUE_MQ_NOTIFY 43138 /* FreeBSD. */ #define AUE_MQ_UNLINK 43139 /* FreeBSD. */ #define AUE_LISTEN 43140 /* FreeBSD/Darwin/Linux. */ #define AUE_MLOCKALL 43141 /* FreeBSD. */ #define AUE_MUNLOCKALL 43142 /* FreeBSD. */ #define AUE_CLOSEFROM 43143 /* FreeBSD. */ #define AUE_FEXECVE 43144 /* FreeBSD. */ #define AUE_FACCESSAT 43145 /* FreeBSD. */ #define AUE_FCHMODAT 43146 /* FreeBSD. */ #define AUE_LINKAT 43147 /* FreeBSD. */ #define AUE_MKDIRAT 43148 /* FreeBSD. */ #define AUE_MKFIFOAT 43149 /* FreeBSD. */ #define AUE_MKNODAT 43150 /* FreeBSD. */ #define AUE_READLINKAT 43151 /* FreeBSD. */ #define AUE_SYMLINKAT 43152 /* FreeBSD. */ #define AUE_MAC_GETFSSTAT 43153 /* Darwin. */ #define AUE_MAC_GET_MOUNT 43154 /* Darwin. */ #define AUE_MAC_GET_LCID 43155 /* Darwin. */ #define AUE_MAC_GET_LCTX 43156 /* Darwin. */ #define AUE_MAC_SET_LCTX 43157 /* Darwin. */ #define AUE_MAC_MOUNT 43158 /* Darwin. */ #define AUE_GETLCID 43159 /* Darwin. */ #define AUE_SETLCID 43160 /* Darwin. */ #define AUE_TASKNAMEFORPID 43161 /* Darwin. */ #define AUE_ACCESS_EXTENDED 43162 /* Darwin. */ #define AUE_CHMOD_EXTENDED 43163 /* Darwin. */ #define AUE_FCHMOD_EXTENDED 43164 /* Darwin. */ #define AUE_FSTAT_EXTENDED 43165 /* Darwin. */ #define AUE_LSTAT_EXTENDED 43166 /* Darwin. */ #define AUE_MKDIR_EXTENDED 43167 /* Darwin. */ #define AUE_MKFIFO_EXTENDED 43168 /* Darwin. */ #define AUE_OPEN_EXTENDED 43169 /* Darwin. */ #define AUE_OPEN_EXTENDED_R 43170 /* Darwin. */ #define AUE_OPEN_EXTENDED_RC 43171 /* Darwin. */ #define AUE_OPEN_EXTENDED_RT 43172 /* Darwin. */ #define AUE_OPEN_EXTENDED_RTC 43173 /* Darwin. */ #define AUE_OPEN_EXTENDED_W 43174 /* Darwin. */ #define AUE_OPEN_EXTENDED_WC 43175 /* Darwin. */ #define AUE_OPEN_EXTENDED_WT 43176 /* Darwin. */ #define AUE_OPEN_EXTENDED_WTC 43177 /* Darwin. */ #define AUE_OPEN_EXTENDED_RW 43178 /* Darwin. */ #define AUE_OPEN_EXTENDED_RWC 43179 /* Darwin. */ #define AUE_OPEN_EXTENDED_RWT 43180 /* Darwin. */ #define AUE_OPEN_EXTENDED_RWTC 43181 /* Darwin. */ #define AUE_STAT_EXTENDED 43182 /* Darwin. */ #define AUE_UMASK_EXTENDED 43183 /* Darwin. */ #define AUE_OPENAT 43184 /* FreeBSD. */ #define AUE_POSIX_OPENPT 43185 /* FreeBSD. */ #define AUE_CAP_NEW 43186 /* TrustedBSD. */ -#define AUE_CAP_GETRIGHTS 43187 /* TrustedBSD. */ +#define AUE_CAP_RIGHTS_GET 43187 /* TrustedBSD. */ +#define AUE_CAP_GETRIGHTS AUE_CAP_RIGHTS_GET #define AUE_CAP_ENTER 43188 /* TrustedBSD. */ #define AUE_CAP_GETMODE 43189 /* TrustedBSD. */ #define AUE_POSIX_SPAWN 43190 /* Darwin. */ #define AUE_FSGETPATH 43191 /* Darwin. */ #define AUE_PREAD 43192 /* Darwin/FreeBSD. */ #define AUE_PWRITE 43193 /* Darwin/FreeBSD. */ #define AUE_FSCTL 43194 /* Darwin. */ #define AUE_FFSCTL 43195 /* Darwin. */ #define AUE_LPATHCONF 43196 /* FreeBSD. */ #define AUE_PDFORK 43197 /* FreeBSD. */ #define AUE_PDKILL 43198 /* FreeBSD. */ #define AUE_PDGETPID 43199 /* FreeBSD. */ #define AUE_PDWAIT 43200 /* FreeBSD. */ #define AUE_WAIT6 43201 /* FreeBSD. */ +#define AUE_CAP_RIGHTS_LIMIT 43202 /* TrustedBSD. */ +#define AUE_CAP_IOCTLS_LIMIT 43203 /* TrustedBSD. */ +#define AUE_CAP_IOCTLS_GET 43204 /* TrustedBSD. */ +#define AUE_CAP_FCNTLS_LIMIT 43205 /* TrustedBSD. */ +#define AUE_CAP_FCNTLS_GET 43206 /* TrustedBSD. */ +#define AUE_BINDAT 43207 /* TrustedBSD. */ +#define AUE_CONNECTAT 43208 /* TrustedBSD. */ +#define AUE_CHFLAGSAT 43209 /* FreeBSD-specific. */ /* * Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the * normal Solaris BSM identifiers. _O_ refers to it being an old, or compat * interface. In most cases, Darwin has never implemented these system calls * but picked up the fields in their system call table from their FreeBSD * import. Happily, these have different names than the AUE_O* definitions * in Solaris BSM. */ #define AUE_O_CREAT AUE_OPEN_RWTC /* Darwin */ #define AUE_O_EXECVE AUE_NULL /* Darwin */ #define AUE_O_SBREAK AUE_NULL /* Darwin */ #define AUE_O_LSEEK AUE_NULL /* Darwin */ #define AUE_O_MOUNT AUE_NULL /* Darwin */ #define AUE_O_UMOUNT AUE_NULL /* Darwin */ #define AUE_O_STAT AUE_STAT /* Darwin */ #define AUE_O_LSTAT AUE_LSTAT /* Darwin */ #define AUE_O_FSTAT AUE_FSTAT /* Darwin */ #define AUE_O_GETPAGESIZE AUE_NULL /* Darwin */ #define AUE_O_VREAD AUE_NULL /* Darwin */ #define AUE_O_VWRITE AUE_NULL /* Darwin */ #define AUE_O_MMAP AUE_MMAP /* Darwin */ #define AUE_O_VADVISE AUE_NULL /* Darwin */ #define AUE_O_VHANGUP AUE_NULL /* Darwin */ #define AUE_O_VLIMIT AUE_NULL /* Darwin */ #define AUE_O_WAIT AUE_NULL /* Darwin */ #define AUE_O_GETHOSTNAME AUE_NULL /* Darwin */ #define AUE_O_SETHOSTNAME AUE_SYSCTL /* Darwin */ #define AUE_O_GETDOPT AUE_NULL /* Darwin */ #define AUE_O_SETDOPT AUE_NULL /* Darwin */ #define AUE_O_ACCEPT AUE_NULL /* Darwin */ #define AUE_O_SEND AUE_SENDMSG /* Darwin */ #define AUE_O_RECV AUE_RECVMSG /* Darwin */ #define AUE_O_VTIMES AUE_NULL /* Darwin */ #define AUE_O_SIGVEC AUE_NULL /* Darwin */ #define AUE_O_SIGBLOCK AUE_NULL /* Darwin */ #define AUE_O_SIGSETMASK AUE_NULL /* Darwin */ #define AUE_O_SIGSTACK AUE_NULL /* Darwin */ #define AUE_O_RECVMSG AUE_RECVMSG /* Darwin */ #define AUE_O_SENDMSG AUE_SENDMSG /* Darwin */ #define AUE_O_VTRACE AUE_NULL /* Darwin */ #define AUE_O_RESUBA AUE_NULL /* Darwin */ #define AUE_O_RECVFROM AUE_RECVFROM /* Darwin */ #define AUE_O_SETREUID AUE_SETREUID /* Darwin */ #define AUE_O_SETREGID AUE_SETREGID /* Darwin */ #define AUE_O_GETDIRENTRIES AUE_GETDIRENTRIES /* Darwin */ #define AUE_O_TRUNCATE AUE_TRUNCATE /* Darwin */ #define AUE_O_FTRUNCATE AUE_FTRUNCATE /* Darwin */ #define AUE_O_GETPEERNAME AUE_NULL /* Darwin */ #define AUE_O_GETHOSTID AUE_NULL /* Darwin */ #define AUE_O_SETHOSTID AUE_NULL /* Darwin */ #define AUE_O_GETRLIMIT AUE_NULL /* Darwin */ #define AUE_O_SETRLIMIT AUE_SETRLIMIT /* Darwin */ #define AUE_O_KILLPG AUE_KILL /* Darwin */ #define AUE_O_SETQUOTA AUE_NULL /* Darwin */ #define AUE_O_QUOTA AUE_NULL /* Darwin */ #define AUE_O_GETSOCKNAME AUE_NULL /* Darwin */ #define AUE_O_GETDIREENTRIES AUE_GETDIREENTRIES /* Darwin */ #define AUE_O_ASYNCDAEMON AUE_NULL /* Darwin */ #define AUE_O_GETDOMAINNAME AUE_NULL /* Darwin */ #define AUE_O_SETDOMAINNAME AUE_SYSCTL /* Darwin */ #define AUE_O_PCFS_MOUNT AUE_NULL /* Darwin */ #define AUE_O_EXPORTFS AUE_NULL /* Darwin */ #define AUE_O_USTATE AUE_NULL /* Darwin */ #define AUE_O_WAIT3 AUE_NULL /* Darwin */ #define AUE_O_RPAUSE AUE_NULL /* Darwin */ #define AUE_O_GETDENTS AUE_NULL /* Darwin */ /* * Possible desired future values based on review of BSD/Darwin system calls. */ #define AUE_ATGETMSG AUE_NULL #define AUE_ATPUTMSG AUE_NULL #define AUE_ATSOCKET AUE_NULL #define AUE_ATPGETREQ AUE_NULL #define AUE_ATPGETRSP AUE_NULL #define AUE_ATPSNDREQ AUE_NULL #define AUE_ATPSNDRSP AUE_NULL #define AUE_BSDTHREADCREATE AUE_NULL #define AUE_BSDTHREADTERMINATE AUE_NULL #define AUE_BSDTHREADREGISTER AUE_NULL #define AUE_CHUD AUE_NULL #define AUE_CSOPS AUE_NULL #define AUE_DUP AUE_NULL #define AUE_FDATASYNC AUE_NULL #define AUE_FGETATTRLIST AUE_NULL #define AUE_FGETXATTR AUE_NULL #define AUE_FLISTXATTR AUE_NULL #define AUE_FREMOVEXATTR AUE_NULL #define AUE_FSETATTRLIST AUE_NULL #define AUE_FSETXATTR AUE_NULL #define AUE_FSTATFS64 AUE_NULL #define AUE_FSTATV AUE_NULL #define AUE_FSTAT64 AUE_NULL #define AUE_FSTAT64_EXTENDED AUE_NULL #define AUE_GCCONTROL AUE_NULL #define AUE_GETDIRENTRIES64 AUE_NULL #define AUE_GETDTABLESIZE AUE_NULL #define AUE_GETEGID AUE_NULL #define AUE_GETEUID AUE_NULL #define AUE_GETFSSTAT64 AUE_NULL #define AUE_GETGID AUE_NULL #define AUE_GETGROUPS AUE_NULL #define AUE_GETITIMER AUE_NULL #define AUE_GETLOGIN AUE_NULL #define AUE_GETPEERNAME AUE_NULL #define AUE_GETPGID AUE_NULL #define AUE_GETPGRP AUE_NULL #define AUE_GETPID AUE_NULL #define AUE_GETPPID AUE_NULL #define AUE_GETPRIORITY AUE_NULL #define AUE_GETRLIMIT AUE_NULL #define AUE_GETRUSAGE AUE_NULL #define AUE_GETSGROUPS AUE_NULL #define AUE_GETSID AUE_NULL #define AUE_GETSOCKNAME AUE_NULL #define AUE_GETTIMEOFDAY AUE_NULL #define AUE_GETTID AUE_NULL #define AUE_GETUID AUE_NULL #define AUE_GETSOCKOPT AUE_NULL #define AUE_GETWGROUPS AUE_NULL #define AUE_GETXATTR AUE_NULL #define AUE_IDENTITYSVC AUE_NULL #define AUE_INITGROUPS AUE_NULL #define AUE_IOPOLICYSYS AUE_NULL #define AUE_ISSETUGID AUE_NULL #define AUE_LIOLISTIO AUE_NULL #define AUE_LISTXATTR AUE_NULL #define AUE_LSTATV AUE_NULL #define AUE_LSTAT64 AUE_NULL #define AUE_LSTAT64_EXTENDED AUE_NULL #define AUE_MADVISE AUE_NULL #define AUE_MINCORE AUE_NULL #define AUE_MKCOMPLEX AUE_NULL #define AUE_MODWATCH AUE_NULL #define AUE_MSGCL AUE_NULL #define AUE_MSYNC AUE_NULL #define AUE_PREADV AUE_NULL #define AUE_PROCINFO AUE_NULL #define AUE_PTHREADCANCELED AUE_NULL #define AUE_PTHREADCHDIR AUE_NULL #define AUE_PTHREADCONDBROADCAST AUE_NULL #define AUE_PTHREADCONDDESTORY AUE_NULL #define AUE_PTHREADCONDINIT AUE_NULL #define AUE_PTHREADCONDSIGNAL AUE_NULL #define AUE_PTHREADCONDWAIT AUE_NULL #define AUE_PTHREADFCHDIR AUE_NULL #define AUE_PTHREADMARK AUE_NULL #define AUE_PTHREADMUTEXDESTROY AUE_NULL #define AUE_PTHREADMUTEXINIT AUE_NULL #define AUE_PTHREADMUTEXTRYLOCK AUE_NULL #define AUE_PTHREADMUTEXUNLOCK AUE_NULL #define AUE_PWRITEV AUE_NULL #define AUE_REMOVEXATTR AUE_NULL #define AUE_SBRK AUE_NULL #define AUE_SELECT AUE_NULL #define AUE_SEMDESTROY AUE_NULL #define AUE_SEMGETVALUE AUE_NULL #define AUE_SEMINIT AUE_NULL #define AUE_SEMPOST AUE_NULL #define AUE_SEMTRYWAIT AUE_NULL #define AUE_SEMWAIT AUE_NULL #define AUE_SEMWAITSIGNAL AUE_NULL #define AUE_SETITIMER AUE_NULL #define AUE_SETSGROUPS AUE_NULL #define AUE_SETTID AUE_NULL #define AUE_SETTIDWITHPID AUE_NULL #define AUE_SETWGROUPS AUE_NULL #define AUE_SETXATTR AUE_NULL #define AUE_SHAREDREGIONCHECK AUE_NULL #define AUE_SHAREDREGIONMAP AUE_NULL #define AUE_SIGACTION AUE_NULL #define AUE_SIGALTSTACK AUE_NULL #define AUE_SIGPENDING AUE_NULL #define AUE_SIGPROCMASK AUE_NULL #define AUE_SIGRETURN AUE_NULL #define AUE_SIGSUSPEND AUE_NULL #define AUE_SIGWAIT AUE_NULL #define AUE_SSTK AUE_NULL #define AUE_STACKSNAPSHOT AUE_NULL #define AUE_STATFS64 AUE_NULL #define AUE_STATV AUE_NULL #define AUE_STAT64 AUE_NULL #define AUE_STAT64_EXTENDED AUE_NULL #define AUE_SYNC AUE_NULL #define AUE_SYSCALL AUE_NULL #define AUE_TABLE AUE_NULL #define AUE_VMPRESSUREMONITOR AUE_NULL #define AUE_WAITEVENT AUE_NULL #define AUE_WAITID AUE_NULL #define AUE_WATCHEVENT AUE_NULL #define AUE_WORKQOPEN AUE_NULL #define AUE_WORKQOPS AUE_NULL #endif /* !_BSM_AUDIT_KEVENTS_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_record.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_record.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_record.h (revision 292449) @@ -1,300 +1,298 @@ /*- * Copyright (c) 2005-2009 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/sys/bsm/audit_record.h#12 $ */ #ifndef _BSM_AUDIT_RECORD_H_ #define _BSM_AUDIT_RECORD_H_ #include /* struct timeval */ /* * Token type identifiers. */ #define AUT_INVALID 0x00 #define AUT_OTHER_FILE32 0x11 #define AUT_OHEADER 0x12 #define AUT_TRAILER 0x13 #define AUT_HEADER32 0x14 #define AUT_HEADER32_EX 0x15 #define AUT_DATA 0x21 #define AUT_IPC 0x22 #define AUT_PATH 0x23 #define AUT_SUBJECT32 0x24 #define AUT_XATPATH 0x25 #define AUT_PROCESS32 0x26 #define AUT_RETURN32 0x27 #define AUT_TEXT 0x28 #define AUT_OPAQUE 0x29 #define AUT_IN_ADDR 0x2a #define AUT_IP 0x2b #define AUT_IPORT 0x2c #define AUT_ARG32 0x2d #define AUT_SOCKET 0x2e #define AUT_SEQ 0x2f #define AUT_ACL 0x30 #define AUT_ATTR 0x31 #define AUT_IPC_PERM 0x32 #define AUT_LABEL 0x33 #define AUT_GROUPS 0x34 #define AUT_ACE 0x35 #define AUT_PRIV 0x38 #define AUT_UPRIV 0x39 #define AUT_LIAISON 0x3a #define AUT_NEWGROUPS 0x3b #define AUT_EXEC_ARGS 0x3c #define AUT_EXEC_ENV 0x3d #define AUT_ATTR32 0x3e #define AUT_UNAUTH 0x3f #define AUT_XATOM 0x40 #define AUT_XOBJ 0x41 #define AUT_XPROTO 0x42 #define AUT_XSELECT 0x43 #define AUT_XCOLORMAP 0x44 #define AUT_XCURSOR 0x45 #define AUT_XFONT 0x46 #define AUT_XGC 0x47 #define AUT_XPIXMAP 0x48 #define AUT_XPROPERTY 0x49 #define AUT_XWINDOW 0x4a #define AUT_XCLIENT 0x4b #define AUT_CMD 0x51 #define AUT_EXIT 0x52 #define AUT_ZONENAME 0x60 #define AUT_HOST 0x70 #define AUT_ARG64 0x71 #define AUT_RETURN64 0x72 #define AUT_ATTR64 0x73 #define AUT_HEADER64 0x74 #define AUT_SUBJECT64 0x75 #define AUT_PROCESS64 0x77 #define AUT_OTHER_FILE64 0x78 #define AUT_HEADER64_EX 0x79 #define AUT_SUBJECT32_EX 0x7a #define AUT_PROCESS32_EX 0x7b #define AUT_SUBJECT64_EX 0x7c #define AUT_PROCESS64_EX 0x7d #define AUT_IN_ADDR_EX 0x7e #define AUT_SOCKET_EX 0x7f /* * Pre-64-bit BSM, 32-bit tokens weren't explicitly named as '32'. We have * compatibility defines. */ #define AUT_HEADER AUT_HEADER32 #define AUT_ARG AUT_ARG32 #define AUT_RETURN AUT_RETURN32 #define AUT_SUBJECT AUT_SUBJECT32 #define AUT_PROCESS AUT_PROCESS32 #define AUT_OTHER_FILE AUT_OTHER_FILE32 /* * The values for the following token ids are not defined by BSM. * * XXXRW: Not sure how to handle these in OpenBSM yet, but I'll give them * names more consistent with Sun's BSM. These originally came from Apple's * BSM. */ #define AUT_SOCKINET32 0x80 /* XXX */ #define AUT_SOCKINET128 0x81 /* XXX */ #define AUT_SOCKUNIX 0x82 /* XXX */ /* print values for the arbitrary token */ #define AUP_BINARY 0 #define AUP_OCTAL 1 #define AUP_DECIMAL 2 #define AUP_HEX 3 #define AUP_STRING 4 /* data-types for the arbitrary token */ #define AUR_BYTE 0 #define AUR_CHAR AUR_BYTE #define AUR_SHORT 1 #define AUR_INT32 2 #define AUR_INT AUR_INT32 #define AUR_INT64 3 /* ... and their sizes */ #define AUR_BYTE_SIZE sizeof(u_char) #define AUR_CHAR_SIZE AUR_BYTE_SIZE #define AUR_SHORT_SIZE sizeof(uint16_t) #define AUR_INT32_SIZE sizeof(uint32_t) #define AUR_INT_SIZE AUR_INT32_SIZE #define AUR_INT64_SIZE sizeof(uint64_t) /* Modifiers for the header token */ #define PAD_NOTATTR 0x4000 /* nonattributable event */ #define PAD_FAILURE 0x8000 /* fail audit event */ #define AUDIT_MAX_GROUPS 16 /* * A number of BSM versions are floating around and defined. Here are * constants for them. OpenBSM uses the same token types, etc, used in the * Solaris BSM version, but has a separate version number in order to * identify a potentially different event identifier name space. */ #define AUDIT_HEADER_VERSION_OLDDARWIN 1 /* In retrospect, a mistake. */ #define AUDIT_HEADER_VERSION_SOLARIS 2 #define AUDIT_HEADER_VERSION_TSOL25 3 #define AUDIT_HEADER_VERSION_TSOL 4 #define AUDIT_HEADER_VERSION_OPENBSM10 10 #define AUDIT_HEADER_VERSION_OPENBSM11 11 #define AUDIT_HEADER_VERSION_OPENBSM AUDIT_HEADER_VERSION_OPENBSM11 #define AUT_TRAILER_MAGIC 0xb105 /* BSM library calls */ __BEGIN_DECLS struct in_addr; struct in6_addr; struct ip; struct ipc_perm; struct kevent; struct sockaddr; struct sockaddr_in; struct sockaddr_in6; struct sockaddr_un; #if defined(_KERNEL) || defined(KERNEL) struct vnode_au_info; #endif int au_open(void); int au_write(int d, token_t *m); int au_close(int d, int keep, short event); int au_close_buffer(int d, short event, u_char *buffer, size_t *buflen); int au_close_token(token_t *tok, u_char *buffer, size_t *buflen); token_t *au_to_file(const char *file, struct timeval tm); token_t *au_to_header32_tm(int rec_size, au_event_t e_type, au_emod_t e_mod, struct timeval tm); token_t *au_to_header32_ex_tm(int rec_size, au_event_t e_type, au_emod_t e_mod, struct timeval tm, struct auditinfo_addr *aia); token_t *au_to_header64_tm(int rec_size, au_event_t e_type, au_emod_t e_mod, struct timeval tm); #if !defined(KERNEL) && !defined(_KERNEL) token_t *au_to_header(int rec_size, au_event_t e_type, au_emod_t e_mod); token_t *au_to_header_ex(int rec_size, au_event_t e_type, au_emod_t e_mod); token_t *au_to_header32(int rec_size, au_event_t e_type, au_emod_t e_mod); token_t *au_to_header64(int rec_size, au_event_t e_type, au_emod_t e_mod); token_t *au_to_header32_ex(int rec_size, au_event_t e_type, au_emod_t e_mod); #endif token_t *au_to_me(void); token_t *au_to_arg(char n, const char *text, uint32_t v); token_t *au_to_arg32(char n, const char *text, uint32_t v); token_t *au_to_arg64(char n, const char *text, uint64_t v); #if defined(_KERNEL) || defined(KERNEL) token_t *au_to_attr(struct vnode_au_info *vni); token_t *au_to_attr32(struct vnode_au_info *vni); token_t *au_to_attr64(struct vnode_au_info *vni); #endif token_t *au_to_data(char unit_print, char unit_type, char unit_count, const char *p); token_t *au_to_exit(int retval, int err); token_t *au_to_groups(int *groups); token_t *au_to_newgroups(uint16_t n, gid_t *groups); token_t *au_to_in_addr(struct in_addr *internet_addr); token_t *au_to_in_addr_ex(struct in6_addr *internet_addr); token_t *au_to_ip(struct ip *ip); token_t *au_to_ipc(char type, int id); token_t *au_to_ipc_perm(struct ipc_perm *perm); token_t *au_to_iport(uint16_t iport); token_t *au_to_opaque(const char *data, uint16_t bytes); token_t *au_to_path(const char *path); token_t *au_to_privset(char *privtypestr, char *privstr); token_t *au_to_process(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_t *tid); token_t *au_to_process32(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_t *tid); token_t *au_to_process64(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_t *tid); token_t *au_to_process_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid); token_t *au_to_process32_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid); token_t *au_to_process64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid); token_t *au_to_return(char status, uint32_t ret); token_t *au_to_return32(char status, uint32_t ret); token_t *au_to_return64(char status, uint64_t ret); token_t *au_to_seq(long audit_count); token_t *au_to_socket_ex(u_short so_domain, u_short so_type, struct sockaddr *sa_local, struct sockaddr *sa_remote); token_t *au_to_sock_inet(struct sockaddr_in *so); token_t *au_to_sock_inet32(struct sockaddr_in *so); token_t *au_to_sock_inet128(struct sockaddr_in6 *so); token_t *au_to_sock_unix(struct sockaddr_un *so); token_t *au_to_subject(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_t *tid); token_t *au_to_subject32(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_t *tid); token_t *au_to_subject64(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_t *tid); token_t *au_to_subject_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid); token_t *au_to_subject32_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid); token_t *au_to_subject64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid); #if defined(_KERNEL) || defined(KERNEL) token_t *au_to_exec_args(char *args, int argc); token_t *au_to_exec_env(char *envs, int envc); #else token_t *au_to_exec_args(char **argv); token_t *au_to_exec_env(char **envp); #endif token_t *au_to_text(const char *text); token_t *au_to_kevent(struct kevent *kev); token_t *au_to_trailer(int rec_size); token_t *au_to_upriv(char sorf, char *priv); token_t *au_to_zonename(const char *zonename); /* * BSM library routines for converting between local and BSM constant spaces. */ int au_bsm_to_domain(u_short bsm_domain, int *local_domainp); int au_bsm_to_errno(u_char bsm_error, int *errorp); int au_bsm_to_fcntl_cmd(u_short bsm_fcntl_cmd, int *local_fcntl_cmdp); int au_bsm_to_socket_type(u_short bsm_socket_type, int *local_socket_typep); u_short au_domain_to_bsm(int local_domain); u_char au_errno_to_bsm(int local_errno); u_short au_fcntl_cmd_to_bsm(int local_fcntl_command); u_short au_socket_type_to_bsm(int local_socket_type); __END_DECLS #endif /* ! _BSM_AUDIT_RECORD_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_socket_type.h =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_socket_type.h (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/sys/bsm/audit_socket_type.h (revision 292449) @@ -1,46 +1,44 @@ /*- * Copyright (c) 2008 Apple Inc. * 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 Apple Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/sys/bsm/audit_socket_type.h#1 $ */ #ifndef _BSM_AUDIT_SOCKET_TYPE_H_ #define _BSM_AUDIT_SOCKET_TYPE_H_ /* * BSM socket type constants. */ #define BSM_SOCK_DGRAM 1 #define BSM_SOCK_STREAM 2 #define BSM_SOCK_RAW 4 #define BSM_SOCK_RDM 5 #define BSM_SOCK_SEQPACKET 6 #define BSM_SOCK_UNKNOWN 500 #endif /* !_BSM_AUDIT_SOCKET_TYPE_H_ */ Index: user/alc/PQ_LAUNDRY/contrib/openbsm/test/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/test/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/test/Makefile.am (revision 292449) @@ -1,6 +1,2 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/test/Makefile.am#3 $ -## - SUBDIRS = \ bsm Index: user/alc/PQ_LAUNDRY/contrib/openbsm/test/bsm/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/test/bsm/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/test/bsm/Makefile.am (revision 292449) @@ -1,13 +1,9 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/test/bsm/Makefile.am#4 $ -## - if USE_NATIVE_INCLUDES INCLUDES = -I$(top_builddir) -I$(top_srcdir) else INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys endif bin_PROGRAMS = generate generate_SOURCES = generate.c generate_LDADD = $(top_builddir)/libbsm/libbsm.la Index: user/alc/PQ_LAUNDRY/contrib/openbsm/test/bsm/generate.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/test/bsm/generate.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/test/bsm/generate.c (revision 292449) @@ -1,1157 +1,1155 @@ /*- * Copyright (c) 2006-2007 Robert N. M. Watson * Copyright (c) 2008 Apple Inc. * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/test/bsm/generate.c#14 $ */ /* * Generate a series of BSM token samples in the requested directory. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int do_records, do_tokens; static void usage(void) { fprintf(stderr, "generate [-rt] path\n"); exit(EX_USAGE); } static int open_file(const char *directory, const char *name) { char pathname[PATH_MAX]; int fd; snprintf(pathname, PATH_MAX, "%s/%s", directory, name); (void)unlink(pathname); fd = open(pathname, O_WRONLY | O_CREAT | O_EXCL, 0600); if (fd < 0) err(EX_CANTCREAT, "open: %s", name); return (fd); } static void write_file(int fd, void *buffer, size_t buflen, const char *filename) { ssize_t len; len = write(fd, buffer, buflen); if (len < 0) err(EX_OSERR, "write_file: %s", filename); if (len < buflen) err(EX_OSERR, "write_file: short write: %s", filename); } /* * Write a single token to a file. */ static void write_token(const char *directory, const char *filename, token_t *tok) { u_char buffer[MAX_AUDIT_RECORD_SIZE]; size_t buflen; int fd; buflen = MAX_AUDIT_RECORD_SIZE; if (au_close_token(tok, buffer, &buflen) < 0) err(EX_UNAVAILABLE, "au_close_token"); fd = open_file(directory, filename); write_file(fd, buffer, buflen, filename); close(fd); } /* * Write a token to a file, wrapped in audit record header and trailer. */ static void write_record(const char *directory, const char *filename, token_t *tok, short event) { u_char buffer[MAX_AUDIT_RECORD_SIZE]; size_t buflen; int au, fd; au = au_open(); if (au < 0) err(EX_UNAVAILABLE, "au_open"); if (au_write(au, tok) < 0) err(EX_UNAVAILABLE, "au_write"); buflen = MAX_AUDIT_RECORD_SIZE; if (au_close_buffer(au, event, buffer, &buflen) < 0) err(EX_UNAVAILABLE, "au_close_buffer"); fd = open_file(directory, filename); write_file(fd, buffer, buflen, filename); close(fd); } static struct timeval file_token_timeval = { 0x12345, 0x67890} ; static void generate_file_token(const char *directory, const char *token_filename) { token_t *file_token; file_token = au_to_file("test", file_token_timeval); if (file_token == NULL) err(EX_UNAVAILABLE, "au_to_file"); write_token(directory, token_filename, file_token); } static void generate_file_record(const char *directory, const char *record_filename) { token_t *file_token; file_token = au_to_file("test", file_token_timeval); if (file_token == NULL) err(EX_UNAVAILABLE, "au_to_file"); write_record(directory, record_filename, file_token, AUE_NULL); } /* * AUT_OHEADER */ static int trailer_token_len = 0x12345678; static void generate_trailer_token(const char *directory, const char *token_filename) { token_t *trailer_token; trailer_token = au_to_trailer(trailer_token_len); if (trailer_token == NULL) err(EX_UNAVAILABLE, "au_to_trailer"); write_token(directory, token_filename, trailer_token); } static int header32_token_len = 0x12345678; static au_event_t header32_e_type = AUE_OPEN; static au_emod_t header32_e_mod = 0x4567; static struct timeval header32_tm = { 0x12345, 0x67890 }; static void generate_header32_token(const char *directory, const char *token_filename) { token_t *header32_token; header32_token = au_to_header32_tm(header32_token_len, header32_e_type, header32_e_mod, header32_tm); if (header32_token == NULL) err(EX_UNAVAILABLE, "au_to_header32"); write_token(directory, token_filename, header32_token); } /* * AUT_HEADER32_EX */ static char data_token_unit_print = AUP_STRING; static char data_token_unit_type = AUR_CHAR; static char *data_token_data = "SomeData"; static char data_token_unit_count = sizeof("SomeData") + 1; static void generate_data_token(const char *directory, const char *token_filename) { token_t *data_token; data_token = au_to_data(data_token_unit_print, data_token_unit_type, data_token_unit_count, data_token_data); if (data_token == NULL) err(EX_UNAVAILABLE, "au_to_data"); write_token(directory, token_filename, data_token); } static void generate_data_record(const char *directory, const char *record_filename) { token_t *data_token; data_token = au_to_data(data_token_unit_print, data_token_unit_type, data_token_unit_count, data_token_data); if (data_token == NULL) err(EX_UNAVAILABLE, "au_to_data"); write_record(directory, record_filename, data_token, AUE_NULL); } static char ipc_type = AT_IPC_MSG; static int ipc_id = 0x12345678; static void generate_ipc_token(const char *directory, const char *token_filename) { token_t *ipc_token; ipc_token = au_to_ipc(ipc_type, ipc_id); if (ipc_token == NULL) err(EX_UNAVAILABLE, "au_to_ipc"); write_token(directory, token_filename, ipc_token); } static void generate_ipc_record(const char *directory, const char *record_filename) { token_t *ipc_token; ipc_token = au_to_ipc(ipc_type, ipc_id); if (ipc_token == NULL) err(EX_UNAVAILABLE, "au_to_ipc"); write_record(directory, record_filename, ipc_token, AUE_NULL); } static char *path_token_path = "/test/this/is/a/test"; static void generate_path_token(const char *directory, const char *token_filename) { token_t *path_token; path_token = au_to_path(path_token_path); if (path_token == NULL) err(EX_UNAVAILABLE, "au_to_path"); write_token(directory, token_filename, path_token); } static void generate_path_record(const char *directory, const char *record_filename) { token_t *path_token; path_token = au_to_path(path_token_path); if (path_token == NULL) err(EX_UNAVAILABLE, "au_to_path"); write_record(directory, record_filename, path_token, AUE_NULL); } static au_id_t subject32_auid = 0x12345678; static uid_t subject32_euid = 0x01234567; static gid_t subject32_egid = 0x23456789; static uid_t subject32_ruid = 0x98765432; static gid_t subject32_rgid = 0x09876543; static pid_t subject32_pid = 0x13243546; static au_asid_t subject32_sid = 0x97867564; static au_tid_t subject32_tid = { 0x16593746 }; static au_tid_addr_t subject32_tid_addr = { 0x16593746 }; static void generate_subject32_token(const char *directory, const char *token_filename) { token_t *subject32_token; subject32_tid.machine = inet_addr("127.0.0.1"); subject32_token = au_to_subject32(subject32_auid, subject32_euid, subject32_egid, subject32_ruid, subject32_rgid, subject32_pid, subject32_sid, &subject32_tid); if (subject32_token == NULL) err(EX_UNAVAILABLE, "au_to_subject32"); write_token(directory, token_filename, subject32_token); } static void generate_subject32_record(const char *directory, const char *record_filename) { token_t *subject32_token; subject32_tid.machine = inet_addr("127.0.0.1"); subject32_token = au_to_subject32(subject32_auid, subject32_euid, subject32_egid, subject32_ruid, subject32_rgid, subject32_pid, subject32_sid, &subject32_tid); if (subject32_token == NULL) err(EX_UNAVAILABLE, "au_to_subject32"); write_record(directory, record_filename, subject32_token, AUE_NULL); } static void generate_subject32ex_token(const char *directory, const char *token_filename, u_int32_t type) { token_t *subject32ex_token; char *buf; buf = (char *)malloc(strlen(token_filename) + 6); if (type == AU_IPv6) { inet_pton(AF_INET6, "fe80::1", subject32_tid_addr.at_addr); subject32_tid_addr.at_type = AU_IPv6; sprintf(buf, "%s%s", token_filename, "-IPv6"); } else { subject32_tid_addr.at_addr[0] = inet_addr("127.0.0.1"); subject32_tid_addr.at_type = AU_IPv4; sprintf(buf, "%s%s", token_filename, "-IPv4"); } subject32ex_token = au_to_subject32_ex(subject32_auid, subject32_euid, subject32_egid, subject32_ruid, subject32_rgid, subject32_pid, subject32_sid, &subject32_tid_addr); if (subject32ex_token == NULL) err(EX_UNAVAILABLE, "au_to_subject32_ex"); write_token(directory, buf, subject32ex_token); free(buf); } static void generate_subject32ex_record(const char *directory, const char *record_filename, u_int32_t type) { token_t *subject32ex_token; char *buf; buf = (char *)malloc(strlen(record_filename) + 6); if (type == AU_IPv6) { inet_pton(AF_INET6, "fe80::1", subject32_tid_addr.at_addr); subject32_tid_addr.at_type = AU_IPv6; sprintf(buf, "%s%s", record_filename, "-IPv6"); } else { subject32_tid_addr.at_addr[0] = inet_addr("127.0.0.1"); subject32_tid_addr.at_type = AU_IPv4; sprintf(buf, "%s%s", record_filename, "-IPv4"); } subject32ex_token = au_to_subject32_ex(subject32_auid, subject32_euid, subject32_egid, subject32_ruid, subject32_rgid, subject32_pid, subject32_sid, &subject32_tid_addr); if (subject32ex_token == NULL) err(EX_UNAVAILABLE, "au_to_subject32_ex"); write_record(directory, record_filename, subject32ex_token, AUE_NULL); free(buf); } static au_id_t process32_auid = 0x12345678; static uid_t process32_euid = 0x01234567; static gid_t process32_egid = 0x23456789; static uid_t process32_ruid = 0x98765432; static gid_t process32_rgid = 0x09876543; static pid_t process32_pid = 0x13243546; static au_asid_t process32_sid = 0x97867564; static au_tid_t process32_tid = { 0x16593746 }; static au_tid_addr_t process32_tid_addr = { 0x16593746 }; static void generate_process32_token(const char *directory, const char *token_filename) { token_t *process32_token; process32_tid.machine = inet_addr("127.0.0.1"); process32_token = au_to_process32(process32_auid, process32_euid, process32_egid, process32_ruid, process32_rgid, process32_pid, process32_sid, &process32_tid); if (process32_token == NULL) err(EX_UNAVAILABLE, "au_to_process32"); write_token(directory, token_filename, process32_token); } static void generate_process32_record(const char *directory, const char *record_filename) { token_t *process32_token; process32_tid.machine = inet_addr("127.0.0.1"); process32_token = au_to_process32(process32_auid, process32_euid, process32_egid, process32_ruid, process32_rgid, process32_pid, process32_sid, &process32_tid); if (process32_token == NULL) err(EX_UNAVAILABLE, "au_ti_process32"); write_record(directory, record_filename, process32_token, AUE_NULL); } static void generate_process32ex_token(const char *directory, const char *token_filename, u_int32_t type) { token_t *process32ex_token; char *buf; buf = (char *)malloc(strlen(token_filename) + 6); if (type == AU_IPv6) { inet_pton(AF_INET6, "fe80::1", process32_tid_addr.at_addr); process32_tid_addr.at_type = AU_IPv6; sprintf(buf, "%s%s", token_filename, "-IPv6"); } else { process32_tid_addr.at_addr[0] = inet_addr("127.0.0.1"); process32_tid_addr.at_type = AU_IPv4; sprintf(buf, "%s%s", token_filename, "-IPv4"); } process32ex_token = au_to_process32_ex(process32_auid, process32_euid, process32_egid, process32_ruid, process32_rgid, process32_pid, process32_sid, &process32_tid_addr); if (process32ex_token == NULL) err(EX_UNAVAILABLE, "au_to_process32_ex"); write_token(directory, buf, process32ex_token); free(buf); } static void generate_process32ex_record(const char *directory, const char *record_filename, u_int32_t type) { token_t *process32ex_token; char *buf; buf = (char *)malloc(strlen(record_filename) + 6); if (type == AU_IPv6) { inet_pton(AF_INET6, "fe80::1", process32_tid_addr.at_addr); process32_tid_addr.at_type = AU_IPv6; sprintf(buf, "%s%s", record_filename, "-IPv6"); } else { process32_tid_addr.at_addr[0] = inet_addr("127.0.0.1"); process32_tid_addr.at_type = AU_IPv4; sprintf(buf, "%s%s", record_filename, "-IPv4"); } process32ex_token = au_to_process32_ex(process32_auid, process32_euid, process32_egid, process32_ruid, process32_rgid, process32_pid, process32_sid, &process32_tid_addr); if (process32ex_token == NULL) err(EX_UNAVAILABLE, "au_to_process32_ex"); write_record(directory, buf, process32ex_token, AUE_NULL); free(buf); } static au_id_t process64_auid = 0x12345678; static uid_t process64_euid = 0x01234567; static gid_t process64_egid = 0x23456789; static uid_t process64_ruid = 0x98765432; static gid_t process64_rgid = 0x09876543; static pid_t process64_pid = 0x13243546; static au_asid_t process64_sid = 0x97867564; static au_tid_t process64_tid = { 0x16593746 }; static au_tid_addr_t process64_tid_addr = { 0x16593746 }; static void generate_process64_token(const char *directory, const char *token_filename) { token_t *process64_token; process64_tid.machine = inet_addr("127.0.0.1"); process64_token = au_to_process64(process64_auid, process64_euid, process64_egid, process64_ruid, process64_rgid, process64_pid, process64_sid, &process64_tid); if (process64_token == NULL) err(EX_UNAVAILABLE, "au_to_process64"); write_token(directory, token_filename, process64_token); } static void generate_process64_record(const char *directory, const char *record_filename) { token_t *process64_token; process64_tid.machine = inet_addr("127.0.0.1"); process64_token = au_to_process64(process64_auid, process64_euid, process64_egid, process64_ruid, process64_rgid, process64_pid, process64_sid, &process64_tid); if (process64_token == NULL) err(EX_UNAVAILABLE, "au_ti_process64"); write_record(directory, record_filename, process64_token, AUE_NULL); } static void generate_process64ex_token(const char *directory, const char *token_filename, u_int32_t type) { token_t *process64ex_token; char *buf; buf = (char *)malloc(strlen(token_filename) + 6); if (type == AU_IPv6) { inet_pton(AF_INET6, "fe80::1", process64_tid_addr.at_addr); process64_tid_addr.at_type = AU_IPv6; sprintf(buf, "%s%s", token_filename, "-IPv6"); } else { process64_tid_addr.at_addr[0] = inet_addr("127.0.0.1"); process64_tid_addr.at_type = AU_IPv4; sprintf(buf, "%s%s", token_filename, "-IPv4"); } process64ex_token = au_to_process64_ex(process64_auid, process64_euid, process64_egid, process64_ruid, process64_rgid, process64_pid, process64_sid, &process64_tid_addr); if (process64ex_token == NULL) err(EX_UNAVAILABLE, "au_to_process64_ex"); write_token(directory, buf, process64ex_token); free(buf); } static void generate_process64ex_record(const char *directory, const char *record_filename, u_int32_t type) { token_t *process64ex_token; char *buf; buf = (char *)malloc(strlen(record_filename) + 6); if (type == AU_IPv6) { inet_pton(AF_INET6, "fe80::1", process64_tid_addr.at_addr); process64_tid_addr.at_type = AU_IPv6; sprintf(buf, "%s%s", record_filename, "-IPv6"); } else { process64_tid_addr.at_addr[0] = inet_addr("127.0.0.1"); process64_tid_addr.at_type = AU_IPv4; sprintf(buf, "%s%s", record_filename, "-IPv4"); } process64ex_token = au_to_process64_ex(process64_auid, process64_euid, process64_egid, process64_ruid, process64_rgid, process64_pid, process64_sid, &process64_tid_addr); if (process64ex_token == NULL) err(EX_UNAVAILABLE, "au_to_process64_ex"); write_record(directory, buf, process64ex_token, AUE_NULL); free(buf); } static char return32_status = EINVAL; static uint32_t return32_ret = 0x12345678; static void generate_return32_token(const char *directory, const char *token_filename) { token_t *return32_token; return32_token = au_to_return32(au_errno_to_bsm(return32_status), return32_ret); if (return32_token == NULL) err(EX_UNAVAILABLE, "au_to_return32"); write_token(directory, token_filename, return32_token); } static void generate_return32_record(const char *directory, const char *record_filename) { token_t *return32_token; return32_token = au_to_return32(au_errno_to_bsm(return32_status), return32_ret); if (return32_token == NULL) err(EX_UNAVAILABLE, "au_to_return32"); write_record(directory, record_filename, return32_token, AUE_NULL); } static char *text_token_text = "This is a test."; static void generate_text_token(const char *directory, const char *token_filename) { token_t *text_token; text_token = au_to_text(text_token_text); if (text_token == NULL) err(EX_UNAVAILABLE, "au_to_text"); write_token(directory, token_filename, text_token); } static void generate_text_record(const char *directory, const char *record_filename) { token_t *text_token; text_token = au_to_text(text_token_text); if (text_token == NULL) err(EX_UNAVAILABLE, "au_to_text"); write_record(directory, record_filename, text_token, AUE_NULL); } static char opaque_token_data[] = {0xaa, 0xbb, 0xcc, 0xdd}; static int opaque_token_bytes = sizeof(opaque_token_data); static void generate_opaque_token(const char *directory, const char *token_filename) { token_t *opaque_token; opaque_token = au_to_opaque(opaque_token_data, opaque_token_bytes); if (opaque_token == NULL) err(EX_UNAVAILABLE, "au_to_opaque"); write_token(directory, token_filename, opaque_token); } static void generate_opaque_record(const char *directory, const char *record_filename) { token_t *opaque_token; opaque_token = au_to_opaque(opaque_token_data, opaque_token_bytes); if (opaque_token == NULL) err(EX_UNAVAILABLE, "au_to_opaque"); write_record(directory, record_filename, opaque_token, AUE_NULL); } static struct in_addr in_addr_token_addr; static void generate_in_addr_token(const char *directory, const char *token_filename) { token_t *in_addr_token; in_addr_token_addr.s_addr = inet_addr("192.168.100.15"); in_addr_token = au_to_in_addr(&in_addr_token_addr); if (in_addr_token == NULL) err(EX_UNAVAILABLE, "au_to_in_addr"); write_token(directory, token_filename, in_addr_token); } static void generate_in_addr_record(const char *directory, const char *record_filename) { token_t *in_addr_token; in_addr_token_addr.s_addr = inet_addr("192.168.100.15"); in_addr_token = au_to_in_addr(&in_addr_token_addr); if (in_addr_token == NULL) err(EX_UNAVAILABLE, "au_to_in_addr"); write_record(directory, record_filename, in_addr_token, AUE_NULL); } static struct ip ip_token_ip; static u_char ip_token_ip_v = 4; static uint16_t ip_token_ip_id = 0x5478; static u_char ip_token_ip_ttl = 64; static u_char ip_token_ip_p = IPPROTO_ICMP; static struct in_addr ip_token_ip_src; static struct in_addr ip_token_ip_dst; static void generate_ip_token(const char *directory, const char *token_filename) { token_t *ip_token; ip_token_ip_src.s_addr = inet_addr("192.168.100.155"); ip_token_ip_dst.s_addr = inet_addr("192.168.110.48"); memset(&ip_token_ip, 0, sizeof(ip_token_ip)); ip_token_ip.ip_v = ip_token_ip_v; ip_token_ip.ip_len = htons(sizeof(ip_token_ip)); ip_token_ip.ip_id = htons(ip_token_ip_id); ip_token_ip.ip_ttl = ip_token_ip_ttl; ip_token_ip.ip_p = ip_token_ip_p; ip_token_ip.ip_src = ip_token_ip_src; ip_token_ip.ip_dst = ip_token_ip_dst; ip_token = au_to_ip(&ip_token_ip); if (ip_token == NULL) err(EX_UNAVAILABLE, "au_to_ip"); write_token(directory, token_filename, ip_token); } static void generate_ip_record(const char *directory, const char *record_filename) { token_t *ip_token; ip_token_ip_src.s_addr = inet_addr("192.168.100.155"); ip_token_ip_dst.s_addr = inet_addr("192.168.110.48"); memset(&ip_token_ip, 0, sizeof(ip_token_ip)); ip_token_ip.ip_v = ip_token_ip_v; ip_token_ip.ip_len = htons(sizeof(ip_token_ip)); ip_token_ip.ip_id = htons(ip_token_ip_id); ip_token_ip.ip_ttl = ip_token_ip_ttl; ip_token_ip.ip_p = ip_token_ip_p; ip_token_ip.ip_src = ip_token_ip_src; ip_token_ip.ip_dst = ip_token_ip_dst; ip_token = au_to_ip(&ip_token_ip); if (ip_token == NULL) err(EX_UNAVAILABLE, "au_to_ip"); write_record(directory, record_filename, ip_token, AUE_NULL); } static u_int16_t iport_token_iport; static void generate_iport_token(const char *directory, const char *token_filename) { token_t *iport_token; iport_token_iport = htons(80); iport_token = au_to_iport(iport_token_iport); if (iport_token == NULL) err(EX_UNAVAILABLE, "au_to_iport"); write_token(directory, token_filename, iport_token); } static void generate_iport_record(const char *directory, const char *record_filename) { token_t *iport_token; iport_token_iport = htons(80); iport_token = au_to_iport(iport_token_iport); if (iport_token == NULL) err(EX_UNAVAILABLE, "au_to_iport"); write_record(directory, record_filename, iport_token, AUE_NULL); } static char arg32_token_n = 3; static char *arg32_token_text = "test_arg32_token"; static uint32_t arg32_token_v = 0xabcdef00; static void generate_arg32_token(const char *directory, const char *token_filename) { token_t *arg32_token; arg32_token = au_to_arg32(arg32_token_n, arg32_token_text, arg32_token_v); if (arg32_token == NULL) err(EX_UNAVAILABLE, "au_to_arg32"); write_token(directory, token_filename, arg32_token); } static void generate_arg32_record(const char *directory, const char *record_filename) { token_t *arg32_token; arg32_token = au_to_arg32(arg32_token_n, arg32_token_text, arg32_token_v); if (arg32_token == NULL) err(EX_UNAVAILABLE, "au_to_arg32"); write_record(directory, record_filename, arg32_token, AUE_NULL); } static long seq_audit_count = 0x12345678; static void generate_seq_token(const char *directory, const char *token_filename) { token_t *seq_token; seq_token = au_to_seq(seq_audit_count); if (seq_token == NULL) err(EX_UNAVAILABLE, "au_to_seq"); write_token(directory, token_filename, seq_token); } static void generate_seq_record(const char *directory, const char *record_filename) { token_t *seq_token; seq_token = au_to_seq(seq_audit_count); if (seq_token == NULL) err(EX_UNAVAILABLE, "au_to_seq"); write_record(directory, record_filename, seq_token, AUE_NULL); } #if 0 /* * AUT_ACL */ static void generate_attr_token(const char *directory, const char *token_filename) { token_t *attr_token; } static void generate_attr_record(const char *directory, const char *record_filename) { token_t *attr_token; } static void generate_ipc_perm_token(const char *directory, const char *token_filename) { token_t *ipc_perm_token; } static void generate_ipc_perm_record(const char *directory, const char *record_filename) { token_t *ipc_perm_token; } #endif #if 0 /* * AUT_LABEL */ static void generate_groups_token(const char *directory, const char *token_filename) { token_t *groups_token; } static void generate_groups_record(const char *directory, const char *record_filename) { token_t *groups_token; } #endif /* * AUT_ILABEL */ /* * AUT_SLABEL */ /* * AUT_CLEAR */ /* * AUT_PRIV */ /* * AUT_UPRIV */ /* * AUT_LIAISON */ /* * AUT_NEWGROUPS */ /* * AUT_EXEC_ARGS */ /* * AUT_EXEC_ENV */ #if 0 static void generate_attr32_token(const char *directory, const char *token_filename) { token_t *attr32_token; } static void generate_attr32_record(const char *directory, const char *record_filename) { token_t *attr32_token; } #endif static char *zonename_sample = "testzone"; static void generate_zonename_token(const char *directory, const char *token_filename) { token_t *zonename_token; zonename_token = au_to_zonename(zonename_sample); if (zonename_token == NULL) err(EX_UNAVAILABLE, "au_to_zonename"); write_token(directory, token_filename, zonename_token); } static void generate_zonename_record(const char *directory, const char *record_filename) { token_t *zonename_token; zonename_token = au_to_zonename(zonename_sample); if (zonename_token == NULL) err(EX_UNAVAILABLE, "au_to_zonename"); write_record(directory, record_filename, zonename_token, AUE_NULL); } static u_short socketex_domain = PF_INET; static u_short socketex_type = SOCK_STREAM; static struct sockaddr_in socketex_laddr, socketex_raddr; static void generate_socketex_token(const char *directory, const char *token_filename) { token_t *socketex_token; bzero(&socketex_laddr, sizeof(socketex_laddr)); socketex_laddr.sin_family = AF_INET; socketex_laddr.sin_len = sizeof(socketex_laddr); socketex_laddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); bzero(&socketex_raddr, sizeof(socketex_raddr)); socketex_raddr.sin_family = AF_INET; socketex_raddr.sin_len = sizeof(socketex_raddr); socketex_raddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); socketex_token = au_to_socket_ex(au_domain_to_bsm(socketex_domain), au_socket_type_to_bsm(socketex_type), (struct sockaddr *)&socketex_laddr, (struct sockaddr *)&socketex_raddr); if (socketex_token == NULL) err(EX_UNAVAILABLE, "au_to_socket_ex"); write_token(directory, token_filename, socketex_token); } static void generate_socketex_record(const char *directory, const char *record_filename) { token_t *socketex_token; bzero(&socketex_laddr, sizeof(socketex_laddr)); socketex_laddr.sin_family = AF_INET; socketex_laddr.sin_len = sizeof(socketex_laddr); socketex_laddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); bzero(&socketex_raddr, sizeof(socketex_raddr)); socketex_raddr.sin_family = AF_INET; socketex_raddr.sin_len = sizeof(socketex_raddr); socketex_raddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); socketex_token = au_to_socket_ex(au_domain_to_bsm(socketex_domain), au_socket_type_to_bsm(socketex_type), (struct sockaddr *)&socketex_laddr, (struct sockaddr *)&socketex_raddr); if (socketex_token == NULL) err(EX_UNAVAILABLE, "au_to_socket_ex"); write_record(directory, record_filename, socketex_token, AUE_NULL); } /* * Generate a series of error-number specific return tokens in records. */ static void generate_error_record(const char *directory, const char *filename, int error) { char pathname[PATH_MAX]; token_t *return32_token; return32_token = au_to_return32(au_errno_to_bsm(error), -1); if (return32_token == NULL) err(EX_UNAVAILABLE, "au_to_return32"); (void)snprintf(pathname, PATH_MAX, "%s_record", filename); write_record(directory, pathname, return32_token, AUE_NULL); } /* * Not all the error numbers, just a few present on all platforms for now. */ const struct { int error_number; const char *error_name; } error_list[] = { { EPERM, "EPERM" }, { ENOENT, "ENOENT" }, { ESRCH, "ESRCH" }, { EINTR, "EINTR" }, { EIO, "EIO" }, { ENXIO, "ENXIO" }, { E2BIG, "E2BIG" }, { ENOEXEC, "ENOEXEC" }, { EBADF, "EBADF" }, { ECHILD, "ECHILD" }, { EDEADLK, "EDEADLK" }, { ENOMEM, "ENOMEM" }, { EACCES, "EACCES" }, { EFAULT, "EFAULT" }, { ENOTBLK, "ENOTBLK" }, { EBUSY, "EBUSY" }, { EEXIST, "EEXIST" }, { EXDEV, "EXDEV" }, { ENODEV, "ENODEV" }, { ENOTDIR, "ENOTDIR" }, { EISDIR, "EISDIR" }, { EINVAL, "EINVAL" }, { ENFILE, "ENFILE" }, { EMFILE, "EMFILE" }, { ENOTTY, "ENOTTY" }, { ETXTBSY, "ETXTBSY" }, { EFBIG, "EFBIG" }, { ENOSPC, "ENOSPC" }, { ESPIPE, "ESPIPE" }, { EROFS, "EROFS" }, { EMLINK, "EMLINK" }, { EPIPE, "EPIPE" } }; const int error_list_count = sizeof(error_list)/sizeof(error_list[0]); static void do_error_records(const char *directory) { int i; for (i = 0; i < error_list_count; i++) generate_error_record(directory, error_list[i].error_name, error_list[i].error_number); } int main(int argc, char *argv[]) { const char *directory; int ch; while ((ch = getopt(argc, argv, "rt")) != -1) { switch (ch) { case 'r': do_records++; break; case 't': do_tokens++; break; default: usage(); } } argc -= optind; argv += optind; if (argc != 1) usage(); directory = argv[0]; if (mkdir(directory, 0755) < 0 && errno != EEXIST) err(EX_OSERR, "mkdir: %s", directory); if (do_tokens) { generate_file_token(directory, "file_token"); generate_trailer_token(directory, "trailer_token"); generate_header32_token(directory, "header32_token"); generate_data_token(directory, "data_token"); generate_ipc_token(directory, "ipc_token"); generate_path_token(directory, "path_token"); generate_subject32_token(directory, "subject32_token"); generate_subject32ex_token(directory, "subject32ex_token", AU_IPv4); generate_subject32ex_token(directory, "subject32ex_token", AU_IPv6); generate_process32_token(directory, "process32_token"); generate_process32ex_token(directory, "process32ex_token", AU_IPv4); generate_process32ex_token(directory, "process32ex_token", AU_IPv6); generate_process64_token(directory, "process64_token"); generate_process64ex_token(directory, "process64ex_token", AU_IPv4); generate_process64ex_token(directory, "process64ex_token", AU_IPv6); generate_return32_token(directory, "return32_token"); generate_text_token(directory, "text_token"); generate_opaque_token(directory, "opaque_token"); generate_in_addr_token(directory, "in_addr_token"); generate_ip_token(directory, "ip_token"); generate_iport_token(directory, "iport_token"); generate_arg32_token(directory, "arg32_token"); generate_seq_token(directory, "seq_token"); #if 0 generate_attr_token(directory, "attr_token"); generate_ipc_perm_token(directory, "ipc_perm_token"); generate_groups_token(directory, "groups_token"); generate_attr32_token(directory, "attr32_token"); #endif generate_zonename_token(directory, "zonename_token"); generate_socketex_token(directory, "socketex_token"); } if (do_records) { generate_file_record(directory, "file_record"); generate_data_record(directory, "data_record"); generate_ipc_record(directory, "ipc_record"); generate_path_record(directory, "path_record"); generate_subject32_record(directory, "subject32_record"); generate_subject32ex_record(directory, "subject32ex_record", AU_IPv4); generate_subject32ex_record(directory, "subject32ex_record", AU_IPv6); generate_process32_record(directory, "process32_record"); generate_process32ex_record(directory, "process32ex_record", AU_IPv4); generate_process32ex_record(directory, "process32ex_record", AU_IPv6); generate_process64_record(directory, "process64_record"); generate_process64ex_record(directory, "process64ex_record", AU_IPv4); generate_process64ex_record(directory, "process64ex_record", AU_IPv6); generate_return32_record(directory, "return32_record"); generate_text_record(directory, "text_record"); generate_opaque_record(directory, "opaque_record"); generate_in_addr_record(directory, "in_addr_record"); generate_ip_record(directory, "ip_record"); generate_iport_record(directory, "iport_record"); generate_arg32_record(directory, "arg32_record"); generate_seq_record(directory, "seq_record"); #if 0 generate_attr_record(directory, "attr_record"); generate_ipc_perm_record(directory, "ipc_perm_record"); generate_groups_record(directory, "groups_record"); generate_attr32_record(directory, "attr32_record"); #endif generate_zonename_record(directory, "zonename_record"); generate_socketex_record(directory, "socketex_record"); do_error_records(directory); } return (0); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm/tools/Makefile.am =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/tools/Makefile.am (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/tools/Makefile.am (revision 292449) @@ -1,13 +1,9 @@ -## -## $P4: //depot/projects/trustedbsd/openbsm/tools/Makefile.am#5 $ -## - if USE_NATIVE_INCLUDES INCLUDES = -I$(top_builddir) -I$(top_srcdir) else INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/sys endif bin_PROGRAMS = audump audump_SOURCES = audump.c audump_LDADD = $(top_builddir)/libbsm/libbsm.la Index: user/alc/PQ_LAUNDRY/contrib/openbsm/tools/audump.c =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm/tools/audump.c (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm/tools/audump.c (revision 292449) @@ -1,272 +1,270 @@ /*- * Copyright (c) 2005-2009 Robert N. M. Watson * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $P4: //depot/projects/trustedbsd/openbsm/tools/audump.c#9 $ */ #include #include #include #include #include #include /* * Simple tool to dump various /etc/security databases using the defined APIs. */ static void usage(void) { fprintf(stderr, "usage: audump [class|class_r|control|event|event_r|" "user|user_r]\n"); exit(-1); } static void audump_class(void) { au_class_ent_t *cp; while ((cp = getauclassent()) != NULL) printf("0x%08x:%s:%s\n", cp->ac_class, cp->ac_name, cp->ac_desc); } static void audump_class_r(void) { char class_ent_name[AU_CLASS_NAME_MAX]; char class_ent_desc[AU_CLASS_DESC_MAX]; au_class_ent_t c, *cp; bzero(&c, sizeof(c)); bzero(class_ent_name, sizeof(class_ent_name)); bzero(class_ent_desc, sizeof(class_ent_desc)); c.ac_name = class_ent_name; c.ac_desc = class_ent_desc; while ((cp = getauclassent_r(&c)) != NULL) printf("0x%08x:%s:%s\n", cp->ac_class, cp->ac_name, cp->ac_desc); } static void audump_control(void) { char string[PATH_MAX], string2[PATH_MAX]; int ret, val; long policy; time_t age; size_t size; ret = getacflg(string, PATH_MAX); if (ret == -2) err(-1, "getacflg"); if (ret != 0) errx(-1, "getacflg: %d", ret); printf("flags:%s\n", string); ret = getacmin(&val); if (ret == -2) err(-1, "getacmin"); if (ret != 0) errx(-1, "getacmin: %d", ret); printf("min:%d\n", val); ret = getacna(string, PATH_MAX); if (ret == -2) err(-1, "getacna"); if (ret != 0) errx(-1, "getacna: %d", ret); printf("naflags:%s\n", string); setac(); do { ret = getacdir(string, PATH_MAX); if (ret == -1) break; if (ret == -2) err(-1, "getacdir"); if (ret != 0) errx(-1, "getacdir: %d", ret); printf("dir:%s\n", string); } while (ret == 0); ret = getacpol(string, PATH_MAX); if (ret != 0) err(-1, "getacpol"); if (au_strtopol(string, &policy) < 0) err(-1, "au_strtopol"); if (au_poltostr(policy, PATH_MAX, string2) < 0) err(-1, "au_poltostr"); printf("policy:%s\n", string2); ret = getacfilesz(&size); if (ret == -2) err(-1, "getacfilesz"); if (ret != 0) err(-1, "getacfilesz: %d", ret); printf("filesz:%ldB\n", size); ret = getachost(string, PATH_MAX); if (ret == -2) err(-1, "getachost"); if (ret == -3) err(-1, "getachost: %d", ret); if (ret == 0 && ret != 1) printf("host:%s\n", string); ret = getacexpire(&val, &age, &size); if (ret == -2) err(-1, "getacexpire"); if (ret == -1) err(-1, "getacexpire: %d", ret); if (ret == 0 && ret != 1) printf("expire-after:%ldB %s %lds\n", size, val ? "AND" : "OR", age); } static void printf_classmask(au_class_t classmask) { au_class_ent_t *c; u_int32_t i; int first; first = 1; for (i = 0; i < 32; i++) { if (classmask & (1 << i)) { if (first) first = 0; else printf(","); c = getauclassnum(1 << i); if (c != NULL) printf("%s", c->ac_name); else printf("0x%x", 1 << i); } } } static void audump_event(void) { au_event_ent_t *ep; while ((ep = getauevent()) != NULL) { printf("%d:%s:%s:", ep->ae_number, ep->ae_name, ep->ae_desc); printf_classmask(ep->ae_class); printf("\n"); } } static void audump_event_r(void) { char event_ent_name[AU_EVENT_NAME_MAX]; char event_ent_desc[AU_EVENT_DESC_MAX]; au_event_ent_t e, *ep; bzero(&e, sizeof(e)); bzero(event_ent_name, sizeof(event_ent_name)); bzero(event_ent_desc, sizeof(event_ent_desc)); e.ae_name = event_ent_name; e.ae_desc = event_ent_desc; while ((ep = getauevent_r(&e)) != NULL) { printf("%d:%s:%s:", ep->ae_number, ep->ae_name, ep->ae_desc); printf_classmask(ep->ae_class); printf("\n"); } } static void audump_user(void) { au_user_ent_t *up; while ((up = getauuserent()) != NULL) { printf("%s:", up->au_name); // printf_classmask(up->au_always); printf(":"); // printf_classmask(up->au_never); printf("\n"); } } static void audump_user_r(void) { char user_ent_name[AU_USER_NAME_MAX]; au_user_ent_t u, *up; bzero(&u, sizeof(u)); bzero(user_ent_name, sizeof(user_ent_name)); u.au_name = user_ent_name; while ((up = getauuserent_r(&u)) != NULL) { printf("%s:", up->au_name); // printf_classmask(up->au_always); printf(":"); // printf_classmask(up->au_never); printf("\n"); } } int main(int argc, char *argv[]) { if (argc != 2) usage(); if (strcmp(argv[1], "class") == 0) audump_class(); else if (strcmp(argv[1], "class_r") == 0) audump_class_r(); else if (strcmp(argv[1], "control") == 0) audump_control(); else if (strcmp(argv[1], "event") == 0) audump_event(); else if (strcmp(argv[1], "event_r") == 0) audump_event_r(); else if (strcmp(argv[1], "user") == 0) audump_user(); else if (strcmp(argv[1], "user_r") == 0) audump_user_r(); else usage(); return (0); } Index: user/alc/PQ_LAUNDRY/contrib/openbsm =================================================================== --- user/alc/PQ_LAUNDRY/contrib/openbsm (revision 292448) +++ user/alc/PQ_LAUNDRY/contrib/openbsm (revision 292449) Property changes on: user/alc/PQ_LAUNDRY/contrib/openbsm ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,2 ## Merged /vendor/openbsm/dist:r292016 Merged /head/contrib/openbsm:r289108-292448 Index: user/alc/PQ_LAUNDRY/crypto/openssh/digest-libc.c =================================================================== --- user/alc/PQ_LAUNDRY/crypto/openssh/digest-libc.c (revision 292448) +++ user/alc/PQ_LAUNDRY/crypto/openssh/digest-libc.c (revision 292449) @@ -1,238 +1,238 @@ /* $OpenBSD: digest-libc.c,v 1.2 2014/02/02 03:44:31 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller * Copyright (c) 2014 Markus Friedl. All rights reserved. * * 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. */ #include "includes.h" #include #include #include #include #include #include #include #include #include "buffer.h" #include "digest.h" typedef void md_init_fn(void *mdctx); typedef void md_update_fn(void *mdctx, const u_int8_t *m, size_t mlen); typedef void md_final_fn(u_int8_t[], void *mdctx); struct ssh_digest_ctx { int alg; void *mdctx; }; struct ssh_digest { int id; const char *name; size_t block_len; size_t digest_len; size_t ctx_len; md_init_fn *md_init; md_update_fn *md_update; md_final_fn *md_final; }; /* NB. Indexed directly by algorithm number */ const struct ssh_digest digests[SSH_DIGEST_MAX] = { { SSH_DIGEST_MD5, "MD5", MD5_BLOCK_LENGTH, MD5_DIGEST_LENGTH, sizeof(MD5_CTX), (md_init_fn *) MD5Init, (md_update_fn *) MD5Update, (md_final_fn *) MD5Final }, { SSH_DIGEST_RIPEMD160, "RIPEMD160", RMD160_BLOCK_LENGTH, RMD160_DIGEST_LENGTH, sizeof(RMD160_CTX), (md_init_fn *) RMD160Init, (md_update_fn *) RMD160Update, (md_final_fn *) RMD160Final }, { SSH_DIGEST_SHA1, "SHA1", SHA1_BLOCK_LENGTH, SHA1_DIGEST_LENGTH, sizeof(SHA1_CTX), (md_init_fn *) SHA1Init, (md_update_fn *) SHA1Update, (md_final_fn *) SHA1Final }, { SSH_DIGEST_SHA256, "SHA256", SHA256_BLOCK_LENGTH, SHA256_DIGEST_LENGTH, sizeof(SHA2_CTX), (md_init_fn *) SHA256Init, (md_update_fn *) SHA256Update, (md_final_fn *) SHA256Final }, { SSH_DIGEST_SHA384, "SHA384", SHA384_BLOCK_LENGTH, SHA384_DIGEST_LENGTH, sizeof(SHA2_CTX), (md_init_fn *) SHA384Init, (md_update_fn *) SHA384Update, (md_final_fn *) SHA384Final }, { SSH_DIGEST_SHA512, "SHA512", SHA512_BLOCK_LENGTH, SHA512_DIGEST_LENGTH, sizeof(SHA2_CTX), (md_init_fn *) SHA512Init, (md_update_fn *) SHA512Update, (md_final_fn *) SHA512Final } }; static const struct ssh_digest * ssh_digest_by_alg(int alg) { if (alg < 0 || alg >= SSH_DIGEST_MAX) return NULL; if (digests[alg].id != alg) /* sanity */ return NULL; return &(digests[alg]); } size_t ssh_digest_bytes(int alg) { const struct ssh_digest *digest = ssh_digest_by_alg(alg); return digest == NULL ? 0 : digest->digest_len; } size_t ssh_digest_blocksize(struct ssh_digest_ctx *ctx) { const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg); return digest == NULL ? 0 : digest->block_len; } struct ssh_digest_ctx * ssh_digest_start(int alg) { const struct ssh_digest *digest = ssh_digest_by_alg(alg); struct ssh_digest_ctx *ret; - if (digest == NULL || (ret = calloc(1, sizeof(ret))) == NULL) + if (digest == NULL || (ret = calloc(1, sizeof(*ret))) == NULL) return NULL; if ((ret->mdctx = calloc(1, digest->ctx_len)) == NULL) { free(ret); return NULL; } ret->alg = alg; digest->md_init(ret->mdctx); return ret; } int ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to) { const struct ssh_digest *digest = ssh_digest_by_alg(from->alg); if (digest == NULL || from->alg != to->alg) return -1; memcpy(to->mdctx, from->mdctx, digest->ctx_len); return 0; } int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) { const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg); if (digest == NULL) return -1; digest->md_update(ctx->mdctx, m, mlen); return 0; } int ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const Buffer *b) { return ssh_digest_update(ctx, buffer_ptr(b), buffer_len(b)); } int ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen) { const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg); if (digest == NULL) return -1; if (dlen > UINT_MAX) return -1; if (dlen < digest->digest_len) /* No truncation allowed */ return -1; digest->md_final(d, ctx->mdctx); return 0; } void ssh_digest_free(struct ssh_digest_ctx *ctx) { const struct ssh_digest *digest; if (ctx != NULL) { digest = ssh_digest_by_alg(ctx->alg); if (digest) { explicit_bzero(ctx->mdctx, digest->ctx_len); free(ctx->mdctx); explicit_bzero(ctx, sizeof(*ctx)); free(ctx); } } } int ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen) { struct ssh_digest_ctx *ctx = ssh_digest_start(alg); if (ctx == NULL) return -1; if (ssh_digest_update(ctx, m, mlen) != 0 || ssh_digest_final(ctx, d, dlen) != 0) return -1; ssh_digest_free(ctx); return 0; } int ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen) { return ssh_digest_memory(alg, buffer_ptr(b), buffer_len(b), d, dlen); } Index: user/alc/PQ_LAUNDRY/crypto/openssh =================================================================== --- user/alc/PQ_LAUNDRY/crypto/openssh (revision 292448) +++ user/alc/PQ_LAUNDRY/crypto/openssh (revision 292449) Property changes on: user/alc/PQ_LAUNDRY/crypto/openssh ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/crypto/openssh:r291968-292448 Index: user/alc/PQ_LAUNDRY/include/netdb.h =================================================================== --- user/alc/PQ_LAUNDRY/include/netdb.h (revision 292448) +++ user/alc/PQ_LAUNDRY/include/netdb.h (revision 292449) @@ -1,293 +1,293 @@ /*- * Copyright (c) 1980, 1983, 1988, 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. 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. * * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * 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, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION 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. * - * --Copyright-- */ /* * @(#)netdb.h 8.1 (Berkeley) 6/2/93 * From: Id: netdb.h,v 8.9 1996/11/19 08:39:29 vixie Exp $ * $FreeBSD$ */ #ifndef _NETDB_H_ #define _NETDB_H_ #include #include #ifndef _SIZE_T_DECLARED typedef __size_t size_t; #define _SIZE_T_DECLARED #endif #ifndef _SOCKLEN_T_DECLARED typedef __socklen_t socklen_t; #define _SOCKLEN_T_DECLARED #endif #ifndef _UINT32_T_DECLARED typedef __uint32_t uint32_t; #define _UINT32_T_DECLARED #endif #ifndef _PATH_HEQUIV # define _PATH_HEQUIV "/etc/hosts.equiv" #endif #define _PATH_HOSTS "/etc/hosts" #define _PATH_NETWORKS "/etc/networks" #define _PATH_PROTOCOLS "/etc/protocols" #define _PATH_SERVICES "/etc/services" #define _PATH_SERVICES_DB "/var/db/services.db" #define h_errno (*__h_errno()) /* * Structures returned by network data base library. All addresses are * supplied in host order, and returned in network order (suitable for * use in system calls). */ struct hostent { char *h_name; /* official name of host */ char **h_aliases; /* alias list */ int h_addrtype; /* host address type */ int h_length; /* length of address */ char **h_addr_list; /* list of addresses from name server */ #define h_addr h_addr_list[0] /* address, for backward compatibility */ }; struct netent { char *n_name; /* official name of net */ char **n_aliases; /* alias list */ int n_addrtype; /* net address type */ uint32_t n_net; /* network # */ }; struct servent { char *s_name; /* official service name */ char **s_aliases; /* alias list */ int s_port; /* port # */ char *s_proto; /* protocol to use */ }; struct protoent { char *p_name; /* official protocol name */ char **p_aliases; /* alias list */ int p_proto; /* protocol # */ }; struct addrinfo { int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */ int ai_family; /* PF_xxx */ int ai_socktype; /* SOCK_xxx */ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ socklen_t ai_addrlen; /* length of ai_addr */ char *ai_canonname; /* canonical name for hostname */ struct sockaddr *ai_addr; /* binary address */ struct addrinfo *ai_next; /* next structure in linked list */ }; /* * Error return codes from gethostbyname() and gethostbyaddr() * (left in h_errno). */ #define NETDB_INTERNAL -1 /* see errno */ #define NETDB_SUCCESS 0 /* no problem */ #define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ #define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL */ #define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ #define NO_DATA 4 /* Valid name, no data record of requested type */ #define NO_ADDRESS NO_DATA /* no address, look for MX record */ /* * Error return codes from getaddrinfo() */ #if 0 /* obsoleted */ #define EAI_ADDRFAMILY 1 /* address family for hostname not supported */ #endif #define EAI_AGAIN 2 /* temporary failure in name resolution */ #define EAI_BADFLAGS 3 /* invalid value for ai_flags */ #define EAI_FAIL 4 /* non-recoverable failure in name resolution */ #define EAI_FAMILY 5 /* ai_family not supported */ #define EAI_MEMORY 6 /* memory allocation failure */ #if 0 /* obsoleted */ #define EAI_NODATA 7 /* no address associated with hostname */ #endif #define EAI_NONAME 8 /* hostname nor servname provided, or not known */ #define EAI_SERVICE 9 /* servname not supported for ai_socktype */ #define EAI_SOCKTYPE 10 /* ai_socktype not supported */ #define EAI_SYSTEM 11 /* system error returned in errno */ #define EAI_BADHINTS 12 /* invalid value for hints */ #define EAI_PROTOCOL 13 /* resolved protocol is unknown */ #define EAI_OVERFLOW 14 /* argument buffer overflow */ #define EAI_MAX 15 /* * Flag values for getaddrinfo() */ #define AI_PASSIVE 0x00000001 /* get address to use bind() */ #define AI_CANONNAME 0x00000002 /* fill ai_canonname */ #define AI_NUMERICHOST 0x00000004 /* prevent host name resolution */ #define AI_NUMERICSERV 0x00000008 /* prevent service name resolution */ /* valid flags for addrinfo (not a standard def, apps should not use it) */ #define AI_MASK \ (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | \ - AI_ADDRCONFIG) + AI_ADDRCONFIG | AI_ALL | AI_V4MAPPED) #define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */ #define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */ #define AI_ADDRCONFIG 0x00000400 /* only if any address is assigned */ #define AI_V4MAPPED 0x00000800 /* accept IPv4-mapped IPv6 address */ /* special recommended flags for getipnodebyname */ #define AI_DEFAULT (AI_V4MAPPED_CFG | AI_ADDRCONFIG) /* * Constants for getnameinfo() */ #define NI_MAXHOST 1025 #define NI_MAXSERV 32 /* * Flag values for getnameinfo() */ #define NI_NOFQDN 0x00000001 #define NI_NUMERICHOST 0x00000002 #define NI_NAMEREQD 0x00000004 #define NI_NUMERICSERV 0x00000008 #define NI_DGRAM 0x00000010 #if 0 /* obsolete */ #define NI_WITHSCOPEID 0x00000020 #endif /* * Scope delimit character */ #define SCOPE_DELIMITER '%' __BEGIN_DECLS void endhostent(void); void endnetent(void); void endprotoent(void); void endservent(void); #if __BSD_VISIBLE || (__POSIX_VISIBLE && __POSIX_VISIBLE <= 200112) struct hostent *gethostbyaddr(const void *, socklen_t, int); struct hostent *gethostbyname(const char *); #endif struct hostent *gethostent(void); struct netent *getnetbyaddr(uint32_t, int); struct netent *getnetbyname(const char *); struct netent *getnetent(void); struct protoent *getprotobyname(const char *); struct protoent *getprotobynumber(int); struct protoent *getprotoent(void); struct servent *getservbyname(const char *, const char *); struct servent *getservbyport(int, const char *); struct servent *getservent(void); void sethostent(int); /* void sethostfile(const char *); */ void setnetent(int); void setprotoent(int); int getaddrinfo(const char *, const char *, const struct addrinfo *, struct addrinfo **); int getnameinfo(const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, int); void freeaddrinfo(struct addrinfo *); const char *gai_strerror(int); void setservent(int); #if __BSD_VISIBLE void endnetgrent(void); void freehostent(struct hostent *); int gethostbyaddr_r(const void *, socklen_t, int, struct hostent *, char *, size_t, struct hostent **, int *); int gethostbyname_r(const char *, struct hostent *, char *, size_t, struct hostent **, int *); struct hostent *gethostbyname2(const char *, int); int gethostbyname2_r(const char *, int, struct hostent *, char *, size_t, struct hostent **, int *); int gethostent_r(struct hostent *, char *, size_t, struct hostent **, int *); struct hostent *getipnodebyaddr(const void *, size_t, int, int *); struct hostent *getipnodebyname(const char *, int, int, int *); int getnetbyaddr_r(uint32_t, int, struct netent *, char *, size_t, struct netent**, int *); int getnetbyname_r(const char *, struct netent *, char *, size_t, struct netent **, int *); int getnetent_r(struct netent *, char *, size_t, struct netent **, int *); int getnetgrent(char **, char **, char **); int getprotobyname_r(const char *, struct protoent *, char *, size_t, struct protoent **); int getprotobynumber_r(int, struct protoent *, char *, size_t, struct protoent **); int getprotoent_r(struct protoent *, char *, size_t, struct protoent **); int getservbyname_r(const char *, const char *, struct servent *, char *, size_t, struct servent **); int getservbyport_r(int, const char *, struct servent *, char *, size_t, struct servent **); int getservent_r(struct servent *, char *, size_t, struct servent **); void herror(const char *); const char *hstrerror(int); int innetgr(const char *, const char *, const char *, const char *); void setnetgrent(const char *); #endif /* * PRIVATE functions specific to the FreeBSD implementation */ /* DO NOT USE THESE, THEY ARE SUBJECT TO CHANGE AND ARE NOT PORTABLE!!! */ int * __h_errno(void); __END_DECLS #endif /* !_NETDB_H_ */ Index: user/alc/PQ_LAUNDRY/include =================================================================== --- user/alc/PQ_LAUNDRY/include (revision 292448) +++ user/alc/PQ_LAUNDRY/include (revision 292449) Property changes on: user/alc/PQ_LAUNDRY/include ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/include:r292390-292448 Index: user/alc/PQ_LAUNDRY/lib/libbsm/Makefile =================================================================== --- user/alc/PQ_LAUNDRY/lib/libbsm/Makefile (revision 292448) +++ user/alc/PQ_LAUNDRY/lib/libbsm/Makefile (revision 292449) @@ -1,177 +1,181 @@ # # $FreeBSD$ # OPENBSMDIR= ${.CURDIR}/../../contrib/openbsm _LIBBSMDIR= ${OPENBSMDIR}/libbsm LIB= bsm SHLIB_MAJOR= 3 .PATH: ${_LIBBSMDIR} .PATH: ${OPENBSMDIR}/bsm .PATH: ${OPENBSMDIR}/man SRCS= bsm_audit.c \ bsm_class.c \ bsm_control.c \ bsm_domain.c \ bsm_errno.c \ bsm_event.c \ bsm_fcntl.c \ bsm_flags.c \ bsm_io.c \ bsm_mask.c \ bsm_notify.c \ bsm_socket_type.c \ bsm_token.c \ bsm_user.c \ bsm_wrappers.c # # Must use BSM include files from within the contrib area, not the system. # CFLAGS+= -I${OPENBSMDIR} -I${_LIBBSMDIR} WARNS?= 1 INCS= audit_uevents.h libbsm.h INCSDIR= ${INCLUDEDIR}/bsm MAN= libbsm.3 \ au_class.3 \ au_control.3 \ au_domain.3 \ au_errno.3 \ au_event.3 \ au_fcntl_cmd.3 \ au_free_token.3 \ au_io.3 \ au_mask.3 \ + au_notify.3 \ au_open.3 \ au_socket_type.3 \ au_token.3 \ au_user.3 \ audit_submit.3 # # It seems like maybe some of these should be installed separately, since # they're not all libbsm parts. # MAN+= audit.2 \ audit.log.5 \ audit_class.5 \ audit_control.5 \ audit_event.5 \ audit_user.5 \ audit_warn.5 \ auditctl.2 \ auditon.2 \ getaudit.2 \ getauid.2 \ setaudit.2 \ setauid.2 MLINKS= libbsm.3 bsm.3 \ au_class.3 getauclassent.3 \ au_class.3 getauclassent_r.3 \ au_class.3 getauclassnam.3 \ au_class.3 getauclassnam_3.3 \ au_class.3 setauclass.3 \ au_class.3 endauclass.3 \ au_control.3 setac.3 \ au_control.3 endac.3 \ au_control.3 getacdir.3 \ au_control.3 getacmin.3 \ au_control.3 getacfilesz.3 \ au_control.3 getacflg.3 \ au_control.3 getacna.3 \ au_control.3 getacpol.3 \ au_control.3 au_poltostr.3 \ au_control.3 au_strtopol.3 \ au_domain.3 au_bsm_to_domain.3 \ au_domain.3 au_domain_to_bsm.3 \ au_errno.3 au_bsm_to_errno.3 \ au_errno.3 au_errno_to_bsm.3 \ au_errno.3 au_strerror.3 \ au_event.3 setauevent.3 \ au_event.3 endauevent.3 \ au_event.3 getauevent.3 \ au_event.3 getauevent_r.3 \ au_event.3 getauevnam.3 \ au_event.3 getauevnam_r.3 \ au_event.3 getauevnum.3 \ au_event.3 getauevnum_r.3 \ au_event.3 getauevnonam.3 \ au_event.3 getauevnonam_r.3 \ au_fcntl_cmd.3 au_bsm_to_fcntl_cmd.3 \ au_fcntl_cmd.3 au_fcntl_cmd_t_bsm.3 \ au_io.3 au_fetch_tok.3 \ au_io.3 au_print_tok.3 \ au_io.3 au_read_rec.3 \ au_mask.3 au_preselect.3 \ au_mask.3 getauditflagsbin.3 \ au_mask.3 getauditflagschar.3 \ + au_notify.3 au_get_state.3 \ + au_notify.3 au_notify_initialize.3 \ + au_notify.3 au_notify_terminate.3 \ au_open.3 au_close.3 \ au_open.3 au_close_buffer.3 \ au_open.3 au_close_token.3 \ au_open.3 au_write.3 \ au_socket_type.3 au_bsm_to_socket_type.3 \ au_socket_type.3 au_socket_type_to_bsm.3 \ au_token.3 au_to_arg32.3 \ au_token.3 au_to_arg64.3 \ au_token.3 au_to_arg.3 \ au_token.3 au_to_attr64.3 \ au_token.3 au_to_data.3 \ au_token.3 au_to_exit.3 \ au_token.3 au_to_groups.3 \ au_token.3 au_to_newgroups.3 \ au_token.3 au_to_in_addr.3 \ au_token.3 au_to_in_addr_ex.3 \ au_token.3 au_to_ip.3 \ au_token.3 au_to_ipc.3 \ au_token.3 au_to_ipc_perm.3 \ au_token.3 au_to_iport.3 \ au_token.3 au_to_opaque.3 \ au_token.3 au_to_file.3 \ au_token.3 au_to_text.3 \ au_token.3 au_to_path.3 \ au_token.3 au_to_process32.3 \ au_token.3 au_to_process64.3 \ au_token.3 au_to_process.3 \ au_token.3 au_to_process32_ex.3 \ au_token.3 au_to_process64_ex.3 \ au_token.3 au_to_process_ex.3 \ au_token.3 au_to_return32.3 \ au_token.3 au_to_return64.3 \ au_token.3 au_to_return.3 \ au_token.3 au_to_seq.3 \ au_token.3 au_to_sock_inet32.3 \ au_token.3 au_to_sock_inet128.3 \ au_token.3 au_to_sock_inet.3 \ au_token.3 au_to_subject32.3 \ au_token.3 au_to_subject64.3 \ au_token.3 au_to_subject.3 \ au_token.3 au_to_subject32_ex.3 \ au_token.3 au_to_subject64_ex.3 \ au_token.3 au_to_subject_ex.3 \ au_token.3 au_to_me.3 \ au_token.3 au_to_exec_args.3 \ au_token.3 au_to_exec_env.3 \ au_token.3 au_to_header.3 \ au_token.3 au_to_header32.3 \ au_token.3 au_to_header64.3 \ au_token.3 au_to_trailer.3 \ au_token.3 au_to_zonename.3 \ au_user.3 setauuser.3 \ au_user.3 endauuser.3 \ au_user.3 getauuserent.3 \ au_user.3 getauuserent_r.3 \ au_user.3 getauusernam.3 \ au_user.3 getauusernam_R.3 \ au_user.3 au_user_mask.3 \ au_user.3 getfauditflags.3 \ getaudit.2 getaudit_addr.2 \ setaudit.2 setaudit_addr.2 .include Index: user/alc/PQ_LAUNDRY/lib/libc/net/getaddrinfo.3 =================================================================== --- user/alc/PQ_LAUNDRY/lib/libc/net/getaddrinfo.3 (revision 292448) +++ user/alc/PQ_LAUNDRY/lib/libc/net/getaddrinfo.3 (revision 292449) @@ -1,469 +1,509 @@ .\" $KAME: getaddrinfo.3,v 1.36 2005/01/05 03:23:05 itojun Exp $ .\" $OpenBSD: getaddrinfo.3,v 1.35 2004/12/21 03:40:31 jaredy Exp $ .\" .\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") .\" Copyright (C) 2000, 2001 Internet Software Consortium. .\" .\" 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 ISC DISCLAIMS ALL WARRANTIES WITH .\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY .\" AND FITNESS. IN NO EVENT SHALL ISC 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. .\" .\" $FreeBSD$ .\" -.Dd October 5, 2015 +.Dd December 19, 2015 .Dt GETADDRINFO 3 .Os .Sh NAME .Nm getaddrinfo , .Nm freeaddrinfo .Nd socket address structure to host and service name .Sh SYNOPSIS .In sys/types.h .In sys/socket.h .In netdb.h .Ft int .Fo getaddrinfo .Fa "const char *hostname" "const char *servname" .Fa "const struct addrinfo *hints" "struct addrinfo **res" .Fc .Ft void .Fn freeaddrinfo "struct addrinfo *ai" .Sh DESCRIPTION The .Fn getaddrinfo function is used to get a list of addresses and port numbers for host .Fa hostname and service .Fa servname . It is a replacement for and provides more flexibility than the .Xr gethostbyname 3 and .Xr getservbyname 3 functions. .Pp The .Fa hostname and .Fa servname arguments are either pointers to NUL-terminated strings or the null pointer. An acceptable value for .Fa hostname is either a valid host name or a numeric host address string consisting of a dotted decimal IPv4 address, an IPv6 address, or a UNIX-domain address. The .Fa servname is either a decimal port number or a service name listed in .Xr services 5 . At least one of .Fa hostname and .Fa servname must be non-null. .Pp .Fa hints is an optional pointer to a .Li struct addrinfo , as defined by .Aq Pa netdb.h : .Bd -literal struct addrinfo { int ai_flags; /* input flags */ int ai_family; /* protocol family for socket */ int ai_socktype; /* socket type */ int ai_protocol; /* protocol for socket */ socklen_t ai_addrlen; /* length of socket-address */ struct sockaddr *ai_addr; /* socket-address for socket */ char *ai_canonname; /* canonical name for service location */ struct addrinfo *ai_next; /* pointer to next in list */ }; .Ed .Pp This structure can be used to provide hints concerning the type of socket that the caller supports or wishes to use. The caller can supply the following structure elements in .Fa hints : .Bl -tag -width "ai_socktypeXX" .It Fa ai_family The protocol family that should be used. When .Fa ai_family is set to .Dv PF_UNSPEC , it means the caller will accept any protocol family supported by the operating system. .It Fa ai_socktype Denotes the type of socket that is wanted: .Dv SOCK_STREAM , .Dv SOCK_DGRAM , .Dv SOCK_SEQPACKET , or .Dv SOCK_RAW . When .Fa ai_socktype is zero the caller will accept any socket type. .It Fa ai_protocol Indicates which transport protocol is desired, .Dv IPPROTO_UDP , .Dv IPPROTO_TCP , .Dv IPPROTO_SCTP , or .Dv IPPROTO_UDPLITE . If .Fa ai_protocol is zero the caller will accept any protocol. .It Fa ai_flags The .Fa ai_flags field to which the .Fa hints parameter points shall be set to zero or be the bitwise-inclusive OR of one or more of the values .Dv AI_ADDRCONFIG , +.Dv AI_ALL , .Dv AI_CANONNAME , .Dv AI_NUMERICHOST , -.Dv AI_NUMERICSERV +.Dv AI_NUMERICSERV , +.Dv AI_PASSIVE and -.Dv AI_PASSIVE . +.Dv AI_V4MAPPED . For a UNIX-domain address, .Fa ai_flags is ignored. .Bl -tag -width "AI_CANONNAMEXX" .It Dv AI_ADDRCONFIG If the .Dv AI_ADDRCONFIG bit is set, IPv4 addresses shall be returned only if an IPv4 address is configured on the local system, and IPv6 addresses shall be returned only if an IPv6 address is configured on the local system. +.It Dv AI_ALL +If the +.Dv AI_ALL +flag is used with the +.Dv AI_V4MAPPED +flag, then +.Fn getaddrinfo +shall return all matching IPv6 and IPv4 addresses. +.Pp +For example, when using the DNS, queries are made for both AAAA records and A records, and +.Fn getaddrinfo +returns the combined results of both queries. +Any IPv4 addresses found are returned as IPv4-mapped IPv6 addresses. +.Pp +The +.Dv AI_ALL +flag without the +.Dv AI_V4MAPPED +flag is ignored. .It Dv AI_CANONNAME If the .Dv AI_CANONNAME bit is set, a successful call to .Fn getaddrinfo will return a NUL-terminated string containing the canonical name of the specified hostname in the .Fa ai_canonname element of the first .Li addrinfo structure returned. .It Dv AI_NUMERICHOST If the .Dv AI_NUMERICHOST bit is set, it indicates that .Fa hostname should be treated as a numeric string defining an IPv4 or IPv6 address and no name resolution should be attempted. .It Dv AI_NUMERICSERV If the .Dv AI_NUMERICSERV bit is set, then a non-null .Fa servname string supplied shall be a numeric port string. Otherwise, an .Dv EAI_NONAME error shall be returned. This bit shall prevent any type of name resolution service (for example, NIS+) from being invoked. .It Dv AI_PASSIVE If the .Dv AI_PASSIVE bit is set it indicates that the returned socket address structure is intended for use in a call to .Xr bind 2 . In this case, if the .Fa hostname argument is the null pointer, then the IP address portion of the socket address structure will be set to .Dv INADDR_ANY for an IPv4 address or .Dv IN6ADDR_ANY_INIT for an IPv6 address. .Pp If the .Dv AI_PASSIVE bit is not set, the returned socket address structure will be ready for use in a call to .Xr connect 2 for a connection-oriented protocol or .Xr connect 2 , .Xr sendto 2 , or .Xr sendmsg 2 if a connectionless protocol was chosen. The .Tn IP address portion of the socket address structure will be set to the loopback address if .Fa hostname is the null pointer and .Dv AI_PASSIVE is not set. +.It Dv AI_V4MAPPED +If the +.Dv AI_V4MAPPED +flag is specified along with an ai_family of +.Dv AF_INET6 , +then +.Fn getaddrinfo +shall return IPv4-mapped IPv6 addresses on finding no matching IPv6 addresses ( +.Fa ai_addrlen +shall be 16). +.Pp +For example, when using the DNS, if no AAAA records are found then a query is made for A records and any found are returned as IPv4-mapped IPv6 addresses. +.Pp +The +.Dv AI_V4MAPPED +flag shall be ignored unless +.Fa ai_family +equals +.Dv AF_INET6 . .El .El .Pp All other elements of the .Li addrinfo structure passed via .Fa hints must be zero or the null pointer. .Pp If .Fa hints is the null pointer, .Fn getaddrinfo behaves as if the caller provided a .Li struct addrinfo with .Fa ai_family set to .Dv PF_UNSPEC and all other elements set to zero or .Dv NULL . .Pp After a successful call to .Fn getaddrinfo , .Fa *res is a pointer to a linked list of one or more .Li addrinfo structures. The list can be traversed by following the .Fa ai_next pointer in each .Li addrinfo structure until a null pointer is encountered. Each returned .Li addrinfo structure contains three members that are suitable for a call to .Xr socket 2 : .Fa ai_family , .Fa ai_socktype , and .Fa ai_protocol . For each .Li addrinfo structure in the list, the .Fa ai_addr member points to a filled-in socket address structure of length .Fa ai_addrlen . .Pp This implementation of .Fn getaddrinfo allows numeric IPv6 address notation with scope identifier, as documented in chapter 11 of RFC 4007. By appending the percent character and scope identifier to addresses, one can fill the .Li sin6_scope_id field for addresses. This would make management of scoped addresses easier and allows cut-and-paste input of scoped addresses. .Pp At this moment the code supports only link-local addresses with the format. The scope identifier is hardcoded to the name of the hardware interface associated with the link .Po such as .Li ne0 .Pc . An example is .Dq Li fe80::1%ne0 , which means .Do .Li fe80::1 on the link associated with the .Li ne0 interface .Dc . .Pp The current implementation assumes a one-to-one relationship between the interface and link, which is not necessarily true from the specification. .Pp All of the information returned by .Fn getaddrinfo is dynamically allocated: the .Li addrinfo structures themselves as well as the socket address structures and the canonical host name strings included in the .Li addrinfo structures. .Pp Memory allocated for the dynamically allocated structures created by a successful call to .Fn getaddrinfo is released by the .Fn freeaddrinfo function. The .Fa ai pointer should be a .Li addrinfo structure created by a call to .Fn getaddrinfo . .Sh RETURN VALUES .Fn getaddrinfo returns zero on success or one of the error codes listed in .Xr gai_strerror 3 if an error occurs. .Sh EXAMPLES The following code tries to connect to .Dq Li www.kame.net service .Dq Li http via a stream socket. It loops through all the addresses available, regardless of address family. If the destination resolves to an IPv4 address, it will use an .Dv AF_INET socket. Similarly, if it resolves to IPv6, an .Dv AF_INET6 socket is used. Observe that there is no hardcoded reference to a particular address family. The code works even if .Fn getaddrinfo returns addresses that are not IPv4/v6. .Bd -literal -offset indent struct addrinfo hints, *res, *res0; int error; int s; const char *cause = NULL; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo("www.kame.net", "http", &hints, &res0); if (error) { errx(1, "%s", gai_strerror(error)); /* NOTREACHED */ } s = -1; for (res = res0; res; res = res->ai_next) { s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s < 0) { cause = "socket"; continue; } if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { cause = "connect"; close(s); s = -1; continue; } break; /* okay we got one */ } if (s < 0) { err(1, "%s", cause); /* NOTREACHED */ } freeaddrinfo(res0); .Ed .Pp The following example tries to open a wildcard listening socket onto service .Dq Li http , for all the address families available. .Bd -literal -offset indent struct addrinfo hints, *res, *res0; int error; int s[MAXSOCK]; int nsock; const char *cause = NULL; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; error = getaddrinfo(NULL, "http", &hints, &res0); if (error) { errx(1, "%s", gai_strerror(error)); /* NOTREACHED */ } nsock = 0; for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) { s[nsock] = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s[nsock] < 0) { cause = "socket"; continue; } if (bind(s[nsock], res->ai_addr, res->ai_addrlen) < 0) { cause = "bind"; close(s[nsock]); continue; } (void) listen(s[nsock], 5); nsock++; } if (nsock == 0) { err(1, "%s", cause); /* NOTREACHED */ } freeaddrinfo(res0); .Ed .Sh SEE ALSO .Xr bind 2 , .Xr connect 2 , .Xr send 2 , .Xr socket 2 , .Xr gai_strerror 3 , .Xr gethostbyname 3 , .Xr getnameinfo 3 , .Xr getservbyname 3 , .Xr resolver 3 , .Xr inet 4 , .Xr inet6 4 , .Xr unix 4 , .Xr hosts 5 , .Xr resolv.conf 5 , .Xr services 5 , .Xr hostname 7 , .Xr named 8 .Rs .%A R. Gilligan .%A S. Thomson .%A J. Bound .%A J. McCann .%A W. Stevens .%T Basic Socket Interface Extensions for IPv6 .%R RFC 3493 .%D February 2003 .Re .Rs .%A S. Deering .%A B. Haberman .%A T. Jinmei .%A E. Nordmark .%A B. Zill .%T "IPv6 Scoped Address Architecture" .%R RFC 4007 .%D March 2005 .Re .Rs .%A Craig Metz .%T Protocol Independence Using the Sockets API .%B "Proceedings of the freenix track: 2000 USENIX annual technical conference" .%D June 2000 .Re .Sh STANDARDS The .Fn getaddrinfo function is defined by the .St -p1003.1-2004 specification and documented in .Dv "RFC 3493" , .Dq Basic Socket Interface Extensions for IPv6 . Index: user/alc/PQ_LAUNDRY/lib/libc/net/getaddrinfo.c =================================================================== --- user/alc/PQ_LAUNDRY/lib/libc/net/getaddrinfo.c (revision 292448) +++ user/alc/PQ_LAUNDRY/lib/libc/net/getaddrinfo.c (revision 292449) @@ -1,2907 +1,3012 @@ /* $KAME: getaddrinfo.c,v 1.15 2000/07/09 04:37:24 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. */ /* * Issues to be discussed: * - Return values. There are nonstandard return values defined and used * in the source code. This is because RFC2553 is silent about which error * code must be returned for which situation. * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is * invalid. current code - SEGV on freeaddrinfo(NULL) * * Note: * - The code filters out AFs that are not supported by the kernel, * when globbing NULL hostname (to loopback, or wildcard). Is it the right * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG * in ai_flags? * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague. * (1) what should we do against numeric hostname (2) what should we do * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready? * non-loopback address configured? global address configured? * * OS specific notes for freebsd4: * - FreeBSD supported $GAI. The code does not. */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #include #include #include #include #ifdef INET6 #include #include #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "res_config.h" #ifdef DEBUG #include #endif #include #include #include "un-namespace.h" +#include "netdb_private.h" #include "libc_private.h" #ifdef NS_CACHING #include "nscache.h" #endif #define ANY 0 #define YES 1 #define NO 0 static const char in_addrany[] = { 0, 0, 0, 0 }; static const char in_loopback[] = { 127, 0, 0, 1 }; #ifdef INET6 static const char in6_addrany[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const char in6_loopback[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; #endif struct policyqueue { TAILQ_ENTRY(policyqueue) pc_entry; #ifdef INET6 struct in6_addrpolicy pc_policy; #endif }; TAILQ_HEAD(policyhead, policyqueue); static const struct afd { int a_af; int a_addrlen; socklen_t a_socklen; int a_off; const char *a_addrany; const char *a_loopback; int a_scoped; } afdl [] = { #ifdef INET6 #define N_INET6 0 {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6), offsetof(struct sockaddr_in6, sin6_addr), in6_addrany, in6_loopback, 1}, #define N_INET 1 #define N_LOCAL 2 #else #define N_INET 0 #define N_LOCAL 1 #endif {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in), offsetof(struct sockaddr_in, sin_addr), in_addrany, in_loopback, 0}, #define sizeofmember(type, member) (sizeof(((type *)0)->member)) {PF_LOCAL, sizeofmember(struct sockaddr_un, sun_path), sizeof(struct sockaddr_un), offsetof(struct sockaddr_un, sun_path), NULL, NULL, 0}, {0, 0, 0, 0, NULL, NULL, 0}, }; struct explore { int e_af; int e_socktype; int e_protocol; int e_wild; #define AF_ANY 0x01 #define SOCKTYPE_ANY 0x02 #define PROTOCOL_ANY 0x04 #define WILD_AF(ex) ((ex)->e_wild & AF_ANY) #define WILD_SOCKTYPE(ex) ((ex)->e_wild & SOCKTYPE_ANY) #define WILD_PROTOCOL(ex) ((ex)->e_wild & PROTOCOL_ANY) }; static const struct explore explore[] = { #ifdef INET6 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY }, { PF_INET6, SOCK_STREAM, IPPROTO_TCP, AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY }, { PF_INET6, SOCK_STREAM, IPPROTO_SCTP, AF_ANY | SOCKTYPE_ANY }, { PF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY }, { PF_INET6, SOCK_DGRAM, IPPROTO_UDPLITE, AF_ANY | SOCKTYPE_ANY }, { PF_INET6, SOCK_RAW, ANY, AF_ANY | PROTOCOL_ANY }, #endif { PF_INET, SOCK_DGRAM, IPPROTO_UDP, AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY }, { PF_INET, SOCK_STREAM, IPPROTO_TCP, AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY }, { PF_INET, SOCK_STREAM, IPPROTO_SCTP, AF_ANY | SOCKTYPE_ANY }, { PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY }, { PF_INET, SOCK_DGRAM, IPPROTO_UDPLITE, AF_ANY | SOCKTYPE_ANY }, { PF_INET, SOCK_RAW, ANY, AF_ANY | PROTOCOL_ANY }, { PF_LOCAL, SOCK_DGRAM, ANY, AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY }, { PF_LOCAL, SOCK_STREAM, ANY, AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY }, { PF_LOCAL, SOCK_SEQPACKET, ANY, AF_ANY | SOCKTYPE_ANY | PROTOCOL_ANY }, { -1, 0, 0, 0 }, }; #ifdef INET6 #define PTON_MAX 16 #else #define PTON_MAX 4 #endif #define AIO_SRCFLAG_DEPRECATED 0x1 struct ai_order { union { struct sockaddr_storage aiou_ss; struct sockaddr aiou_sa; } aio_src_un; #define aio_srcsa aio_src_un.aiou_sa u_int32_t aio_srcflag; int aio_srcscope; int aio_dstscope; struct policyqueue *aio_srcpolicy; struct policyqueue *aio_dstpolicy; struct addrinfo *aio_ai; int aio_matchlen; }; static const ns_src default_dns_files[] = { { NSSRC_FILES, NS_SUCCESS }, { NSSRC_DNS, NS_SUCCESS }, { 0 } }; struct res_target { struct res_target *next; const char *name; /* domain name */ int qclass, qtype; /* class and type of query */ u_char *answer; /* buffer to put answer */ int anslen; /* size of answer buffer */ int n; /* result length */ }; #define MAXPACKET (64*1024) typedef union { HEADER hdr; u_char buf[MAXPACKET]; } querybuf; static int str2number(const char *, int *); static int explore_copy(const struct addrinfo *, const struct addrinfo *, struct addrinfo **); static int explore_null(const struct addrinfo *, const char *, struct addrinfo **); static int explore_numeric(const struct addrinfo *, const char *, const char *, struct addrinfo **, const char *); static int explore_numeric_scope(const struct addrinfo *, const char *, const char *, struct addrinfo **); static int get_canonname(const struct addrinfo *, struct addrinfo *, const char *); static struct addrinfo *get_ai(const struct addrinfo *, const struct afd *, const char *); static struct addrinfo *copy_ai(const struct addrinfo *); static int get_portmatch(const struct addrinfo *, const char *); static int get_port(struct addrinfo *, const char *, int); static const struct afd *find_afd(int); static int addrconfig(struct addrinfo *); #ifdef INET6 static int is_ifdisabled(char *); #endif static void set_source(struct ai_order *, struct policyhead *); static int comp_dst(const void *, const void *); #ifdef INET6 static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *); #endif static int gai_addr2scopetype(struct sockaddr *); static int explore_fqdn(const struct addrinfo *, const char *, const char *, struct addrinfo **); static int reorder(struct addrinfo *); static int get_addrselectpolicy(struct policyhead *); static void free_addrselectpolicy(struct policyhead *); static struct policyqueue *match_addrselectpolicy(struct sockaddr *, struct policyhead *); static int matchlen(struct sockaddr *, struct sockaddr *); static struct addrinfo *getanswer(const querybuf *, int, const char *, int, const struct addrinfo *, res_state); #if defined(RESOLVSORT) static int addr4sort(struct addrinfo *, res_state); #endif static int _dns_getaddrinfo(void *, void *, va_list); static void _sethtent(FILE **); static void _endhtent(FILE **); static struct addrinfo *_gethtent(FILE **, const char *, const struct addrinfo *); static int _files_getaddrinfo(void *, void *, va_list); #ifdef YP static struct addrinfo *_yphostent(char *, const struct addrinfo *); static int _yp_getaddrinfo(void *, void *, va_list); #endif #ifdef NS_CACHING static int addrinfo_id_func(char *, size_t *, va_list, void *); static int addrinfo_marshal_func(char *, size_t *, void *, va_list, void *); static int addrinfo_unmarshal_func(char *, size_t, void *, va_list, void *); #endif static int res_queryN(const char *, struct res_target *, res_state); static int res_searchN(const char *, struct res_target *, res_state); static int res_querydomainN(const char *, const char *, struct res_target *, res_state); /* XXX macros that make external reference is BAD. */ #define GET_AI(ai, afd, addr) \ do { \ /* external reference: pai, error, and label free */ \ (ai) = get_ai(pai, (afd), (addr)); \ if ((ai) == NULL) { \ error = EAI_MEMORY; \ goto free; \ } \ } while (/*CONSTCOND*/0) #define GET_PORT(ai, serv) \ do { \ /* external reference: error and label free */ \ error = get_port((ai), (serv), 0); \ if (error != 0) \ goto free; \ } while (/*CONSTCOND*/0) #define GET_CANONNAME(ai, str) \ do { \ /* external reference: pai, error and label free */ \ error = get_canonname(pai, (ai), (str)); \ if (error != 0) \ goto free; \ } while (/*CONSTCOND*/0) #define ERR(err) \ do { \ /* external reference: error, and label bad */ \ error = (err); \ goto bad; \ /*NOTREACHED*/ \ } while (/*CONSTCOND*/0) #define MATCH_FAMILY(x, y, w) \ ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC))) #define MATCH(x, y, w) \ ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY))) void freeaddrinfo(struct addrinfo *ai) { struct addrinfo *next; do { next = ai->ai_next; if (ai->ai_canonname) free(ai->ai_canonname); /* no need to free(ai->ai_addr) */ free(ai); ai = next; } while (ai); } static int str2number(const char *p, int *portp) { char *ep; unsigned long v; if (*p == '\0') return -1; ep = NULL; errno = 0; v = strtoul(p, &ep, 10); if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX) { *portp = v; return 0; } else return -1; } int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res) { struct addrinfo sentinel; struct addrinfo *cur; int error = 0; struct addrinfo ai, ai0, *afai; struct addrinfo *pai; const struct afd *afd; const struct explore *ex; struct addrinfo *afailist[sizeof(afdl)/sizeof(afdl[0])]; struct addrinfo *afai_unspec; int found; int numeric = 0; /* ensure we return NULL on errors */ *res = NULL; memset(&ai, 0, sizeof(ai)); memset(afailist, 0, sizeof(afailist)); afai_unspec = NULL; memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; pai = &ai; pai->ai_flags = 0; pai->ai_family = PF_UNSPEC; pai->ai_socktype = ANY; pai->ai_protocol = ANY; pai->ai_addrlen = 0; pai->ai_canonname = NULL; pai->ai_addr = NULL; pai->ai_next = NULL; if (hostname == NULL && servname == NULL) return EAI_NONAME; if (hints) { /* error check for hints */ if (hints->ai_addrlen || hints->ai_canonname || hints->ai_addr || hints->ai_next) ERR(EAI_BADHINTS); /* xxx */ if (hints->ai_flags & ~AI_MASK) ERR(EAI_BADFLAGS); switch (hints->ai_family) { case PF_UNSPEC: case PF_LOCAL: case PF_INET: #ifdef INET6 case PF_INET6: #endif break; default: ERR(EAI_FAMILY); } memcpy(pai, hints, sizeof(*pai)); /* * if both socktype/protocol are specified, check if they * are meaningful combination. */ if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { for (ex = explore; ex->e_af >= 0; ex++) { if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) continue; if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) continue; if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) continue; /* matched */ break; } if (ex->e_af < 0) ERR(EAI_BADHINTS); } } /* + * RFC 3493: AI_ALL and AI_V4MAPPED are effective only against + * AF_INET6 query. They need to be ignored if specified in other + * occassions. + */ + switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) { + case AI_V4MAPPED: + case AI_ALL | AI_V4MAPPED: +#ifdef INET6 + if (pai->ai_family != AF_INET6) + pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); + break; +#endif + case AI_ALL: + pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); + break; + } + + /* * check for special cases. (1) numeric servname is disallowed if * socktype/protocol are left unspecified. (2) servname is disallowed * for raw and other inet{,6} sockets. */ if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) #ifdef PF_INET6 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) #endif ) { ai0 = *pai; /* backup *pai */ if (pai->ai_family == PF_UNSPEC) { #ifdef PF_INET6 pai->ai_family = PF_INET6; #else pai->ai_family = PF_INET; #endif } error = get_portmatch(pai, servname); if (error) goto bad; *pai = ai0; } ai0 = *pai; /* * NULL hostname, or numeric hostname. * If numeric representation of AF1 can be interpreted as FQDN * representation of AF2, we need to think again about the code below. */ found = 0; for (afd = afdl; afd->a_af; afd++) { *pai = ai0; if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1)) continue; if (pai->ai_family == PF_UNSPEC) pai->ai_family = afd->a_af; if (hostname == NULL) { error = explore_null(pai, servname, &afailist[afd - afdl]); /* * Errors from explore_null should be unexpected and * be caught to avoid returning an incomplete result. */ if (error != 0) goto bad; } else { error = explore_numeric_scope(pai, hostname, servname, &afailist[afd - afdl]); /* * explore_numeric_scope returns an error for address * families that do not match that of hostname. * Thus we should not catch the error at this moment. */ } if (!error && afailist[afd - afdl]) found++; } if (found) { numeric = 1; goto globcopy; } if (hostname == NULL) ERR(EAI_NONAME); /* used to be EAI_NODATA */ if (pai->ai_flags & AI_NUMERICHOST) ERR(EAI_NONAME); if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(&ai0)) ERR(EAI_FAIL); /* * hostname as alphabetical name. */ *pai = ai0; error = explore_fqdn(pai, hostname, servname, &afai_unspec); globcopy: for (ex = explore; ex->e_af >= 0; ex++) { *pai = ai0; if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) continue; if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) continue; if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) continue; if (pai->ai_family == PF_UNSPEC) pai->ai_family = ex->e_af; if (pai->ai_socktype == ANY && ex->e_socktype != ANY) pai->ai_socktype = ex->e_socktype; if (pai->ai_protocol == ANY && ex->e_protocol != ANY) pai->ai_protocol = ex->e_protocol; /* * if the servname does not match socktype/protocol, ignore it. */ if (get_portmatch(pai, servname) != 0) continue; if (afai_unspec) afai = afai_unspec; else { if ((afd = find_afd(pai->ai_family)) == NULL) continue; /* XXX assumes that afd points inside afdl[] */ afai = afailist[afd - afdl]; } if (!afai) continue; error = explore_copy(pai, afai, &cur->ai_next); if (error != 0) goto bad; while (cur && cur->ai_next) cur = cur->ai_next; } /* * ensure we return either: * - error == 0, non-NULL *res * - error != 0, NULL *res */ if (error == 0) { if (sentinel.ai_next) { /* * If the returned entry is for an active connection, * and the given name is not numeric, reorder the * list, so that the application would try the list * in the most efficient order. Since the head entry * of the original list may contain ai_canonname and * that entry may be moved elsewhere in the new list, * we keep the pointer and will restore it in the new * head entry. (Note that RFC3493 requires the head * entry store it when requested by the caller). */ if (hints == NULL || !(hints->ai_flags & AI_PASSIVE)) { if (!numeric) { char *canonname; canonname = sentinel.ai_next->ai_canonname; sentinel.ai_next->ai_canonname = NULL; (void)reorder(&sentinel); if (sentinel.ai_next->ai_canonname == NULL) { sentinel.ai_next->ai_canonname = canonname; } else if (canonname != NULL) free(canonname); } } *res = sentinel.ai_next; } else error = EAI_FAIL; } bad: if (afai_unspec) freeaddrinfo(afai_unspec); for (afd = afdl; afd->a_af; afd++) { if (afailist[afd - afdl]) freeaddrinfo(afailist[afd - afdl]); } if (!*res) if (sentinel.ai_next) freeaddrinfo(sentinel.ai_next); return (error); } static int reorder(struct addrinfo *sentinel) { struct addrinfo *ai, **aip; struct ai_order *aio; int i, n; struct policyhead policyhead; /* count the number of addrinfo elements for sorting. */ for (n = 0, ai = sentinel->ai_next; ai != NULL; ai = ai->ai_next, n++) ; /* * If the number is small enough, we can skip the reordering process. */ if (n <= 1) return(n); /* allocate a temporary array for sort and initialization of it. */ if ((aio = malloc(sizeof(*aio) * n)) == NULL) return(n); /* give up reordering */ memset(aio, 0, sizeof(*aio) * n); /* retrieve address selection policy from the kernel */ TAILQ_INIT(&policyhead); if (!get_addrselectpolicy(&policyhead)) { /* no policy is installed into kernel, we don't sort. */ free(aio); return (n); } for (i = 0, ai = sentinel->ai_next; i < n; ai = ai->ai_next, i++) { aio[i].aio_ai = ai; aio[i].aio_dstscope = gai_addr2scopetype(ai->ai_addr); aio[i].aio_dstpolicy = match_addrselectpolicy(ai->ai_addr, &policyhead); set_source(&aio[i], &policyhead); } /* perform sorting. */ qsort(aio, n, sizeof(*aio), comp_dst); /* reorder the addrinfo chain. */ for (i = 0, aip = &sentinel->ai_next; i < n; i++) { *aip = aio[i].aio_ai; aip = &aio[i].aio_ai->ai_next; } *aip = NULL; /* cleanup and return */ free(aio); free_addrselectpolicy(&policyhead); return(n); } static int get_addrselectpolicy(struct policyhead *head) { #ifdef INET6 int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY }; size_t l; char *buf; struct in6_addrpolicy *pol, *ep; if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0) return (0); if (l == 0) return (0); if ((buf = malloc(l)) == NULL) return (0); if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) { free(buf); return (0); } ep = (struct in6_addrpolicy *)(buf + l); for (pol = (struct in6_addrpolicy *)buf; pol + 1 <= ep; pol++) { struct policyqueue *new; if ((new = malloc(sizeof(*new))) == NULL) { free_addrselectpolicy(head); /* make the list empty */ break; } new->pc_policy = *pol; TAILQ_INSERT_TAIL(head, new, pc_entry); } free(buf); return (1); #else return (0); #endif } static void free_addrselectpolicy(struct policyhead *head) { struct policyqueue *ent, *nent; for (ent = TAILQ_FIRST(head); ent; ent = nent) { nent = TAILQ_NEXT(ent, pc_entry); TAILQ_REMOVE(head, ent, pc_entry); free(ent); } } static struct policyqueue * match_addrselectpolicy(struct sockaddr *addr, struct policyhead *head) { #ifdef INET6 struct policyqueue *ent, *bestent = NULL; struct in6_addrpolicy *pol; int matchlen, bestmatchlen = -1; u_char *mp, *ep, *k, *p, m; struct sockaddr_in6 key; switch(addr->sa_family) { case AF_INET6: key = *(struct sockaddr_in6 *)addr; break; case AF_INET: /* convert the address into IPv4-mapped IPv6 address. */ memset(&key, 0, sizeof(key)); key.sin6_family = AF_INET6; key.sin6_len = sizeof(key); - key.sin6_addr.s6_addr[10] = 0xff; - key.sin6_addr.s6_addr[11] = 0xff; - memcpy(&key.sin6_addr.s6_addr[12], - &((struct sockaddr_in *)addr)->sin_addr, 4); + _map_v4v6_address( + (char *)&((struct sockaddr_in *)addr)->sin_addr, + (char *)&key.sin6_addr); break; default: return(NULL); } for (ent = TAILQ_FIRST(head); ent; ent = TAILQ_NEXT(ent, pc_entry)) { pol = &ent->pc_policy; matchlen = 0; mp = (u_char *)&pol->addrmask.sin6_addr; ep = mp + 16; /* XXX: scope field? */ k = (u_char *)&key.sin6_addr; p = (u_char *)&pol->addr.sin6_addr; for (; mp < ep && *mp; mp++, k++, p++) { m = *mp; if ((*k & m) != *p) goto next; /* not match */ if (m == 0xff) /* short cut for a typical case */ matchlen += 8; else { while (m >= 0x80) { matchlen++; m <<= 1; } } } /* matched. check if this is better than the current best. */ if (matchlen > bestmatchlen) { bestent = ent; bestmatchlen = matchlen; } next: continue; } return(bestent); #else return(NULL); #endif } static void set_source(struct ai_order *aio, struct policyhead *ph) { struct addrinfo ai = *aio->aio_ai; struct sockaddr_storage ss; socklen_t srclen; int s; /* set unspec ("no source is available"), just in case */ aio->aio_srcsa.sa_family = AF_UNSPEC; aio->aio_srcscope = -1; switch(ai.ai_family) { case AF_INET: #ifdef INET6 case AF_INET6: #endif break; default: /* ignore unsupported AFs explicitly */ return; } /* XXX: make a dummy addrinfo to call connect() */ ai.ai_socktype = SOCK_DGRAM; ai.ai_protocol = IPPROTO_UDP; /* is UDP too specific? */ ai.ai_next = NULL; memset(&ss, 0, sizeof(ss)); memcpy(&ss, ai.ai_addr, ai.ai_addrlen); ai.ai_addr = (struct sockaddr *)&ss; get_port(&ai, "1", 0); /* open a socket to get the source address for the given dst */ if ((s = _socket(ai.ai_family, ai.ai_socktype | SOCK_CLOEXEC, ai.ai_protocol)) < 0) return; /* give up */ +#ifdef INET6 + if (ai.ai_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai.ai_addr; + int off = 0; + + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) + (void)_setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, + (char *)&off, sizeof(off)); + } +#endif if (_connect(s, ai.ai_addr, ai.ai_addrlen) < 0) goto cleanup; srclen = ai.ai_addrlen; if (_getsockname(s, &aio->aio_srcsa, &srclen) < 0) { aio->aio_srcsa.sa_family = AF_UNSPEC; goto cleanup; } aio->aio_srcscope = gai_addr2scopetype(&aio->aio_srcsa); aio->aio_srcpolicy = match_addrselectpolicy(&aio->aio_srcsa, ph); aio->aio_matchlen = matchlen(&aio->aio_srcsa, aio->aio_ai->ai_addr); #ifdef INET6 if (ai.ai_family == AF_INET6) { struct in6_ifreq ifr6; u_int32_t flags6; memset(&ifr6, 0, sizeof(ifr6)); memcpy(&ifr6.ifr_addr, ai.ai_addr, ai.ai_addrlen); if (_ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) { flags6 = ifr6.ifr_ifru.ifru_flags6; if ((flags6 & IN6_IFF_DEPRECATED)) aio->aio_srcflag |= AIO_SRCFLAG_DEPRECATED; } } #endif cleanup: _close(s); return; } static int matchlen(struct sockaddr *src, struct sockaddr *dst) { int match = 0; u_char *s, *d; u_char *lim, r; int addrlen; switch (src->sa_family) { #ifdef INET6 case AF_INET6: s = (u_char *)&((struct sockaddr_in6 *)src)->sin6_addr; d = (u_char *)&((struct sockaddr_in6 *)dst)->sin6_addr; addrlen = sizeof(struct in6_addr); lim = s + addrlen; break; #endif case AF_INET: s = (u_char *)&((struct sockaddr_in *)src)->sin_addr; d = (u_char *)&((struct sockaddr_in *)dst)->sin_addr; addrlen = sizeof(struct in_addr); lim = s + addrlen; break; default: return(0); } while (s < lim) if ((r = (*d++ ^ *s++)) != 0) { while (r < addrlen * 8) { match++; r <<= 1; } break; } else match += 8; return(match); } static int comp_dst(const void *arg1, const void *arg2) { const struct ai_order *dst1 = arg1, *dst2 = arg2; /* * Rule 1: Avoid unusable destinations. * XXX: we currently do not consider if an appropriate route exists. */ if (dst1->aio_srcsa.sa_family != AF_UNSPEC && dst2->aio_srcsa.sa_family == AF_UNSPEC) { return(-1); } if (dst1->aio_srcsa.sa_family == AF_UNSPEC && dst2->aio_srcsa.sa_family != AF_UNSPEC) { return(1); } /* Rule 2: Prefer matching scope. */ if (dst1->aio_dstscope == dst1->aio_srcscope && dst2->aio_dstscope != dst2->aio_srcscope) { return(-1); } if (dst1->aio_dstscope != dst1->aio_srcscope && dst2->aio_dstscope == dst2->aio_srcscope) { return(1); } /* Rule 3: Avoid deprecated addresses. */ if (dst1->aio_srcsa.sa_family != AF_UNSPEC && dst2->aio_srcsa.sa_family != AF_UNSPEC) { if (!(dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) && (dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) { return(-1); } if ((dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) && !(dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) { return(1); } } /* Rule 4: Prefer home addresses. */ /* XXX: not implemented yet */ /* Rule 5: Prefer matching label. */ #ifdef INET6 if (dst1->aio_srcpolicy && dst1->aio_dstpolicy && dst1->aio_srcpolicy->pc_policy.label == dst1->aio_dstpolicy->pc_policy.label && (dst2->aio_srcpolicy == NULL || dst2->aio_dstpolicy == NULL || dst2->aio_srcpolicy->pc_policy.label != dst2->aio_dstpolicy->pc_policy.label)) { return(-1); } if (dst2->aio_srcpolicy && dst2->aio_dstpolicy && dst2->aio_srcpolicy->pc_policy.label == dst2->aio_dstpolicy->pc_policy.label && (dst1->aio_srcpolicy == NULL || dst1->aio_dstpolicy == NULL || dst1->aio_srcpolicy->pc_policy.label != dst1->aio_dstpolicy->pc_policy.label)) { return(1); } #endif /* Rule 6: Prefer higher precedence. */ #ifdef INET6 if (dst1->aio_dstpolicy && (dst2->aio_dstpolicy == NULL || dst1->aio_dstpolicy->pc_policy.preced > dst2->aio_dstpolicy->pc_policy.preced)) { return(-1); } if (dst2->aio_dstpolicy && (dst1->aio_dstpolicy == NULL || dst2->aio_dstpolicy->pc_policy.preced > dst1->aio_dstpolicy->pc_policy.preced)) { return(1); } #endif /* Rule 7: Prefer native transport. */ /* XXX: not implemented yet */ /* Rule 8: Prefer smaller scope. */ if (dst1->aio_dstscope >= 0 && dst1->aio_dstscope < dst2->aio_dstscope) { return(-1); } if (dst2->aio_dstscope >= 0 && dst2->aio_dstscope < dst1->aio_dstscope) { return(1); } /* * Rule 9: Use longest matching prefix. * We compare the match length in a same AF only. */ if (dst1->aio_ai->ai_addr->sa_family == dst2->aio_ai->ai_addr->sa_family && dst1->aio_ai->ai_addr->sa_family != AF_INET) { if (dst1->aio_matchlen > dst2->aio_matchlen) { return(-1); } if (dst1->aio_matchlen < dst2->aio_matchlen) { return(1); } } /* Rule 10: Otherwise, leave the order unchanged. */ return(-1); } /* * Copy from scope.c. * XXX: we should standardize the functions and link them as standard * library. */ static int gai_addr2scopetype(struct sockaddr *sa) { #ifdef INET6 struct sockaddr_in6 *sa6; #endif struct sockaddr_in *sa4; switch(sa->sa_family) { #ifdef INET6 case AF_INET6: sa6 = (struct sockaddr_in6 *)sa; if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) { /* just use the scope field of the multicast address */ return(sa6->sin6_addr.s6_addr[2] & 0x0f); } /* * Unicast addresses: map scope type to corresponding scope * value defined for multcast addresses. * XXX: hardcoded scope type values are bad... */ if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr)) return(1); /* node local scope */ if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) return(2); /* link-local scope */ if (IN6_IS_ADDR_SITELOCAL(&sa6->sin6_addr)) return(5); /* site-local scope */ return(14); /* global scope */ break; #endif case AF_INET: /* * IPv4 pseudo scoping according to RFC 3484. */ sa4 = (struct sockaddr_in *)sa; /* IPv4 autoconfiguration addresses have link-local scope. */ if (((u_char *)&sa4->sin_addr)[0] == 169 && ((u_char *)&sa4->sin_addr)[1] == 254) return(2); /* Private addresses have site-local scope. */ if (((u_char *)&sa4->sin_addr)[0] == 10 || (((u_char *)&sa4->sin_addr)[0] == 172 && (((u_char *)&sa4->sin_addr)[1] & 0xf0) == 16) || (((u_char *)&sa4->sin_addr)[0] == 192 && ((u_char *)&sa4->sin_addr)[1] == 168)) return(14); /* XXX: It should be 5 unless NAT */ /* Loopback addresses have link-local scope. */ if (((u_char *)&sa4->sin_addr)[0] == 127) return(2); return(14); break; default: errno = EAFNOSUPPORT; /* is this a good error? */ return(-1); } } static int explore_copy(const struct addrinfo *pai, const struct addrinfo *src0, struct addrinfo **res) { int error; struct addrinfo sentinel, *cur; const struct addrinfo *src; error = 0; sentinel.ai_next = NULL; cur = &sentinel; for (src = src0; src != NULL; src = src->ai_next) { if (src->ai_family != pai->ai_family) continue; cur->ai_next = copy_ai(src); if (!cur->ai_next) { error = EAI_MEMORY; goto fail; } cur->ai_next->ai_socktype = pai->ai_socktype; cur->ai_next->ai_protocol = pai->ai_protocol; cur = cur->ai_next; } *res = sentinel.ai_next; return 0; fail: freeaddrinfo(sentinel.ai_next); return error; } /* * hostname == NULL. * passive socket -> anyaddr (0.0.0.0 or ::) * non-passive socket -> localhost (127.0.0.1 or ::1) */ static int explore_null(const struct addrinfo *pai, const char *servname, struct addrinfo **res) { int s; const struct afd *afd; struct addrinfo *ai; int error; *res = NULL; ai = NULL; if (pai->ai_family == PF_LOCAL) return (0); /* * filter out AFs that are not supported by the kernel * XXX errno? */ s = _socket(pai->ai_family, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (s < 0) { if (errno != EMFILE) return 0; } else _close(s); afd = find_afd(pai->ai_family); if (afd == NULL) return 0; if (pai->ai_flags & AI_PASSIVE) { GET_AI(ai, afd, afd->a_addrany); GET_PORT(ai, servname); } else { GET_AI(ai, afd, afd->a_loopback); GET_PORT(ai, servname); } *res = ai; return 0; free: if (ai != NULL) freeaddrinfo(ai); return error; } /* * numeric hostname */ static int explore_numeric(const struct addrinfo *pai, const char *hostname, const char *servname, struct addrinfo **res, const char *canonname) { const struct afd *afd; - struct addrinfo *ai; + struct addrinfo *ai, ai0; int error; char pton[PTON_MAX], path[PATH_MAX], *p; #ifdef CTASSERT CTASSERT(sizeofmember(struct sockaddr_un, sun_path) <= PATH_MAX); #endif *res = NULL; ai = NULL; afd = find_afd(pai->ai_family); if (afd == NULL) return 0; switch (afd->a_af) { case AF_LOCAL: if (hostname[0] != '/') ERR(EAI_NONAME); if (strlen(hostname) > afd->a_addrlen) ERR(EAI_MEMORY); /* NUL-termination does not need to be guaranteed. */ strncpy(path, hostname, afd->a_addrlen); p = &path[0]; break; case AF_INET: /* * RFC3493 requires getaddrinfo() to accept AF_INET formats * that are accepted by inet_addr() and its family. The * accepted forms includes the "classful" one, which inet_pton * does not accept. So we need to separate the case for * AF_INET. */ if (inet_aton(hostname, (struct in_addr *)pton) != 1) return 0; p = pton; break; default: - if (inet_pton(afd->a_af, hostname, pton) != 1) - return 0; + if (inet_pton(afd->a_af, hostname, pton) != 1) { + if (pai->ai_family != AF_INET6 || + (pai->ai_flags & AI_V4MAPPED) != AI_V4MAPPED) + return 0; + if (inet_aton(hostname, (struct in_addr *)pton) != 1) + return 0; + afd = &afdl[N_INET]; + ai0 = *pai; + ai0.ai_family = AF_INET; + pai = &ai0; + } p = pton; break; } if (pai->ai_family == afd->a_af) { GET_AI(ai, afd, p); GET_PORT(ai, servname); if ((pai->ai_family == AF_INET || pai->ai_family == AF_INET6) && (pai->ai_flags & AI_CANONNAME)) { /* * Set the numeric address itself as the canonical * name, based on a clarification in RFC3493. */ GET_CANONNAME(ai, canonname); } } else { /* * XXX: This should not happen since we already matched the AF * by find_afd. */ ERR(EAI_FAMILY); } *res = ai; return 0; free: bad: if (ai != NULL) freeaddrinfo(ai); return error; } /* * numeric hostname with scope */ static int explore_numeric_scope(const struct addrinfo *pai, const char *hostname, const char *servname, struct addrinfo **res) { #if !defined(SCOPE_DELIMITER) || !defined(INET6) return explore_numeric(pai, hostname, servname, res, hostname); #else const struct afd *afd; struct addrinfo *cur; int error; char *cp, *hostname2 = NULL, *scope, *addr; struct sockaddr_in6 *sin6; afd = find_afd(pai->ai_family); if (afd == NULL) return 0; if (!afd->a_scoped) return explore_numeric(pai, hostname, servname, res, hostname); cp = strchr(hostname, SCOPE_DELIMITER); if (cp == NULL) return explore_numeric(pai, hostname, servname, res, hostname); /* * Handle special case of */ hostname2 = strdup(hostname); if (hostname2 == NULL) return EAI_MEMORY; /* terminate at the delimiter */ hostname2[cp - hostname] = '\0'; addr = hostname2; scope = cp + 1; error = explore_numeric(pai, addr, servname, res, hostname); if (error == 0) { u_int32_t scopeid; for (cur = *res; cur; cur = cur->ai_next) { if (cur->ai_family != AF_INET6) continue; sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) { free(hostname2); freeaddrinfo(*res); *res = NULL; return(EAI_NONAME); /* XXX: is return OK? */ } sin6->sin6_scope_id = scopeid; } } free(hostname2); if (error && *res) { freeaddrinfo(*res); *res = NULL; } return error; #endif } static int get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str) { if ((pai->ai_flags & AI_CANONNAME) != 0) { ai->ai_canonname = strdup(str); if (ai->ai_canonname == NULL) return EAI_MEMORY; } return 0; } static struct addrinfo * get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr) { char *p; struct addrinfo *ai; +#ifdef INET6 + struct in6_addr mapaddr; + if (afd->a_af == AF_INET && (pai->ai_flags & AI_V4MAPPED) != 0) { + afd = &afdl[N_INET6]; + _map_v4v6_address(addr, (char *)&mapaddr); + addr = (char *)&mapaddr; + } +#endif + ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + (afd->a_socklen)); if (ai == NULL) return NULL; memcpy(ai, pai, sizeof(struct addrinfo)); ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); memset(ai->ai_addr, 0, (size_t)afd->a_socklen); ai->ai_addr->sa_len = afd->a_socklen; ai->ai_addrlen = afd->a_socklen; if (ai->ai_family == PF_LOCAL) { size_t n = strnlen(addr, afd->a_addrlen); ai->ai_addrlen -= afd->a_addrlen - n; ai->ai_addr->sa_len -= afd->a_addrlen - n; } ai->ai_addr->sa_family = ai->ai_family = afd->a_af; p = (char *)(void *)(ai->ai_addr); memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); return ai; } /* XXX need to malloc() the same way we do from other functions! */ static struct addrinfo * copy_ai(const struct addrinfo *pai) { struct addrinfo *ai; size_t l; l = sizeof(*ai) + pai->ai_addrlen; if ((ai = (struct addrinfo *)malloc(l)) == NULL) return NULL; memset(ai, 0, l); memcpy(ai, pai, sizeof(*ai)); ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen); if (pai->ai_canonname) { l = strlen(pai->ai_canonname) + 1; if ((ai->ai_canonname = malloc(l)) == NULL) { free(ai); return NULL; } strlcpy(ai->ai_canonname, pai->ai_canonname, l); } else { /* just to make sure */ ai->ai_canonname = NULL; } ai->ai_next = NULL; return ai; } static int get_portmatch(const struct addrinfo *ai, const char *servname) { /* get_port does not touch first argument when matchonly == 1. */ /* LINTED const cast */ return get_port((struct addrinfo *)ai, servname, 1); } static int get_port(struct addrinfo *ai, const char *servname, int matchonly) { const char *proto; struct servent *sp; int port, error; int allownumeric; if (servname == NULL) return 0; switch (ai->ai_family) { case AF_LOCAL: /* AF_LOCAL ignores servname silently. */ return (0); case AF_INET: #ifdef AF_INET6 case AF_INET6: #endif break; default: return 0; } switch (ai->ai_socktype) { case SOCK_RAW: return EAI_SERVICE; case SOCK_DGRAM: case SOCK_STREAM: case SOCK_SEQPACKET: allownumeric = 1; break; case ANY: switch (ai->ai_family) { case AF_INET: #ifdef AF_INET6 case AF_INET6: #endif allownumeric = 1; break; default: allownumeric = 0; break; } break; default: return EAI_SOCKTYPE; } error = str2number(servname, &port); if (error == 0) { if (!allownumeric) return EAI_SERVICE; if (port < 0 || port > 65535) return EAI_SERVICE; port = htons(port); } else { if (ai->ai_flags & AI_NUMERICSERV) return EAI_NONAME; switch (ai->ai_protocol) { case IPPROTO_UDP: proto = "udp"; break; case IPPROTO_TCP: proto = "tcp"; break; case IPPROTO_SCTP: proto = "sctp"; break; case IPPROTO_UDPLITE: proto = "udplite"; break; default: proto = NULL; break; } if ((sp = getservbyname(servname, proto)) == NULL) return EAI_SERVICE; port = sp->s_port; } if (!matchonly) { switch (ai->ai_family) { case AF_INET: ((struct sockaddr_in *)(void *) ai->ai_addr)->sin_port = port; break; #ifdef INET6 case AF_INET6: ((struct sockaddr_in6 *)(void *) ai->ai_addr)->sin6_port = port; break; #endif } } return 0; } static const struct afd * find_afd(int af) { const struct afd *afd; if (af == PF_UNSPEC) return NULL; for (afd = afdl; afd->a_af; afd++) { if (afd->a_af == af) return afd; } return NULL; } /* * RFC 3493: AI_ADDRCONFIG check. Determines which address families are * configured on the local system and correlates with pai->ai_family value. * If an address family is not configured on the system, it will not be * queried for. For this purpose, loopback addresses are not considered * configured addresses. * * XXX PF_UNSPEC -> PF_INET6 + PF_INET mapping needs to be in sync with * _dns_getaddrinfo. */ static int addrconfig(struct addrinfo *pai) { struct ifaddrs *ifaddrs, *ifa; struct sockaddr_in *sin; #ifdef INET6 struct sockaddr_in6 *sin6; #endif int seen_inet = 0, seen_inet6 = 0; if (getifaddrs(&ifaddrs) != 0) return (0); for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL || (ifa->ifa_flags & IFF_UP) == 0) continue; switch (ifa->ifa_addr->sa_family) { case AF_INET: if (seen_inet) continue; sin = (struct sockaddr_in *)(ifa->ifa_addr); if (htonl(sin->sin_addr.s_addr) == INADDR_LOOPBACK) continue; seen_inet = 1; break; #ifdef INET6 case AF_INET6: if (seen_inet6) continue; sin6 = (struct sockaddr_in6 *)(ifa->ifa_addr); if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) continue; if ((ifa->ifa_flags & IFT_LOOP) != 0 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) continue; if (is_ifdisabled(ifa->ifa_name)) continue; seen_inet6 = 1; break; #endif } } freeifaddrs(ifaddrs); switch(pai->ai_family) { case AF_INET6: return (seen_inet6); case AF_INET: return (seen_inet); case AF_UNSPEC: if (seen_inet == seen_inet6) return (seen_inet); pai->ai_family = seen_inet ? AF_INET : AF_INET6; return (1); } return (1); } #ifdef INET6 static int is_ifdisabled(char *name) { struct in6_ndireq nd; int fd; if ((fd = _socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0) return (-1); memset(&nd, 0, sizeof(nd)); strlcpy(nd.ifname, name, sizeof(nd.ifname)); if (_ioctl(fd, SIOCGIFINFO_IN6, &nd) < 0) { _close(fd); return (-1); } _close(fd); return ((nd.ndi.flags & ND6_IFF_IFDISABLED) != 0); } /* convert a string to a scope identifier. XXX: IPv6 specific */ static int ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid) { u_long lscopeid; struct in6_addr *a6; char *ep; a6 = &sin6->sin6_addr; /* empty scopeid portion is invalid */ if (*scope == '\0') return -1; if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) || IN6_IS_ADDR_MC_NODELOCAL(a6)) { /* * We currently assume a one-to-one mapping between links * and interfaces, so we simply use interface indices for * like-local scopes. */ *scopeid = if_nametoindex(scope); if (*scopeid == 0) goto trynumeric; return 0; } /* still unclear about literal, allow numeric only - placeholder */ if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) goto trynumeric; if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) goto trynumeric; else goto trynumeric; /* global */ /* try to convert to a numeric id as a last resort */ trynumeric: errno = 0; lscopeid = strtoul(scope, &ep, 10); *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL); if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid) return 0; else return -1; } #endif #ifdef NS_CACHING static int addrinfo_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata) { res_state statp; u_long res_options; const int op_id = 0; /* identifies the getaddrinfo for the cache */ char *hostname; struct addrinfo *hints; char *p; int ai_flags, ai_family, ai_socktype, ai_protocol; size_t desired_size, size; statp = __res_state(); res_options = statp->options & (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH | RES_NOALIASES | RES_USE_INET6); hostname = va_arg(ap, char *); hints = va_arg(ap, struct addrinfo *); desired_size = sizeof(res_options) + sizeof(int) + sizeof(int) * 4; if (hostname != NULL) { size = strlen(hostname); desired_size += size + 1; } else size = 0; if (desired_size > *buffer_size) { *buffer_size = desired_size; return (NS_RETURN); } if (hints == NULL) ai_flags = ai_family = ai_socktype = ai_protocol = 0; else { ai_flags = hints->ai_flags; ai_family = hints->ai_family; ai_socktype = hints->ai_socktype; ai_protocol = hints->ai_protocol; } p = buffer; memcpy(p, &res_options, sizeof(res_options)); p += sizeof(res_options); memcpy(p, &op_id, sizeof(int)); p += sizeof(int); memcpy(p, &ai_flags, sizeof(int)); p += sizeof(int); memcpy(p, &ai_family, sizeof(int)); p += sizeof(int); memcpy(p, &ai_socktype, sizeof(int)); p += sizeof(int); memcpy(p, &ai_protocol, sizeof(int)); p += sizeof(int); if (hostname != NULL) memcpy(p, hostname, size); *buffer_size = desired_size; return (NS_SUCCESS); } static int addrinfo_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap, void *cache_mdata) { struct addrinfo *ai, *cai; char *p; size_t desired_size, size, ai_size; ai = *((struct addrinfo **)retval); desired_size = sizeof(size_t); ai_size = 0; for (cai = ai; cai != NULL; cai = cai->ai_next) { desired_size += sizeof(struct addrinfo) + cai->ai_addrlen; if (cai->ai_canonname != NULL) desired_size += sizeof(size_t) + strlen(cai->ai_canonname); ++ai_size; } if (desired_size > *buffer_size) { /* this assignment is here for future use */ errno = ERANGE; *buffer_size = desired_size; return (NS_RETURN); } memset(buffer, 0, desired_size); p = buffer; memcpy(p, &ai_size, sizeof(size_t)); p += sizeof(size_t); for (cai = ai; cai != NULL; cai = cai->ai_next) { memcpy(p, cai, sizeof(struct addrinfo)); p += sizeof(struct addrinfo); memcpy(p, cai->ai_addr, cai->ai_addrlen); p += cai->ai_addrlen; if (cai->ai_canonname != NULL) { size = strlen(cai->ai_canonname); memcpy(p, &size, sizeof(size_t)); p += sizeof(size_t); memcpy(p, cai->ai_canonname, size); p += size; } } return (NS_SUCCESS); } static int addrinfo_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap, void *cache_mdata) { struct addrinfo new_ai, *result, *sentinel, *lasts; char *p; size_t ai_size, ai_i, size; p = buffer; memcpy(&ai_size, p, sizeof(size_t)); p += sizeof(size_t); result = NULL; lasts = NULL; for (ai_i = 0; ai_i < ai_size; ++ai_i) { memcpy(&new_ai, p, sizeof(struct addrinfo)); p += sizeof(struct addrinfo); size = new_ai.ai_addrlen + sizeof(struct addrinfo) + _ALIGNBYTES; sentinel = (struct addrinfo *)malloc(size); memset(sentinel, 0, size); memcpy(sentinel, &new_ai, sizeof(struct addrinfo)); sentinel->ai_addr = (struct sockaddr *)_ALIGN((char *)sentinel + sizeof(struct addrinfo)); memcpy(sentinel->ai_addr, p, new_ai.ai_addrlen); p += new_ai.ai_addrlen; if (new_ai.ai_canonname != NULL) { memcpy(&size, p, sizeof(size_t)); p += sizeof(size_t); sentinel->ai_canonname = (char *)malloc(size + 1); memset(sentinel->ai_canonname, 0, size + 1); memcpy(sentinel->ai_canonname, p, size); p += size; } if (result == NULL) { result = sentinel; lasts = sentinel; } else { lasts->ai_next = sentinel; lasts = sentinel; } } *((struct addrinfo **)retval) = result; return (NS_SUCCESS); } #endif /* NS_CACHING */ /* * FQDN hostname, DNS lookup */ static int explore_fqdn(const struct addrinfo *pai, const char *hostname, const char *servname, struct addrinfo **res) { struct addrinfo *result; struct addrinfo *cur; int error = 0; #ifdef NS_CACHING static const nss_cache_info cache_info = NS_COMMON_CACHE_INFO_INITIALIZER( hosts, NULL, addrinfo_id_func, addrinfo_marshal_func, addrinfo_unmarshal_func); #endif static const ns_dtab dtab[] = { NS_FILES_CB(_files_getaddrinfo, NULL) { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */ NS_NIS_CB(_yp_getaddrinfo, NULL) #ifdef NS_CACHING NS_CACHE_CB(&cache_info) #endif { 0 } }; result = NULL; /* * if the servname does not match socktype/protocol, ignore it. */ if (get_portmatch(pai, servname) != 0) return 0; switch (_nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo", default_dns_files, hostname, pai)) { case NS_TRYAGAIN: error = EAI_AGAIN; goto free; case NS_UNAVAIL: error = EAI_FAIL; goto free; case NS_NOTFOUND: error = EAI_NONAME; goto free; case NS_SUCCESS: error = 0; for (cur = result; cur; cur = cur->ai_next) { GET_PORT(cur, servname); /* canonname should be filled already */ } break; } *res = result; return 0; free: if (result) freeaddrinfo(result); return error; } #ifdef DEBUG static const char AskedForGot[] = "gethostby*.getanswer: asked for \"%s\", got \"%s\""; #endif static struct addrinfo * getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, const struct addrinfo *pai, res_state res) { struct addrinfo sentinel, *cur; struct addrinfo ai; const struct afd *afd; char *canonname; const HEADER *hp; const u_char *cp; int n; const u_char *eom; char *bp, *ep; int type, class, ancount, qdcount; int haveanswer, had_error; char tbuf[MAXDNAME]; int (*name_ok)(const char *); char hostbuf[8*1024]; memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; canonname = NULL; eom = answer->buf + anslen; switch (qtype) { case T_A: case T_AAAA: case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/ name_ok = res_hnok; break; default: return (NULL); /* XXX should be abort(); */ } /* * find first satisfactory answer */ hp = &answer->hdr; ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); bp = hostbuf; ep = hostbuf + sizeof hostbuf; cp = answer->buf + HFIXEDSZ; if (qdcount != 1) { RES_SET_H_ERRNO(res, NO_RECOVERY); return (NULL); } n = dn_expand(answer->buf, eom, cp, bp, ep - bp); if ((n < 0) || !(*name_ok)(bp)) { RES_SET_H_ERRNO(res, NO_RECOVERY); return (NULL); } cp += n + QFIXEDSZ; if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) { /* res_send() has already verified that the query name is the * same as the one we sent; this just gets the expanded name * (i.e., with the succeeding search-domain tacked on). */ n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { RES_SET_H_ERRNO(res, NO_RECOVERY); return (NULL); } canonname = bp; bp += n; /* The qname can be abbreviated, but h_name is now absolute. */ qname = canonname; } haveanswer = 0; had_error = 0; while (ancount-- > 0 && cp < eom && !had_error) { n = dn_expand(answer->buf, eom, cp, bp, ep - bp); if ((n < 0) || !(*name_ok)(bp)) { had_error++; continue; } cp += n; /* name */ type = _getshort(cp); cp += INT16SZ; /* type */ class = _getshort(cp); cp += INT16SZ + INT32SZ; /* class, TTL */ n = _getshort(cp); cp += INT16SZ; /* len */ if (class != C_IN) { /* XXX - debug? syslog? */ cp += n; continue; /* XXX - had_error++ ? */ } if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && type == T_CNAME) { n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); if ((n < 0) || !(*name_ok)(tbuf)) { had_error++; continue; } cp += n; /* Get canonical name. */ n = strlen(tbuf) + 1; /* for the \0 */ if (n > ep - bp || n >= MAXHOSTNAMELEN) { had_error++; continue; } strlcpy(bp, tbuf, ep - bp); canonname = bp; bp += n; continue; } if (qtype == T_ANY) { if (!(type == T_A || type == T_AAAA)) { cp += n; continue; } } else if (type != qtype) { #ifdef DEBUG if (type != T_KEY && type != T_SIG && type != ns_t_dname) syslog(LOG_NOTICE|LOG_AUTH, "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", qname, p_class(C_IN), p_type(qtype), p_type(type)); #endif cp += n; continue; /* XXX - had_error++ ? */ } switch (type) { case T_A: case T_AAAA: if (strcasecmp(canonname, bp) != 0) { #ifdef DEBUG syslog(LOG_NOTICE|LOG_AUTH, AskedForGot, canonname, bp); #endif cp += n; continue; /* XXX - had_error++ ? */ } if (type == T_A && n != INADDRSZ) { cp += n; continue; } if (type == T_AAAA && n != IN6ADDRSZ) { cp += n; continue; } #ifdef FILTER_V4MAPPED if (type == T_AAAA) { struct in6_addr in6; memcpy(&in6, cp, sizeof(in6)); if (IN6_IS_ADDR_V4MAPPED(&in6)) { cp += n; continue; } } #endif if (!haveanswer) { int nn; canonname = bp; nn = strlen(bp) + 1; /* for the \0 */ bp += nn; } /* don't overwrite pai */ ai = *pai; ai.ai_family = (type == T_A) ? AF_INET : AF_INET6; afd = find_afd(ai.ai_family); if (afd == NULL) { cp += n; continue; } cur->ai_next = get_ai(&ai, afd, (const char *)cp); if (cur->ai_next == NULL) had_error++; while (cur && cur->ai_next) cur = cur->ai_next; cp += n; break; default: abort(); } if (!had_error) haveanswer++; } if (haveanswer) { #if defined(RESOLVSORT) /* * We support only IPv4 address for backward * compatibility against gethostbyname(3). */ if (res->nsort && qtype == T_A) { if (addr4sort(&sentinel, res) < 0) { freeaddrinfo(sentinel.ai_next); RES_SET_H_ERRNO(res, NO_RECOVERY); return NULL; } } #endif /*RESOLVSORT*/ if (!canonname) (void)get_canonname(pai, sentinel.ai_next, qname); else (void)get_canonname(pai, sentinel.ai_next, canonname); RES_SET_H_ERRNO(res, NETDB_SUCCESS); return sentinel.ai_next; } RES_SET_H_ERRNO(res, NO_RECOVERY); return NULL; } #ifdef RESOLVSORT struct addr_ptr { struct addrinfo *ai; int aval; }; static int addr4sort(struct addrinfo *sentinel, res_state res) { struct addrinfo *ai; struct addr_ptr *addrs, addr; struct sockaddr_in *sin; int naddrs, i, j; int needsort = 0; if (!sentinel) return -1; naddrs = 0; for (ai = sentinel->ai_next; ai; ai = ai->ai_next) naddrs++; if (naddrs < 2) return 0; /* We don't need sorting. */ if ((addrs = malloc(sizeof(struct addr_ptr) * naddrs)) == NULL) return -1; i = 0; for (ai = sentinel->ai_next; ai; ai = ai->ai_next) { sin = (struct sockaddr_in *)ai->ai_addr; for (j = 0; (unsigned)j < res->nsort; j++) { if (res->sort_list[j].addr.s_addr == (sin->sin_addr.s_addr & res->sort_list[j].mask)) break; } addrs[i].ai = ai; addrs[i].aval = j; if (needsort == 0 && i > 0 && j < addrs[i - 1].aval) needsort = i; i++; } if (!needsort) { free(addrs); return 0; } while (needsort < naddrs) { for (j = needsort - 1; j >= 0; j--) { if (addrs[j].aval > addrs[j+1].aval) { addr = addrs[j]; addrs[j] = addrs[j + 1]; addrs[j + 1] = addr; } else break; } needsort++; } ai = sentinel; for (i = 0; i < naddrs; ++i) { ai->ai_next = addrs[i].ai; ai = ai->ai_next; } ai->ai_next = NULL; free(addrs); return 0; } #endif /*RESOLVSORT*/ /*ARGSUSED*/ static int _dns_getaddrinfo(void *rv, void *cb_data, va_list ap) { - struct addrinfo *ai; + struct addrinfo *ai, ai0; querybuf *buf, *buf2; const char *hostname; const struct addrinfo *pai; struct addrinfo sentinel, *cur; struct res_target q, q2; res_state res; hostname = va_arg(ap, char *); pai = va_arg(ap, const struct addrinfo *); memset(&q, 0, sizeof(q)); memset(&q2, 0, sizeof(q2)); memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; res = __res_state(); buf = malloc(sizeof(*buf)); if (!buf) { RES_SET_H_ERRNO(res, NETDB_INTERNAL); return NS_NOTFOUND; } buf2 = malloc(sizeof(*buf2)); if (!buf2) { free(buf); RES_SET_H_ERRNO(res, NETDB_INTERNAL); return NS_NOTFOUND; } + if (pai->ai_family == AF_INET6 && + (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED) { + ai0 = *pai; + ai0.ai_family = AF_UNSPEC; + pai = &ai0; + } + switch (pai->ai_family) { case AF_UNSPEC: q.name = hostname; q.qclass = C_IN; q.qtype = T_A; q.answer = buf->buf; q.anslen = sizeof(buf->buf); q.next = &q2; q2.name = hostname; q2.qclass = C_IN; q2.qtype = T_AAAA; q2.answer = buf2->buf; q2.anslen = sizeof(buf2->buf); break; case AF_INET: q.name = hostname; q.qclass = C_IN; q.qtype = T_A; q.answer = buf->buf; q.anslen = sizeof(buf->buf); break; case AF_INET6: q.name = hostname; q.qclass = C_IN; q.qtype = T_AAAA; q.answer = buf->buf; q.anslen = sizeof(buf->buf); break; default: free(buf); free(buf2); return NS_UNAVAIL; } if ((res->options & RES_INIT) == 0 && res_ninit(res) == -1) { RES_SET_H_ERRNO(res, NETDB_INTERNAL); free(buf); free(buf2); return NS_NOTFOUND; } if (res_searchN(hostname, &q, res) < 0) { free(buf); free(buf2); return NS_NOTFOUND; } /* prefer IPv6 */ if (q.next) { ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai, res); if (ai) { cur->ai_next = ai; while (cur && cur->ai_next) cur = cur->ai_next; } } - ai = getanswer(buf, q.n, q.name, q.qtype, pai, res); - if (ai) - cur->ai_next = ai; + if (!ai || pai->ai_family != AF_UNSPEC || + (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) != AI_V4MAPPED) { + ai = getanswer(buf, q.n, q.name, q.qtype, pai, res); + if (ai) + cur->ai_next = ai; + } free(buf); free(buf2); if (sentinel.ai_next == NULL) switch (res->res_h_errno) { case HOST_NOT_FOUND: return NS_NOTFOUND; case TRY_AGAIN: return NS_TRYAGAIN; default: return NS_UNAVAIL; } *((struct addrinfo **)rv) = sentinel.ai_next; return NS_SUCCESS; } static void _sethtent(FILE **hostf) { if (!*hostf) *hostf = fopen(_PATH_HOSTS, "re"); else rewind(*hostf); } static void _endhtent(FILE **hostf) { if (*hostf) { (void) fclose(*hostf); *hostf = NULL; } } static struct addrinfo * _gethtent(FILE **hostf, const char *name, const struct addrinfo *pai) { char *p; char *cp, *tname, *cname; struct addrinfo hints, *res0, *res; int error; const char *addr; char hostbuf[8*1024]; if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "re"))) return (NULL); again: if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf))) return (NULL); if (*p == '#') goto again; cp = strpbrk(p, "#\n"); if (cp != NULL) *cp = '\0'; if (!(cp = strpbrk(p, " \t"))) goto again; *cp++ = '\0'; addr = p; cname = NULL; /* if this is not something we're looking for, skip it. */ while (cp && *cp) { if (*cp == ' ' || *cp == '\t') { cp++; continue; } tname = cp; if (cname == NULL) cname = cp; if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0'; if (strcasecmp(name, tname) == 0) goto found; } goto again; found: /* we should not glob socktype/protocol here */ memset(&hints, 0, sizeof(hints)); hints.ai_family = pai->ai_family; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = 0; hints.ai_flags = AI_NUMERICHOST; + if (pai->ai_family == AF_INET6 && + (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED) + hints.ai_flags |= AI_V4MAPPED; error = getaddrinfo(addr, "0", &hints, &res0); if (error) goto again; #ifdef FILTER_V4MAPPED /* XXX should check all items in the chain */ if (res0->ai_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)res0->ai_addr)->sin6_addr)) { freeaddrinfo(res0); goto again; } #endif for (res = res0; res; res = res->ai_next) { /* cover it up */ res->ai_flags = pai->ai_flags; res->ai_socktype = pai->ai_socktype; res->ai_protocol = pai->ai_protocol; if (pai->ai_flags & AI_CANONNAME) { if (get_canonname(pai, res, cname) != 0) { freeaddrinfo(res0); goto again; } } } return res0; } +static struct addrinfo * +_getht(FILE **hostf, const char *name, const struct addrinfo *pai, + struct addrinfo *cur) +{ + struct addrinfo *p; + + while ((p = _gethtent(hostf, name, pai)) != NULL) { + cur->ai_next = p; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + return (cur); +} + /*ARGSUSED*/ static int _files_getaddrinfo(void *rv, void *cb_data, va_list ap) { const char *name; const struct addrinfo *pai; struct addrinfo sentinel, *cur; - struct addrinfo *p; FILE *hostf = NULL; name = va_arg(ap, char *); pai = va_arg(ap, struct addrinfo *); memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; _sethtent(&hostf); - while ((p = _gethtent(&hostf, name, pai)) != NULL) { - cur->ai_next = p; - while (cur && cur->ai_next) - cur = cur->ai_next; - } + if (pai->ai_family == AF_INET6 && + (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) == AI_V4MAPPED) { + struct addrinfo ai0 = *pai; + + ai0.ai_flags &= ~AI_V4MAPPED; + cur = _getht(&hostf, name, &ai0, cur); + if (sentinel.ai_next == NULL) { + _sethtent(&hostf); + ai0.ai_flags |= AI_V4MAPPED; + cur = _getht(&hostf, name, &ai0, cur); + } + } else + cur = _getht(&hostf, name, pai, cur); _endhtent(&hostf); *((struct addrinfo **)rv) = sentinel.ai_next; if (sentinel.ai_next == NULL) return NS_NOTFOUND; return NS_SUCCESS; } #ifdef YP /*ARGSUSED*/ static struct addrinfo * _yphostent(char *line, const struct addrinfo *pai) { struct addrinfo sentinel, *cur; struct addrinfo hints, *res, *res0; int error; char *p = line; const char *addr, *canonname; char *nextline; char *cp; addr = canonname = NULL; memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; nextline: /* terminate line */ cp = strchr(p, '\n'); if (cp) { *cp++ = '\0'; nextline = cp; } else nextline = NULL; cp = strpbrk(p, " \t"); if (cp == NULL) { if (canonname == NULL) return (NULL); else goto done; } *cp++ = '\0'; addr = p; while (cp && *cp) { if (*cp == ' ' || *cp == '\t') { cp++; continue; } if (!canonname) canonname = cp; if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0'; } hints = *pai; hints.ai_flags = AI_NUMERICHOST; + if (pai->ai_family == AF_INET6 && + (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED) + hints.ai_flags |= AI_V4MAPPED; error = getaddrinfo(addr, NULL, &hints, &res0); if (error == 0) { for (res = res0; res; res = res->ai_next) { /* cover it up */ res->ai_flags = pai->ai_flags; if (pai->ai_flags & AI_CANONNAME) (void)get_canonname(pai, res, canonname); } } else res0 = NULL; if (res0) { cur->ai_next = res0; while (cur && cur->ai_next) cur = cur->ai_next; } if (nextline) { p = nextline; goto nextline; } done: return sentinel.ai_next; } /*ARGSUSED*/ static int _yp_getaddrinfo(void *rv, void *cb_data, va_list ap) { struct addrinfo sentinel, *cur; struct addrinfo *ai = NULL; char *ypbuf; int ypbuflen, r; const char *name; const struct addrinfo *pai; char *ypdomain; if (_yp_check(&ypdomain) == 0) return NS_UNAVAIL; name = va_arg(ap, char *); pai = va_arg(ap, const struct addrinfo *); memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; + /* ipnodes.byname can hold both IPv4/v6 */ + r = yp_match(ypdomain, "ipnodes.byname", name, + (int)strlen(name), &ypbuf, &ypbuflen); + if (r == 0) { + ai = _yphostent(ypbuf, pai); + if (ai) { + cur->ai_next = ai; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + free(ypbuf); + } + + if (ai != NULL) { + struct sockaddr_in6 *sin6; + + switch (ai->ai_family) { + case AF_INET: + goto done; + case AF_INET6: + sin6 = (struct sockaddr_in6 *)ai->ai_addr; + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) + goto done; + break; + } + } + /* hosts.byname is only for IPv4 (Solaris8) */ - if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) { + if (pai->ai_family == AF_UNSPEC || pai->ai_family == AF_INET || + ((pai->ai_family == AF_INET6 && + (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED) && + (ai == NULL || (pai->ai_flags & AI_ALL) == AI_ALL))) { r = yp_match(ypdomain, "hosts.byname", name, (int)strlen(name), &ypbuf, &ypbuflen); if (r == 0) { struct addrinfo ai4; ai4 = *pai; - ai4.ai_family = AF_INET; + if (pai->ai_family == AF_UNSPEC) + ai4.ai_family = AF_INET; ai = _yphostent(ypbuf, &ai4); if (ai) { cur->ai_next = ai; while (cur && cur->ai_next) cur = cur->ai_next; } free(ypbuf); } } - /* ipnodes.byname can hold both IPv4/v6 */ - r = yp_match(ypdomain, "ipnodes.byname", name, - (int)strlen(name), &ypbuf, &ypbuflen); - if (r == 0) { - ai = _yphostent(ypbuf, pai); - if (ai) - cur->ai_next = ai; - free(ypbuf); - } - +done: if (sentinel.ai_next == NULL) { RES_SET_H_ERRNO(__res_state(), HOST_NOT_FOUND); return NS_NOTFOUND; } *((struct addrinfo **)rv) = sentinel.ai_next; return NS_SUCCESS; } #endif /* resolver logic */ /* * Formulate a normal query, send, and await answer. * Returned answer is placed in supplied buffer "answer". * Perform preliminary check of answer, returning success only * if no error is indicated and the answer count is nonzero. * Return the size of the response on success, -1 on error. * Error number is left in h_errno. * * Caller must parse answer and determine whether it answers the question. */ static int res_queryN(const char *name, struct res_target *target, res_state res) { u_char *buf; HEADER *hp; int n; u_int oflags; struct res_target *t; int rcode; int ancount; rcode = NOERROR; ancount = 0; buf = malloc(MAXPACKET); if (!buf) { RES_SET_H_ERRNO(res, NETDB_INTERNAL); return -1; } for (t = target; t; t = t->next) { int class, type; u_char *answer; int anslen; hp = (HEADER *)(void *)t->answer; /* make it easier... */ class = t->qclass; type = t->qtype; answer = t->answer; anslen = t->anslen; oflags = res->_flags; again: hp->rcode = NOERROR; /* default */ #ifdef DEBUG if (res->options & RES_DEBUG) printf(";; res_query(%s, %d, %d)\n", name, class, type); #endif n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL, buf, MAXPACKET); if (n > 0 && (res->_flags & RES_F_EDNS0ERR) == 0 && (res->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U) n = res_nopt(res, n, buf, MAXPACKET, anslen); if (n <= 0) { #ifdef DEBUG if (res->options & RES_DEBUG) printf(";; res_query: mkquery failed\n"); #endif free(buf); RES_SET_H_ERRNO(res, NO_RECOVERY); return (n); } n = res_nsend(res, buf, n, answer, anslen); if (n < 0) { /* * if the query choked with EDNS0, retry * without EDNS0 */ if ((res->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U && ((oflags ^ res->_flags) & RES_F_EDNS0ERR) != 0) { res->_flags |= RES_F_EDNS0ERR; if (res->options & RES_DEBUG) printf(";; res_nquery: retry without EDNS0\n"); goto again; } rcode = hp->rcode; /* record most recent error */ #ifdef DEBUG if (res->options & RES_DEBUG) printf(";; res_query: send error\n"); #endif continue; } if (n > anslen) hp->rcode = FORMERR; /* XXX not very informative */ if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { rcode = hp->rcode; /* record most recent error */ #ifdef DEBUG if (res->options & RES_DEBUG) printf(";; rcode = %u, ancount=%u\n", hp->rcode, ntohs(hp->ancount)); #endif continue; } ancount += ntohs(hp->ancount); t->n = n; } free(buf); if (ancount == 0) { switch (rcode) { case NXDOMAIN: RES_SET_H_ERRNO(res, HOST_NOT_FOUND); break; case SERVFAIL: RES_SET_H_ERRNO(res, TRY_AGAIN); break; case NOERROR: RES_SET_H_ERRNO(res, NO_DATA); break; case FORMERR: case NOTIMP: case REFUSED: default: RES_SET_H_ERRNO(res, NO_RECOVERY); break; } return (-1); } return (ancount); } /* * Formulate a normal query, send, and retrieve answer in supplied buffer. * Return the size of the response on success, -1 on error. * If enabled, implement search rules until answer or unrecoverable failure * is detected. Error code, if any, is left in h_errno. */ static int res_searchN(const char *name, struct res_target *target, res_state res) { const char *cp, * const *domain; HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/ u_int dots; int trailing_dot, ret, saved_herrno; int got_nodata = 0, got_servfail = 0, root_on_list = 0; int tried_as_is = 0; int searched = 0; char abuf[MAXDNAME]; errno = 0; RES_SET_H_ERRNO(res, HOST_NOT_FOUND); /* default, if we never query */ dots = 0; for (cp = name; *cp; cp++) dots += (*cp == '.'); trailing_dot = 0; if (cp > name && *--cp == '.') trailing_dot++; /* * if there aren't any dots, it could be a user-level alias */ if (!dots && (cp = res_hostalias(res, name, abuf, sizeof(abuf))) != NULL) return (res_queryN(cp, target, res)); /* * If there are enough dots in the name, let's just give it a * try 'as is'. The threshold can be set with the "ndots" option. * Also, query 'as is', if there is a trailing dot in the name. */ saved_herrno = -1; if (dots >= res->ndots || trailing_dot) { ret = res_querydomainN(name, NULL, target, res); if (ret > 0 || trailing_dot) return (ret); if (errno == ECONNREFUSED) { RES_SET_H_ERRNO(res, TRY_AGAIN); return (-1); } switch (res->res_h_errno) { case NO_DATA: case HOST_NOT_FOUND: break; case TRY_AGAIN: if (hp->rcode == SERVFAIL) break; /* FALLTHROUGH */ default: return (-1); } saved_herrno = res->res_h_errno; tried_as_is++; } /* * We do at least one level of search if * - there is no dot and RES_DEFNAME is set, or * - there is at least one dot, there is no trailing dot, * and RES_DNSRCH is set. */ if ((!dots && (res->options & RES_DEFNAMES)) || (dots && !trailing_dot && (res->options & RES_DNSRCH))) { int done = 0; for (domain = (const char * const *)res->dnsrch; *domain && !done; domain++) { searched = 1; if (domain[0][0] == '\0' || (domain[0][0] == '.' && domain[0][1] == '\0')) root_on_list++; if (root_on_list && tried_as_is) continue; ret = res_querydomainN(name, *domain, target, res); if (ret > 0) return (ret); /* * If no server present, give up. * If name isn't found in this domain, * keep trying higher domains in the search list * (if that's enabled). * On a NO_DATA error, keep trying, otherwise * a wildcard entry of another type could keep us * from finding this entry higher in the domain. * If we get some other error (negative answer or * server failure), then stop searching up, * but try the input name below in case it's * fully-qualified. */ if (errno == ECONNREFUSED) { RES_SET_H_ERRNO(res, TRY_AGAIN); return (-1); } switch (res->res_h_errno) { case NO_DATA: got_nodata++; /* FALLTHROUGH */ case HOST_NOT_FOUND: /* keep trying */ break; case TRY_AGAIN: got_servfail++; if (hp->rcode == SERVFAIL) { /* try next search element, if any */ break; } /* FALLTHROUGH */ default: /* anything else implies that we're done */ done++; } /* * if we got here for some reason other than DNSRCH, * we only wanted one iteration of the loop, so stop. */ if (!(res->options & RES_DNSRCH)) done++; } } switch (res->res_h_errno) { case NO_DATA: case HOST_NOT_FOUND: break; case TRY_AGAIN: if (hp->rcode == SERVFAIL) break; /* FALLTHROUGH */ default: goto giveup; } /* * If the query has not already been tried as is then try it * unless RES_NOTLDQUERY is set and there were no dots. */ if ((dots || !searched || !(res->options & RES_NOTLDQUERY)) && !(tried_as_is || root_on_list)) { ret = res_querydomainN(name, NULL, target, res); if (ret > 0) return (ret); } /* * if we got here, we didn't satisfy the search. * if we did an initial full query, return that query's h_errno * (note that we wouldn't be here if that query had succeeded). * else if we ever got a nodata, send that back as the reason. * else send back meaningless h_errno, that being the one from * the last DNSRCH we did. */ giveup: if (saved_herrno != -1) RES_SET_H_ERRNO(res, saved_herrno); else if (got_nodata) RES_SET_H_ERRNO(res, NO_DATA); else if (got_servfail) RES_SET_H_ERRNO(res, TRY_AGAIN); return (-1); } /* * Perform a call on res_query on the concatenation of name and domain, * removing a trailing dot from name if domain is NULL. */ static int res_querydomainN(const char *name, const char *domain, struct res_target *target, res_state res) { char nbuf[MAXDNAME]; const char *longname = nbuf; size_t n, d; #ifdef DEBUG if (res->options & RES_DEBUG) printf(";; res_querydomain(%s, %s)\n", name, domain?domain:""); #endif if (domain == NULL) { /* * Check for trailing '.'; * copy without '.' if present. */ n = strlen(name); if (n >= MAXDNAME) { RES_SET_H_ERRNO(res, NO_RECOVERY); return (-1); } if (n > 0 && name[--n] == '.') { strncpy(nbuf, name, n); nbuf[n] = '\0'; } else longname = name; } else { n = strlen(name); d = strlen(domain); if (n + d + 1 >= MAXDNAME) { RES_SET_H_ERRNO(res, NO_RECOVERY); return (-1); } snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); } return (res_queryN(longname, target, res)); } Index: user/alc/PQ_LAUNDRY/lib/libc =================================================================== --- user/alc/PQ_LAUNDRY/lib/libc (revision 292448) +++ user/alc/PQ_LAUNDRY/lib/libc (revision 292449) Property changes on: user/alc/PQ_LAUNDRY/lib/libc ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/lib/libc:r292390-292448 Index: user/alc/PQ_LAUNDRY/libexec/rtld-elf/rtld.c =================================================================== --- user/alc/PQ_LAUNDRY/libexec/rtld-elf/rtld.c (revision 292448) +++ user/alc/PQ_LAUNDRY/libexec/rtld-elf/rtld.c (revision 292449) @@ -1,5098 +1,5098 @@ /*- * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra. * Copyright 2003 Alexander Kabaev . * Copyright 2009-2012 Konstantin Belousov . * Copyright 2012 John Marino . * 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. * * $FreeBSD$ */ /* * Dynamic linker for ELF. * * John Polstra . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "debug.h" #include "rtld.h" #include "libmap.h" #include "paths.h" #include "rtld_tls.h" #include "rtld_printf.h" #include "notes.h" /* Types. */ typedef void (*func_ptr_type)(); typedef void * (*path_enum_proc) (const char *path, size_t len, void *arg); /* * Function declarations. */ static const char *basename(const char *); static void digest_dynamic1(Obj_Entry *, int, const Elf_Dyn **, const Elf_Dyn **, const Elf_Dyn **); static void digest_dynamic2(Obj_Entry *, const Elf_Dyn *, const Elf_Dyn *, const Elf_Dyn *); static void digest_dynamic(Obj_Entry *, int); static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *); static Obj_Entry *dlcheck(void *); static Obj_Entry *dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags, int mode, RtldLockState *lockstate); static Obj_Entry *do_load_object(int, const char *, char *, struct stat *, int); static int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *); static bool donelist_check(DoneList *, const Obj_Entry *); static void errmsg_restore(char *); static char *errmsg_save(void); static void *fill_search_info(const char *, size_t, void *); static char *find_library(const char *, const Obj_Entry *, int *); static const char *gethints(bool); static void init_dag(Obj_Entry *); static void init_pagesizes(Elf_Auxinfo **aux_info); static void init_rtld(caddr_t, Elf_Auxinfo **); static void initlist_add_neededs(Needed_Entry *, Objlist *); static void initlist_add_objects(Obj_Entry *, Obj_Entry **, Objlist *); static void linkmap_add(Obj_Entry *); static void linkmap_delete(Obj_Entry *); static void load_filtees(Obj_Entry *, int flags, RtldLockState *); static void unload_filtees(Obj_Entry *); static int load_needed_objects(Obj_Entry *, int); static int load_preload_objects(void); static Obj_Entry *load_object(const char *, int fd, const Obj_Entry *, int); static void map_stacks_exec(RtldLockState *); static Obj_Entry *obj_from_addr(const void *); static void objlist_call_fini(Objlist *, Obj_Entry *, RtldLockState *); static void objlist_call_init(Objlist *, RtldLockState *); static void objlist_clear(Objlist *); static Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *); static void objlist_init(Objlist *); static void objlist_push_head(Objlist *, Obj_Entry *); static void objlist_push_tail(Objlist *, Obj_Entry *); static void objlist_put_after(Objlist *, Obj_Entry *, Obj_Entry *); static void objlist_remove(Objlist *, Obj_Entry *); static int parse_libdir(const char *); static void *path_enumerate(const char *, path_enum_proc, void *); static int relocate_object_dag(Obj_Entry *root, bool bind_now, Obj_Entry *rtldobj, int flags, RtldLockState *lockstate); static int relocate_object(Obj_Entry *obj, bool bind_now, Obj_Entry *rtldobj, int flags, RtldLockState *lockstate); static int relocate_objects(Obj_Entry *, bool, Obj_Entry *, int, RtldLockState *); static int resolve_objects_ifunc(Obj_Entry *first, bool bind_now, int flags, RtldLockState *lockstate); static int rtld_dirname(const char *, char *); static int rtld_dirname_abs(const char *, char *); static void *rtld_dlopen(const char *name, int fd, int mode); static void rtld_exit(void); static char *search_library_path(const char *, const char *); static char *search_library_pathfds(const char *, const char *, int *); static const void **get_program_var_addr(const char *, RtldLockState *); static void set_program_var(const char *, const void *); static int symlook_default(SymLook *, const Obj_Entry *refobj); static int symlook_global(SymLook *, DoneList *); static void symlook_init_from_req(SymLook *, const SymLook *); static int symlook_list(SymLook *, const Objlist *, DoneList *); static int symlook_needed(SymLook *, const Needed_Entry *, DoneList *); static int symlook_obj1_sysv(SymLook *, const Obj_Entry *); static int symlook_obj1_gnu(SymLook *, const Obj_Entry *); static void trace_loaded_objects(Obj_Entry *); static void unlink_object(Obj_Entry *); static void unload_object(Obj_Entry *); static void unref_dag(Obj_Entry *); static void ref_dag(Obj_Entry *); static char *origin_subst_one(Obj_Entry *, char *, const char *, const char *, bool); static char *origin_subst(Obj_Entry *, char *); static bool obj_resolve_origin(Obj_Entry *obj); static void preinit_main(void); static int rtld_verify_versions(const Objlist *); static int rtld_verify_object_versions(Obj_Entry *); static void object_add_name(Obj_Entry *, const char *); static int object_match_name(const Obj_Entry *, const char *); static void ld_utrace_log(int, void *, void *, size_t, int, const char *); static void rtld_fill_dl_phdr_info(const Obj_Entry *obj, struct dl_phdr_info *phdr_info); static uint32_t gnu_hash(const char *); static bool matched_symbol(SymLook *, const Obj_Entry *, Sym_Match_Result *, const unsigned long); void r_debug_state(struct r_debug *, struct link_map *) __noinline __exported; void _r_debug_postinit(struct link_map *) __noinline __exported; int __sys_openat(int, const char *, int, ...); /* * Data declarations. */ static char *error_message; /* Message for dlerror(), or NULL */ struct r_debug r_debug __exported; /* for GDB; */ static bool libmap_disable; /* Disable libmap */ static bool ld_loadfltr; /* Immediate filters processing */ static char *libmap_override; /* Maps to use in addition to libmap.conf */ static bool trust; /* False for setuid and setgid programs */ static bool dangerous_ld_env; /* True if environment variables have been used to affect the libraries loaded */ static char *ld_bind_now; /* Environment variable for immediate binding */ static char *ld_debug; /* Environment variable for debugging */ static char *ld_library_path; /* Environment variable for search path */ static char *ld_library_dirs; /* Environment variable for library descriptors */ static char *ld_preload; /* Environment variable for libraries to load first */ static char *ld_elf_hints_path; /* Environment variable for alternative hints path */ static char *ld_tracing; /* Called from ldd to print libs */ static char *ld_utrace; /* Use utrace() to log events. */ static Obj_Entry *obj_list; /* Head of linked list of shared objects */ static Obj_Entry **obj_tail; /* Link field of last object in list */ static Obj_Entry *obj_main; /* The main program shared object */ static Obj_Entry obj_rtld; /* The dynamic linker shared object */ static unsigned int obj_count; /* Number of objects in obj_list */ static unsigned int obj_loads; /* Number of objects in obj_list */ static Objlist list_global = /* Objects dlopened with RTLD_GLOBAL */ STAILQ_HEAD_INITIALIZER(list_global); static Objlist list_main = /* Objects loaded at program startup */ STAILQ_HEAD_INITIALIZER(list_main); static Objlist list_fini = /* Objects needing fini() calls */ STAILQ_HEAD_INITIALIZER(list_fini); Elf_Sym sym_zero; /* For resolving undefined weak refs. */ #define GDB_STATE(s,m) r_debug.r_state = s; r_debug_state(&r_debug,m); extern Elf_Dyn _DYNAMIC; #pragma weak _DYNAMIC #ifndef RTLD_IS_DYNAMIC #define RTLD_IS_DYNAMIC() (&_DYNAMIC != NULL) #endif int dlclose(void *) __exported; char *dlerror(void) __exported; void *dlopen(const char *, int) __exported; void *fdlopen(int, int) __exported; void *dlsym(void *, const char *) __exported; dlfunc_t dlfunc(void *, const char *) __exported; void *dlvsym(void *, const char *, const char *) __exported; int dladdr(const void *, Dl_info *) __exported; void dllockinit(void *, void *(*)(void *), void (*)(void *), void (*)(void *), void (*)(void *), void (*)(void *), void (*)(void *)) __exported; int dlinfo(void *, int , void *) __exported; int dl_iterate_phdr(__dl_iterate_hdr_callback, void *) __exported; int _rtld_addr_phdr(const void *, struct dl_phdr_info *) __exported; int _rtld_get_stack_prot(void) __exported; int _rtld_is_dlopened(void *) __exported; void _rtld_error(const char *, ...) __exported; int npagesizes, osreldate; size_t *pagesizes; long __stack_chk_guard[8] = {0, 0, 0, 0, 0, 0, 0, 0}; static int stack_prot = PROT_READ | PROT_WRITE | RTLD_DEFAULT_STACK_EXEC; static int max_stack_flags; /* * Global declarations normally provided by crt1. The dynamic linker is * not built with crt1, so we have to provide them ourselves. */ char *__progname; char **environ; /* * Used to pass argc, argv to init functions. */ int main_argc; char **main_argv; /* * Globals to control TLS allocation. */ size_t tls_last_offset; /* Static TLS offset of last module */ size_t tls_last_size; /* Static TLS size of last module */ size_t tls_static_space; /* Static TLS space allocated */ size_t tls_static_max_align; int tls_dtv_generation = 1; /* Used to detect when dtv size changes */ int tls_max_index = 1; /* Largest module index allocated */ bool ld_library_path_rpath = false; /* * Globals for path names, and such */ -char *ld_path_elf_hints = _PATH_ELF_HINTS; +char *ld_elf_hints_default = _PATH_ELF_HINTS; char *ld_path_libmap_conf = _PATH_LIBMAP_CONF; char *ld_path_rtld = _PATH_RTLD; char *ld_standard_library_path = STANDARD_LIBRARY_PATH; char *ld_env_prefix = LD_; /* * Fill in a DoneList with an allocation large enough to hold all of * the currently-loaded objects. Keep this as a macro since it calls * alloca and we want that to occur within the scope of the caller. */ #define donelist_init(dlp) \ ((dlp)->objs = alloca(obj_count * sizeof (dlp)->objs[0]), \ assert((dlp)->objs != NULL), \ (dlp)->num_alloc = obj_count, \ (dlp)->num_used = 0) #define UTRACE_DLOPEN_START 1 #define UTRACE_DLOPEN_STOP 2 #define UTRACE_DLCLOSE_START 3 #define UTRACE_DLCLOSE_STOP 4 #define UTRACE_LOAD_OBJECT 5 #define UTRACE_UNLOAD_OBJECT 6 #define UTRACE_ADD_RUNDEP 7 #define UTRACE_PRELOAD_FINISHED 8 #define UTRACE_INIT_CALL 9 #define UTRACE_FINI_CALL 10 #define UTRACE_DLSYM_START 11 #define UTRACE_DLSYM_STOP 12 struct utrace_rtld { char sig[4]; /* 'RTLD' */ int event; void *handle; void *mapbase; /* Used for 'parent' and 'init/fini' */ size_t mapsize; int refcnt; /* Used for 'mode' */ char name[MAXPATHLEN]; }; #define LD_UTRACE(e, h, mb, ms, r, n) do { \ if (ld_utrace != NULL) \ ld_utrace_log(e, h, mb, ms, r, n); \ } while (0) static void ld_utrace_log(int event, void *handle, void *mapbase, size_t mapsize, int refcnt, const char *name) { struct utrace_rtld ut; ut.sig[0] = 'R'; ut.sig[1] = 'T'; ut.sig[2] = 'L'; ut.sig[3] = 'D'; ut.event = event; ut.handle = handle; ut.mapbase = mapbase; ut.mapsize = mapsize; ut.refcnt = refcnt; bzero(ut.name, sizeof(ut.name)); if (name) strlcpy(ut.name, name, sizeof(ut.name)); utrace(&ut, sizeof(ut)); } /* * Main entry point for dynamic linking. The first argument is the * stack pointer. The stack is expected to be laid out as described * in the SVR4 ABI specification, Intel 386 Processor Supplement. * Specifically, the stack pointer points to a word containing * ARGC. Following that in the stack is a null-terminated sequence * of pointers to argument strings. Then comes a null-terminated * sequence of pointers to environment strings. Finally, there is a * sequence of "auxiliary vector" entries. * * The second argument points to a place to store the dynamic linker's * exit procedure pointer and the third to a place to store the main * program's object. * * The return value is the main program's entry point. */ func_ptr_type _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) { Elf_Auxinfo *aux_info[AT_COUNT]; int i; int argc; char **argv; char **env; Elf_Auxinfo *aux; Elf_Auxinfo *auxp; const char *argv0; Objlist_Entry *entry; Obj_Entry *obj; Obj_Entry **preload_tail; Obj_Entry *last_interposer; Objlist initlist; RtldLockState lockstate; char *library_path_rpath; int mib[2]; size_t len; /* * On entry, the dynamic linker itself has not been relocated yet. * Be very careful not to reference any global data until after * init_rtld has returned. It is OK to reference file-scope statics * and string constants, and to call static and global functions. */ /* Find the auxiliary vector on the stack. */ argc = *sp++; argv = (char **) sp; sp += argc + 1; /* Skip over arguments and NULL terminator */ env = (char **) sp; while (*sp++ != 0) /* Skip over environment, and NULL terminator */ ; aux = (Elf_Auxinfo *) sp; /* Digest the auxiliary vector. */ for (i = 0; i < AT_COUNT; i++) aux_info[i] = NULL; for (auxp = aux; auxp->a_type != AT_NULL; auxp++) { if (auxp->a_type < AT_COUNT) aux_info[auxp->a_type] = auxp; } /* Initialize and relocate ourselves. */ assert(aux_info[AT_BASE] != NULL); init_rtld((caddr_t) aux_info[AT_BASE]->a_un.a_ptr, aux_info); __progname = obj_rtld.path; argv0 = argv[0] != NULL ? argv[0] : "(null)"; environ = env; main_argc = argc; main_argv = argv; if (aux_info[AT_CANARY] != NULL && aux_info[AT_CANARY]->a_un.a_ptr != NULL) { i = aux_info[AT_CANARYLEN]->a_un.a_val; if (i > sizeof(__stack_chk_guard)) i = sizeof(__stack_chk_guard); memcpy(__stack_chk_guard, aux_info[AT_CANARY]->a_un.a_ptr, i); } else { mib[0] = CTL_KERN; mib[1] = KERN_ARND; len = sizeof(__stack_chk_guard); if (sysctl(mib, 2, __stack_chk_guard, &len, NULL, 0) == -1 || len != sizeof(__stack_chk_guard)) { /* If sysctl was unsuccessful, use the "terminator canary". */ ((unsigned char *)(void *)__stack_chk_guard)[0] = 0; ((unsigned char *)(void *)__stack_chk_guard)[1] = 0; ((unsigned char *)(void *)__stack_chk_guard)[2] = '\n'; ((unsigned char *)(void *)__stack_chk_guard)[3] = 255; } } trust = !issetugid(); ld_bind_now = getenv(LD_ "BIND_NOW"); /* * If the process is tainted, then we un-set the dangerous environment * variables. The process will be marked as tainted until setuid(2) * is called. If any child process calls setuid(2) we do not want any * future processes to honor the potentially un-safe variables. */ if (!trust) { if (unsetenv(LD_ "PRELOAD") || unsetenv(LD_ "LIBMAP") || unsetenv(LD_ "LIBRARY_PATH") || unsetenv(LD_ "LIBRARY_PATH_FDS") || unsetenv(LD_ "LIBMAP_DISABLE") || unsetenv(LD_ "DEBUG") || unsetenv(LD_ "ELF_HINTS_PATH") || unsetenv(LD_ "LOADFLTR") || unsetenv(LD_ "LIBRARY_PATH_RPATH")) { _rtld_error("environment corrupt; aborting"); rtld_die(); } } ld_debug = getenv(LD_ "DEBUG"); libmap_disable = getenv(LD_ "LIBMAP_DISABLE") != NULL; libmap_override = getenv(LD_ "LIBMAP"); ld_library_path = getenv(LD_ "LIBRARY_PATH"); ld_library_dirs = getenv(LD_ "LIBRARY_PATH_FDS"); ld_preload = getenv(LD_ "PRELOAD"); ld_elf_hints_path = getenv(LD_ "ELF_HINTS_PATH"); ld_loadfltr = getenv(LD_ "LOADFLTR") != NULL; library_path_rpath = getenv(LD_ "LIBRARY_PATH_RPATH"); if (library_path_rpath != NULL) { if (library_path_rpath[0] == 'y' || library_path_rpath[0] == 'Y' || library_path_rpath[0] == '1') ld_library_path_rpath = true; else ld_library_path_rpath = false; } dangerous_ld_env = libmap_disable || (libmap_override != NULL) || (ld_library_path != NULL) || (ld_preload != NULL) || (ld_elf_hints_path != NULL) || ld_loadfltr; ld_tracing = getenv(LD_ "TRACE_LOADED_OBJECTS"); ld_utrace = getenv(LD_ "UTRACE"); if ((ld_elf_hints_path == NULL) || strlen(ld_elf_hints_path) == 0) - ld_elf_hints_path = ld_path_elf_hints; + ld_elf_hints_path = ld_elf_hints_default; if (ld_debug != NULL && *ld_debug != '\0') debug = 1; dbg("%s is initialized, base address = %p", __progname, (caddr_t) aux_info[AT_BASE]->a_un.a_ptr); dbg("RTLD dynamic = %p", obj_rtld.dynamic); dbg("RTLD pltgot = %p", obj_rtld.pltgot); dbg("initializing thread locks"); lockdflt_init(); /* * Load the main program, or process its program header if it is * already loaded. */ if (aux_info[AT_EXECFD] != NULL) { /* Load the main program. */ int fd = aux_info[AT_EXECFD]->a_un.a_val; dbg("loading main program"); obj_main = map_object(fd, argv0, NULL); close(fd); if (obj_main == NULL) rtld_die(); max_stack_flags = obj->stack_flags; } else { /* Main program already loaded. */ const Elf_Phdr *phdr; int phnum; caddr_t entry; dbg("processing main program's program header"); assert(aux_info[AT_PHDR] != NULL); phdr = (const Elf_Phdr *) aux_info[AT_PHDR]->a_un.a_ptr; assert(aux_info[AT_PHNUM] != NULL); phnum = aux_info[AT_PHNUM]->a_un.a_val; assert(aux_info[AT_PHENT] != NULL); assert(aux_info[AT_PHENT]->a_un.a_val == sizeof(Elf_Phdr)); assert(aux_info[AT_ENTRY] != NULL); entry = (caddr_t) aux_info[AT_ENTRY]->a_un.a_ptr; if ((obj_main = digest_phdr(phdr, phnum, entry, argv0)) == NULL) rtld_die(); } if (aux_info[AT_EXECPATH] != 0) { char *kexecpath; char buf[MAXPATHLEN]; kexecpath = aux_info[AT_EXECPATH]->a_un.a_ptr; dbg("AT_EXECPATH %p %s", kexecpath, kexecpath); if (kexecpath[0] == '/') obj_main->path = kexecpath; else if (getcwd(buf, sizeof(buf)) == NULL || strlcat(buf, "/", sizeof(buf)) >= sizeof(buf) || strlcat(buf, kexecpath, sizeof(buf)) >= sizeof(buf)) obj_main->path = xstrdup(argv0); else obj_main->path = xstrdup(buf); } else { dbg("No AT_EXECPATH"); obj_main->path = xstrdup(argv0); } dbg("obj_main path %s", obj_main->path); obj_main->mainprog = true; if (aux_info[AT_STACKPROT] != NULL && aux_info[AT_STACKPROT]->a_un.a_val != 0) stack_prot = aux_info[AT_STACKPROT]->a_un.a_val; #ifndef COMPAT_32BIT /* * Get the actual dynamic linker pathname from the executable if * possible. (It should always be possible.) That ensures that * gdb will find the right dynamic linker even if a non-standard * one is being used. */ if (obj_main->interp != NULL && strcmp(obj_main->interp, obj_rtld.path) != 0) { free(obj_rtld.path); obj_rtld.path = xstrdup(obj_main->interp); __progname = obj_rtld.path; } #endif digest_dynamic(obj_main, 0); dbg("%s valid_hash_sysv %d valid_hash_gnu %d dynsymcount %d", obj_main->path, obj_main->valid_hash_sysv, obj_main->valid_hash_gnu, obj_main->dynsymcount); linkmap_add(obj_main); linkmap_add(&obj_rtld); /* Link the main program into the list of objects. */ *obj_tail = obj_main; obj_tail = &obj_main->next; obj_count++; obj_loads++; /* Initialize a fake symbol for resolving undefined weak references. */ sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE); sym_zero.st_shndx = SHN_UNDEF; sym_zero.st_value = -(uintptr_t)obj_main->relocbase; if (!libmap_disable) libmap_disable = (bool)lm_init(libmap_override); dbg("loading LD_PRELOAD libraries"); if (load_preload_objects() == -1) rtld_die(); preload_tail = obj_tail; dbg("loading needed objects"); if (load_needed_objects(obj_main, 0) == -1) rtld_die(); /* Make a list of all objects loaded at startup. */ last_interposer = obj_main; for (obj = obj_list; obj != NULL; obj = obj->next) { if (obj->z_interpose && obj != obj_main) { objlist_put_after(&list_main, last_interposer, obj); last_interposer = obj; } else { objlist_push_tail(&list_main, obj); } obj->refcount++; } dbg("checking for required versions"); if (rtld_verify_versions(&list_main) == -1 && !ld_tracing) rtld_die(); if (ld_tracing) { /* We're done */ trace_loaded_objects(obj_main); exit(0); } if (getenv(LD_ "DUMP_REL_PRE") != NULL) { dump_relocations(obj_main); exit (0); } /* * Processing tls relocations requires having the tls offsets * initialized. Prepare offsets before starting initial * relocation processing. */ dbg("initializing initial thread local storage offsets"); STAILQ_FOREACH(entry, &list_main, link) { /* * Allocate all the initial objects out of the static TLS * block even if they didn't ask for it. */ allocate_tls_offset(entry->obj); } if (relocate_objects(obj_main, ld_bind_now != NULL && *ld_bind_now != '\0', &obj_rtld, SYMLOOK_EARLY, NULL) == -1) rtld_die(); dbg("doing copy relocations"); if (do_copy_relocations(obj_main) == -1) rtld_die(); if (getenv(LD_ "DUMP_REL_POST") != NULL) { dump_relocations(obj_main); exit (0); } /* * Setup TLS for main thread. This must be done after the * relocations are processed, since tls initialization section * might be the subject for relocations. */ dbg("initializing initial thread local storage"); allocate_initial_tls(obj_list); dbg("initializing key program variables"); set_program_var("__progname", argv[0] != NULL ? basename(argv[0]) : ""); set_program_var("environ", env); set_program_var("__elf_aux_vector", aux); /* Make a list of init functions to call. */ objlist_init(&initlist); initlist_add_objects(obj_list, preload_tail, &initlist); r_debug_state(NULL, &obj_main->linkmap); /* say hello to gdb! */ map_stacks_exec(NULL); dbg("resolving ifuncs"); if (resolve_objects_ifunc(obj_main, ld_bind_now != NULL && *ld_bind_now != '\0', SYMLOOK_EARLY, NULL) == -1) rtld_die(); if (!obj_main->crt_no_init) { /* * Make sure we don't call the main program's init and fini * functions for binaries linked with old crt1 which calls * _init itself. */ obj_main->init = obj_main->fini = (Elf_Addr)NULL; obj_main->preinit_array = obj_main->init_array = obj_main->fini_array = (Elf_Addr)NULL; } wlock_acquire(rtld_bind_lock, &lockstate); if (obj_main->crt_no_init) preinit_main(); objlist_call_init(&initlist, &lockstate); _r_debug_postinit(&obj_main->linkmap); objlist_clear(&initlist); dbg("loading filtees"); for (obj = obj_list->next; obj != NULL; obj = obj->next) { if (ld_loadfltr || obj->z_loadfltr) load_filtees(obj, 0, &lockstate); } lock_release(rtld_bind_lock, &lockstate); dbg("transferring control to program entry point = %p", obj_main->entry); /* Return the exit procedure and the program entry point. */ *exit_proc = rtld_exit; *objp = obj_main; return (func_ptr_type) obj_main->entry; } void * rtld_resolve_ifunc(const Obj_Entry *obj, const Elf_Sym *def) { void *ptr; Elf_Addr target; ptr = (void *)make_function_pointer(def, obj); target = ((Elf_Addr (*)(void))ptr)(); return ((void *)target); } Elf_Addr _rtld_bind(Obj_Entry *obj, Elf_Size reloff) { const Elf_Rel *rel; const Elf_Sym *def; const Obj_Entry *defobj; Elf_Addr *where; Elf_Addr target; RtldLockState lockstate; rlock_acquire(rtld_bind_lock, &lockstate); if (sigsetjmp(lockstate.env, 0) != 0) lock_upgrade(rtld_bind_lock, &lockstate); if (obj->pltrel) rel = (const Elf_Rel *) ((caddr_t) obj->pltrel + reloff); else rel = (const Elf_Rel *) ((caddr_t) obj->pltrela + reloff); where = (Elf_Addr *) (obj->relocbase + rel->r_offset); def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL, &lockstate); if (def == NULL) rtld_die(); if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) target = (Elf_Addr)rtld_resolve_ifunc(defobj, def); else target = (Elf_Addr)(defobj->relocbase + def->st_value); dbg("\"%s\" in \"%s\" ==> %p in \"%s\"", defobj->strtab + def->st_name, basename(obj->path), (void *)target, basename(defobj->path)); /* * Write the new contents for the jmpslot. Note that depending on * architecture, the value which we need to return back to the * lazy binding trampoline may or may not be the target * address. The value returned from reloc_jmpslot() is the value * that the trampoline needs. */ target = reloc_jmpslot(where, target, defobj, obj, rel); lock_release(rtld_bind_lock, &lockstate); return target; } /* * Error reporting function. Use it like printf. If formats the message * into a buffer, and sets things up so that the next call to dlerror() * will return the message. */ void _rtld_error(const char *fmt, ...) { static char buf[512]; va_list ap; va_start(ap, fmt); rtld_vsnprintf(buf, sizeof buf, fmt, ap); error_message = buf; va_end(ap); } /* * Return a dynamically-allocated copy of the current error message, if any. */ static char * errmsg_save(void) { return error_message == NULL ? NULL : xstrdup(error_message); } /* * Restore the current error message from a copy which was previously saved * by errmsg_save(). The copy is freed. */ static void errmsg_restore(char *saved_msg) { if (saved_msg == NULL) error_message = NULL; else { _rtld_error("%s", saved_msg); free(saved_msg); } } static const char * basename(const char *name) { const char *p = strrchr(name, '/'); return p != NULL ? p + 1 : name; } static struct utsname uts; static char * origin_subst_one(Obj_Entry *obj, char *real, const char *kw, const char *subst, bool may_free) { char *p, *p1, *res, *resp; int subst_len, kw_len, subst_count, old_len, new_len; kw_len = strlen(kw); /* * First, count the number of the keyword occurences, to * preallocate the final string. */ for (p = real, subst_count = 0;; p = p1 + kw_len, subst_count++) { p1 = strstr(p, kw); if (p1 == NULL) break; } /* * If the keyword is not found, just return. * * Return non-substituted string if resolution failed. We * cannot do anything more reasonable, the failure mode of the * caller is unresolved library anyway. */ if (subst_count == 0 || (obj != NULL && !obj_resolve_origin(obj))) return (may_free ? real : xstrdup(real)); if (obj != NULL) subst = obj->origin_path; /* * There is indeed something to substitute. Calculate the * length of the resulting string, and allocate it. */ subst_len = strlen(subst); old_len = strlen(real); new_len = old_len + (subst_len - kw_len) * subst_count; res = xmalloc(new_len + 1); /* * Now, execute the substitution loop. */ for (p = real, resp = res, *resp = '\0';;) { p1 = strstr(p, kw); if (p1 != NULL) { /* Copy the prefix before keyword. */ memcpy(resp, p, p1 - p); resp += p1 - p; /* Keyword replacement. */ memcpy(resp, subst, subst_len); resp += subst_len; *resp = '\0'; p = p1 + kw_len; } else break; } /* Copy to the end of string and finish. */ strcat(resp, p); if (may_free) free(real); return (res); } static char * origin_subst(Obj_Entry *obj, char *real) { char *res1, *res2, *res3, *res4; if (obj == NULL || !trust) return (xstrdup(real)); if (uts.sysname[0] == '\0') { if (uname(&uts) != 0) { _rtld_error("utsname failed: %d", errno); return (NULL); } } res1 = origin_subst_one(obj, real, "$ORIGIN", NULL, false); res2 = origin_subst_one(NULL, res1, "$OSNAME", uts.sysname, true); res3 = origin_subst_one(NULL, res2, "$OSREL", uts.release, true); res4 = origin_subst_one(NULL, res3, "$PLATFORM", uts.machine, true); return (res4); } void rtld_die(void) { const char *msg = dlerror(); if (msg == NULL) msg = "Fatal error"; rtld_fdputstr(STDERR_FILENO, msg); rtld_fdputchar(STDERR_FILENO, '\n'); _exit(1); } /* * Process a shared object's DYNAMIC section, and save the important * information in its Obj_Entry structure. */ static void digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath, const Elf_Dyn **dyn_soname, const Elf_Dyn **dyn_runpath) { const Elf_Dyn *dynp; Needed_Entry **needed_tail = &obj->needed; Needed_Entry **needed_filtees_tail = &obj->needed_filtees; Needed_Entry **needed_aux_filtees_tail = &obj->needed_aux_filtees; const Elf_Hashelt *hashtab; const Elf32_Word *hashval; Elf32_Word bkt, nmaskwords; int bloom_size32; int plttype = DT_REL; *dyn_rpath = NULL; *dyn_soname = NULL; *dyn_runpath = NULL; obj->bind_now = false; for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; dynp++) { switch (dynp->d_tag) { case DT_REL: obj->rel = (const Elf_Rel *) (obj->relocbase + dynp->d_un.d_ptr); break; case DT_RELSZ: obj->relsize = dynp->d_un.d_val; break; case DT_RELENT: assert(dynp->d_un.d_val == sizeof(Elf_Rel)); break; case DT_JMPREL: obj->pltrel = (const Elf_Rel *) (obj->relocbase + dynp->d_un.d_ptr); break; case DT_PLTRELSZ: obj->pltrelsize = dynp->d_un.d_val; break; case DT_RELA: obj->rela = (const Elf_Rela *) (obj->relocbase + dynp->d_un.d_ptr); break; case DT_RELASZ: obj->relasize = dynp->d_un.d_val; break; case DT_RELAENT: assert(dynp->d_un.d_val == sizeof(Elf_Rela)); break; case DT_PLTREL: plttype = dynp->d_un.d_val; assert(dynp->d_un.d_val == DT_REL || plttype == DT_RELA); break; case DT_SYMTAB: obj->symtab = (const Elf_Sym *) (obj->relocbase + dynp->d_un.d_ptr); break; case DT_SYMENT: assert(dynp->d_un.d_val == sizeof(Elf_Sym)); break; case DT_STRTAB: obj->strtab = (const char *) (obj->relocbase + dynp->d_un.d_ptr); break; case DT_STRSZ: obj->strsize = dynp->d_un.d_val; break; case DT_VERNEED: obj->verneed = (const Elf_Verneed *) (obj->relocbase + dynp->d_un.d_val); break; case DT_VERNEEDNUM: obj->verneednum = dynp->d_un.d_val; break; case DT_VERDEF: obj->verdef = (const Elf_Verdef *) (obj->relocbase + dynp->d_un.d_val); break; case DT_VERDEFNUM: obj->verdefnum = dynp->d_un.d_val; break; case DT_VERSYM: obj->versyms = (const Elf_Versym *)(obj->relocbase + dynp->d_un.d_val); break; case DT_HASH: { hashtab = (const Elf_Hashelt *)(obj->relocbase + dynp->d_un.d_ptr); obj->nbuckets = hashtab[0]; obj->nchains = hashtab[1]; obj->buckets = hashtab + 2; obj->chains = obj->buckets + obj->nbuckets; obj->valid_hash_sysv = obj->nbuckets > 0 && obj->nchains > 0 && obj->buckets != NULL; } break; case DT_GNU_HASH: { hashtab = (const Elf_Hashelt *)(obj->relocbase + dynp->d_un.d_ptr); obj->nbuckets_gnu = hashtab[0]; obj->symndx_gnu = hashtab[1]; nmaskwords = hashtab[2]; bloom_size32 = (__ELF_WORD_SIZE / 32) * nmaskwords; obj->maskwords_bm_gnu = nmaskwords - 1; obj->shift2_gnu = hashtab[3]; obj->bloom_gnu = (Elf_Addr *) (hashtab + 4); obj->buckets_gnu = hashtab + 4 + bloom_size32; obj->chain_zero_gnu = obj->buckets_gnu + obj->nbuckets_gnu - obj->symndx_gnu; /* Number of bitmask words is required to be power of 2 */ obj->valid_hash_gnu = powerof2(nmaskwords) && obj->nbuckets_gnu > 0 && obj->buckets_gnu != NULL; } break; case DT_NEEDED: if (!obj->rtld) { Needed_Entry *nep = NEW(Needed_Entry); nep->name = dynp->d_un.d_val; nep->obj = NULL; nep->next = NULL; *needed_tail = nep; needed_tail = &nep->next; } break; case DT_FILTER: if (!obj->rtld) { Needed_Entry *nep = NEW(Needed_Entry); nep->name = dynp->d_un.d_val; nep->obj = NULL; nep->next = NULL; *needed_filtees_tail = nep; needed_filtees_tail = &nep->next; } break; case DT_AUXILIARY: if (!obj->rtld) { Needed_Entry *nep = NEW(Needed_Entry); nep->name = dynp->d_un.d_val; nep->obj = NULL; nep->next = NULL; *needed_aux_filtees_tail = nep; needed_aux_filtees_tail = &nep->next; } break; case DT_PLTGOT: obj->pltgot = (Elf_Addr *) (obj->relocbase + dynp->d_un.d_ptr); break; case DT_TEXTREL: obj->textrel = true; break; case DT_SYMBOLIC: obj->symbolic = true; break; case DT_RPATH: /* * We have to wait until later to process this, because we * might not have gotten the address of the string table yet. */ *dyn_rpath = dynp; break; case DT_SONAME: *dyn_soname = dynp; break; case DT_RUNPATH: *dyn_runpath = dynp; break; case DT_INIT: obj->init = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr); break; case DT_PREINIT_ARRAY: obj->preinit_array = (Elf_Addr)(obj->relocbase + dynp->d_un.d_ptr); break; case DT_PREINIT_ARRAYSZ: obj->preinit_array_num = dynp->d_un.d_val / sizeof(Elf_Addr); break; case DT_INIT_ARRAY: obj->init_array = (Elf_Addr)(obj->relocbase + dynp->d_un.d_ptr); break; case DT_INIT_ARRAYSZ: obj->init_array_num = dynp->d_un.d_val / sizeof(Elf_Addr); break; case DT_FINI: obj->fini = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr); break; case DT_FINI_ARRAY: obj->fini_array = (Elf_Addr)(obj->relocbase + dynp->d_un.d_ptr); break; case DT_FINI_ARRAYSZ: obj->fini_array_num = dynp->d_un.d_val / sizeof(Elf_Addr); break; /* * Don't process DT_DEBUG on MIPS as the dynamic section * is mapped read-only. DT_MIPS_RLD_MAP is used instead. */ #ifndef __mips__ case DT_DEBUG: /* XXX - not implemented yet */ if (!early) dbg("Filling in DT_DEBUG entry"); ((Elf_Dyn*)dynp)->d_un.d_ptr = (Elf_Addr) &r_debug; break; #endif case DT_FLAGS: if (dynp->d_un.d_val & DF_ORIGIN) obj->z_origin = true; if (dynp->d_un.d_val & DF_SYMBOLIC) obj->symbolic = true; if (dynp->d_un.d_val & DF_TEXTREL) obj->textrel = true; if (dynp->d_un.d_val & DF_BIND_NOW) obj->bind_now = true; /*if (dynp->d_un.d_val & DF_STATIC_TLS) ;*/ break; #ifdef __mips__ case DT_MIPS_LOCAL_GOTNO: obj->local_gotno = dynp->d_un.d_val; break; case DT_MIPS_SYMTABNO: obj->symtabno = dynp->d_un.d_val; break; case DT_MIPS_GOTSYM: obj->gotsym = dynp->d_un.d_val; break; case DT_MIPS_RLD_MAP: *((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr) &r_debug; break; #endif #ifdef __powerpc64__ case DT_PPC64_GLINK: obj->glink = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr); break; #endif case DT_FLAGS_1: if (dynp->d_un.d_val & DF_1_NOOPEN) obj->z_noopen = true; if (dynp->d_un.d_val & DF_1_ORIGIN) obj->z_origin = true; if (dynp->d_un.d_val & DF_1_GLOBAL) obj->z_global = true; if (dynp->d_un.d_val & DF_1_BIND_NOW) obj->bind_now = true; if (dynp->d_un.d_val & DF_1_NODELETE) obj->z_nodelete = true; if (dynp->d_un.d_val & DF_1_LOADFLTR) obj->z_loadfltr = true; if (dynp->d_un.d_val & DF_1_INTERPOSE) obj->z_interpose = true; if (dynp->d_un.d_val & DF_1_NODEFLIB) obj->z_nodeflib = true; break; default: if (!early) { dbg("Ignoring d_tag %ld = %#lx", (long)dynp->d_tag, (long)dynp->d_tag); } break; } } obj->traced = false; if (plttype == DT_RELA) { obj->pltrela = (const Elf_Rela *) obj->pltrel; obj->pltrel = NULL; obj->pltrelasize = obj->pltrelsize; obj->pltrelsize = 0; } /* Determine size of dynsym table (equal to nchains of sysv hash) */ if (obj->valid_hash_sysv) obj->dynsymcount = obj->nchains; else if (obj->valid_hash_gnu) { obj->dynsymcount = 0; for (bkt = 0; bkt < obj->nbuckets_gnu; bkt++) { if (obj->buckets_gnu[bkt] == 0) continue; hashval = &obj->chain_zero_gnu[obj->buckets_gnu[bkt]]; do obj->dynsymcount++; while ((*hashval++ & 1u) == 0); } obj->dynsymcount += obj->symndx_gnu; } } static bool obj_resolve_origin(Obj_Entry *obj) { if (obj->origin_path != NULL) return (true); obj->origin_path = xmalloc(PATH_MAX); return (rtld_dirname_abs(obj->path, obj->origin_path) != -1); } static void digest_dynamic2(Obj_Entry *obj, const Elf_Dyn *dyn_rpath, const Elf_Dyn *dyn_soname, const Elf_Dyn *dyn_runpath) { if (obj->z_origin && !obj_resolve_origin(obj)) rtld_die(); if (dyn_runpath != NULL) { obj->runpath = (char *)obj->strtab + dyn_runpath->d_un.d_val; obj->runpath = origin_subst(obj, obj->runpath); } else if (dyn_rpath != NULL) { obj->rpath = (char *)obj->strtab + dyn_rpath->d_un.d_val; obj->rpath = origin_subst(obj, obj->rpath); } if (dyn_soname != NULL) object_add_name(obj, obj->strtab + dyn_soname->d_un.d_val); } static void digest_dynamic(Obj_Entry *obj, int early) { const Elf_Dyn *dyn_rpath; const Elf_Dyn *dyn_soname; const Elf_Dyn *dyn_runpath; digest_dynamic1(obj, early, &dyn_rpath, &dyn_soname, &dyn_runpath); digest_dynamic2(obj, dyn_rpath, dyn_soname, dyn_runpath); } /* * Process a shared object's program header. This is used only for the * main program, when the kernel has already loaded the main program * into memory before calling the dynamic linker. It creates and * returns an Obj_Entry structure. */ static Obj_Entry * digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path) { Obj_Entry *obj; const Elf_Phdr *phlimit = phdr + phnum; const Elf_Phdr *ph; Elf_Addr note_start, note_end; int nsegs = 0; obj = obj_new(); for (ph = phdr; ph < phlimit; ph++) { if (ph->p_type != PT_PHDR) continue; obj->phdr = phdr; obj->phsize = ph->p_memsz; obj->relocbase = (caddr_t)phdr - ph->p_vaddr; break; } obj->stack_flags = PF_X | PF_R | PF_W; for (ph = phdr; ph < phlimit; ph++) { switch (ph->p_type) { case PT_INTERP: obj->interp = (const char *)(ph->p_vaddr + obj->relocbase); break; case PT_LOAD: if (nsegs == 0) { /* First load segment */ obj->vaddrbase = trunc_page(ph->p_vaddr); obj->mapbase = obj->vaddrbase + obj->relocbase; obj->textsize = round_page(ph->p_vaddr + ph->p_memsz) - obj->vaddrbase; } else { /* Last load segment */ obj->mapsize = round_page(ph->p_vaddr + ph->p_memsz) - obj->vaddrbase; } nsegs++; break; case PT_DYNAMIC: obj->dynamic = (const Elf_Dyn *)(ph->p_vaddr + obj->relocbase); break; case PT_TLS: obj->tlsindex = 1; obj->tlssize = ph->p_memsz; obj->tlsalign = ph->p_align; obj->tlsinitsize = ph->p_filesz; obj->tlsinit = (void*)(ph->p_vaddr + obj->relocbase); break; case PT_GNU_STACK: obj->stack_flags = ph->p_flags; break; case PT_GNU_RELRO: obj->relro_page = obj->relocbase + trunc_page(ph->p_vaddr); obj->relro_size = round_page(ph->p_memsz); break; case PT_NOTE: note_start = (Elf_Addr)obj->relocbase + ph->p_vaddr; note_end = note_start + ph->p_filesz; digest_notes(obj, note_start, note_end); break; } } if (nsegs < 1) { _rtld_error("%s: too few PT_LOAD segments", path); return NULL; } obj->entry = entry; return obj; } void digest_notes(Obj_Entry *obj, Elf_Addr note_start, Elf_Addr note_end) { const Elf_Note *note; const char *note_name; uintptr_t p; for (note = (const Elf_Note *)note_start; (Elf_Addr)note < note_end; note = (const Elf_Note *)((const char *)(note + 1) + roundup2(note->n_namesz, sizeof(Elf32_Addr)) + roundup2(note->n_descsz, sizeof(Elf32_Addr)))) { if (note->n_namesz != sizeof(NOTE_FREEBSD_VENDOR) || note->n_descsz != sizeof(int32_t)) continue; if (note->n_type != ABI_NOTETYPE && note->n_type != CRT_NOINIT_NOTETYPE) continue; note_name = (const char *)(note + 1); if (strncmp(NOTE_FREEBSD_VENDOR, note_name, sizeof(NOTE_FREEBSD_VENDOR)) != 0) continue; switch (note->n_type) { case ABI_NOTETYPE: /* FreeBSD osrel note */ p = (uintptr_t)(note + 1); p += roundup2(note->n_namesz, sizeof(Elf32_Addr)); obj->osrel = *(const int32_t *)(p); dbg("note osrel %d", obj->osrel); break; case CRT_NOINIT_NOTETYPE: /* FreeBSD 'crt does not call init' note */ obj->crt_no_init = true; dbg("note crt_no_init"); break; } } } static Obj_Entry * dlcheck(void *handle) { Obj_Entry *obj; for (obj = obj_list; obj != NULL; obj = obj->next) if (obj == (Obj_Entry *) handle) break; if (obj == NULL || obj->refcount == 0 || obj->dl_refcount == 0) { _rtld_error("Invalid shared object handle %p", handle); return NULL; } return obj; } /* * If the given object is already in the donelist, return true. Otherwise * add the object to the list and return false. */ static bool donelist_check(DoneList *dlp, const Obj_Entry *obj) { unsigned int i; for (i = 0; i < dlp->num_used; i++) if (dlp->objs[i] == obj) return true; /* * Our donelist allocation should always be sufficient. But if * our threads locking isn't working properly, more shared objects * could have been loaded since we allocated the list. That should * never happen, but we'll handle it properly just in case it does. */ if (dlp->num_used < dlp->num_alloc) dlp->objs[dlp->num_used++] = obj; return false; } /* * Hash function for symbol table lookup. Don't even think about changing * this. It is specified by the System V ABI. */ unsigned long elf_hash(const char *name) { const unsigned char *p = (const unsigned char *) name; unsigned long h = 0; unsigned long g; while (*p != '\0') { h = (h << 4) + *p++; if ((g = h & 0xf0000000) != 0) h ^= g >> 24; h &= ~g; } return h; } /* * The GNU hash function is the Daniel J. Bernstein hash clipped to 32 bits * unsigned in case it's implemented with a wider type. */ static uint32_t gnu_hash(const char *s) { uint32_t h; unsigned char c; h = 5381; for (c = *s; c != '\0'; c = *++s) h = h * 33 + c; return (h & 0xffffffff); } /* * Find the library with the given name, and return its full pathname. * The returned string is dynamically allocated. Generates an error * message and returns NULL if the library cannot be found. * * If the second argument is non-NULL, then it refers to an already- * loaded shared object, whose library search path will be searched. * * If a library is successfully located via LD_LIBRARY_PATH_FDS, its * descriptor (which is close-on-exec) will be passed out via the third * argument. * * The search order is: * DT_RPATH in the referencing file _unless_ DT_RUNPATH is present (1) * DT_RPATH of the main object if DSO without defined DT_RUNPATH (1) * LD_LIBRARY_PATH * DT_RUNPATH in the referencing file * ldconfig hints (if -z nodefaultlib, filter out default library directories * from list) * /lib:/usr/lib _unless_ the referencing file is linked with -z nodefaultlib * * (1) Handled in digest_dynamic2 - rpath left NULL if runpath defined. */ static char * find_library(const char *xname, const Obj_Entry *refobj, int *fdp) { char *pathname; char *name; bool nodeflib, objgiven; objgiven = refobj != NULL; if (strchr(xname, '/') != NULL) { /* Hard coded pathname */ if (xname[0] != '/' && !trust) { _rtld_error("Absolute pathname required for shared object \"%s\"", xname); return NULL; } return (origin_subst(__DECONST(Obj_Entry *, refobj), __DECONST(char *, xname))); } if (libmap_disable || !objgiven || (name = lm_find(refobj->path, xname)) == NULL) name = (char *)xname; dbg(" Searching for \"%s\"", name); /* * If refobj->rpath != NULL, then refobj->runpath is NULL. Fall * back to pre-conforming behaviour if user requested so with * LD_LIBRARY_PATH_RPATH environment variable and ignore -z * nodeflib. */ if (objgiven && refobj->rpath != NULL && ld_library_path_rpath) { if ((pathname = search_library_path(name, ld_library_path)) != NULL || (refobj != NULL && (pathname = search_library_path(name, refobj->rpath)) != NULL) || (pathname = search_library_pathfds(name, ld_library_dirs, fdp)) != NULL || (pathname = search_library_path(name, gethints(false))) != NULL || (pathname = search_library_path(name, ld_standard_library_path)) != NULL) return (pathname); } else { nodeflib = objgiven ? refobj->z_nodeflib : false; if ((objgiven && (pathname = search_library_path(name, refobj->rpath)) != NULL) || (objgiven && refobj->runpath == NULL && refobj != obj_main && (pathname = search_library_path(name, obj_main->rpath)) != NULL) || (pathname = search_library_path(name, ld_library_path)) != NULL || (objgiven && (pathname = search_library_path(name, refobj->runpath)) != NULL) || (pathname = search_library_pathfds(name, ld_library_dirs, fdp)) != NULL || (pathname = search_library_path(name, gethints(nodeflib))) != NULL || (objgiven && !nodeflib && (pathname = search_library_path(name, ld_standard_library_path)) != NULL)) return (pathname); } if (objgiven && refobj->path != NULL) { _rtld_error("Shared object \"%s\" not found, required by \"%s\"", name, basename(refobj->path)); } else { _rtld_error("Shared object \"%s\" not found", name); } return NULL; } /* * Given a symbol number in a referencing object, find the corresponding * definition of the symbol. Returns a pointer to the symbol, or NULL if * no definition was found. Returns a pointer to the Obj_Entry of the * defining object via the reference parameter DEFOBJ_OUT. */ const Elf_Sym * find_symdef(unsigned long symnum, const Obj_Entry *refobj, const Obj_Entry **defobj_out, int flags, SymCache *cache, RtldLockState *lockstate) { const Elf_Sym *ref; const Elf_Sym *def; const Obj_Entry *defobj; SymLook req; const char *name; int res; /* * If we have already found this symbol, get the information from * the cache. */ if (symnum >= refobj->dynsymcount) return NULL; /* Bad object */ if (cache != NULL && cache[symnum].sym != NULL) { *defobj_out = cache[symnum].obj; return cache[symnum].sym; } ref = refobj->symtab + symnum; name = refobj->strtab + ref->st_name; def = NULL; defobj = NULL; /* * We don't have to do a full scale lookup if the symbol is local. * We know it will bind to the instance in this load module; to * which we already have a pointer (ie ref). By not doing a lookup, * we not only improve performance, but it also avoids unresolvable * symbols when local symbols are not in the hash table. This has * been seen with the ia64 toolchain. */ if (ELF_ST_BIND(ref->st_info) != STB_LOCAL) { if (ELF_ST_TYPE(ref->st_info) == STT_SECTION) { _rtld_error("%s: Bogus symbol table entry %lu", refobj->path, symnum); } symlook_init(&req, name); req.flags = flags; req.ventry = fetch_ventry(refobj, symnum); req.lockstate = lockstate; res = symlook_default(&req, refobj); if (res == 0) { def = req.sym_out; defobj = req.defobj_out; } } else { def = ref; defobj = refobj; } /* * If we found no definition and the reference is weak, treat the * symbol as having the value zero. */ if (def == NULL && ELF_ST_BIND(ref->st_info) == STB_WEAK) { def = &sym_zero; defobj = obj_main; } if (def != NULL) { *defobj_out = defobj; /* Record the information in the cache to avoid subsequent lookups. */ if (cache != NULL) { cache[symnum].sym = def; cache[symnum].obj = defobj; } } else { if (refobj != &obj_rtld) _rtld_error("%s: Undefined symbol \"%s\"", refobj->path, name); } return def; } /* * Return the search path from the ldconfig hints file, reading it if * necessary. If nostdlib is true, then the default search paths are * not added to result. * * Returns NULL if there are problems with the hints file, * or if the search path there is empty. */ static const char * gethints(bool nostdlib) { static char *hints, *filtered_path; struct elfhints_hdr hdr; struct fill_search_info_args sargs, hargs; struct dl_serinfo smeta, hmeta, *SLPinfo, *hintinfo; struct dl_serpath *SLPpath, *hintpath; char *p; unsigned int SLPndx, hintndx, fndx, fcount; int fd; size_t flen; bool skip; /* First call, read the hints file */ if (hints == NULL) { /* Keep from trying again in case the hints file is bad. */ hints = ""; if ((fd = open(ld_elf_hints_path, O_RDONLY | O_CLOEXEC)) == -1) return (NULL); if (read(fd, &hdr, sizeof hdr) != sizeof hdr || hdr.magic != ELFHINTS_MAGIC || hdr.version != 1) { close(fd); return (NULL); } p = xmalloc(hdr.dirlistlen + 1); if (lseek(fd, hdr.strtab + hdr.dirlist, SEEK_SET) == -1 || read(fd, p, hdr.dirlistlen + 1) != (ssize_t)hdr.dirlistlen + 1) { free(p); close(fd); return (NULL); } hints = p; close(fd); } /* * If caller agreed to receive list which includes the default * paths, we are done. Otherwise, if we still did not * calculated filtered result, do it now. */ if (!nostdlib) return (hints[0] != '\0' ? hints : NULL); if (filtered_path != NULL) goto filt_ret; /* * Obtain the list of all configured search paths, and the * list of the default paths. * * First estimate the size of the results. */ smeta.dls_size = __offsetof(struct dl_serinfo, dls_serpath); smeta.dls_cnt = 0; hmeta.dls_size = __offsetof(struct dl_serinfo, dls_serpath); hmeta.dls_cnt = 0; sargs.request = RTLD_DI_SERINFOSIZE; sargs.serinfo = &smeta; hargs.request = RTLD_DI_SERINFOSIZE; hargs.serinfo = &hmeta; path_enumerate(ld_standard_library_path, fill_search_info, &sargs); path_enumerate(p, fill_search_info, &hargs); SLPinfo = xmalloc(smeta.dls_size); hintinfo = xmalloc(hmeta.dls_size); /* * Next fetch both sets of paths. */ sargs.request = RTLD_DI_SERINFO; sargs.serinfo = SLPinfo; sargs.serpath = &SLPinfo->dls_serpath[0]; sargs.strspace = (char *)&SLPinfo->dls_serpath[smeta.dls_cnt]; hargs.request = RTLD_DI_SERINFO; hargs.serinfo = hintinfo; hargs.serpath = &hintinfo->dls_serpath[0]; hargs.strspace = (char *)&hintinfo->dls_serpath[hmeta.dls_cnt]; path_enumerate(ld_standard_library_path, fill_search_info, &sargs); path_enumerate(p, fill_search_info, &hargs); /* * Now calculate the difference between two sets, by excluding * standard paths from the full set. */ fndx = 0; fcount = 0; filtered_path = xmalloc(hdr.dirlistlen + 1); hintpath = &hintinfo->dls_serpath[0]; for (hintndx = 0; hintndx < hmeta.dls_cnt; hintndx++, hintpath++) { skip = false; SLPpath = &SLPinfo->dls_serpath[0]; /* * Check each standard path against current. */ for (SLPndx = 0; SLPndx < smeta.dls_cnt; SLPndx++, SLPpath++) { /* matched, skip the path */ if (!strcmp(hintpath->dls_name, SLPpath->dls_name)) { skip = true; break; } } if (skip) continue; /* * Not matched against any standard path, add the path * to result. Separate consequtive paths with ':'. */ if (fcount > 0) { filtered_path[fndx] = ':'; fndx++; } fcount++; flen = strlen(hintpath->dls_name); strncpy((filtered_path + fndx), hintpath->dls_name, flen); fndx += flen; } filtered_path[fndx] = '\0'; free(SLPinfo); free(hintinfo); filt_ret: return (filtered_path[0] != '\0' ? filtered_path : NULL); } static void init_dag(Obj_Entry *root) { const Needed_Entry *needed; const Objlist_Entry *elm; DoneList donelist; if (root->dag_inited) return; donelist_init(&donelist); /* Root object belongs to own DAG. */ objlist_push_tail(&root->dldags, root); objlist_push_tail(&root->dagmembers, root); donelist_check(&donelist, root); /* * Add dependencies of root object to DAG in breadth order * by exploiting the fact that each new object get added * to the tail of the dagmembers list. */ STAILQ_FOREACH(elm, &root->dagmembers, link) { for (needed = elm->obj->needed; needed != NULL; needed = needed->next) { if (needed->obj == NULL || donelist_check(&donelist, needed->obj)) continue; objlist_push_tail(&needed->obj->dldags, root); objlist_push_tail(&root->dagmembers, needed->obj); } } root->dag_inited = true; } static void process_z(Obj_Entry *root) { const Objlist_Entry *elm; Obj_Entry *obj; /* * Walk over object DAG and process every dependent object * that is marked as DF_1_NODELETE or DF_1_GLOBAL. They need * to grow their own DAG. * * For DF_1_GLOBAL, DAG is required for symbol lookups in * symlook_global() to work. * * For DF_1_NODELETE, the DAG should have its reference upped. */ STAILQ_FOREACH(elm, &root->dagmembers, link) { obj = elm->obj; if (obj == NULL) continue; if (obj->z_nodelete && !obj->ref_nodel) { dbg("obj %s -z nodelete", obj->path); init_dag(obj); ref_dag(obj); obj->ref_nodel = true; } if (obj->z_global && objlist_find(&list_global, obj) == NULL) { dbg("obj %s -z global", obj->path); objlist_push_tail(&list_global, obj); init_dag(obj); } } } /* * Initialize the dynamic linker. The argument is the address at which * the dynamic linker has been mapped into memory. The primary task of * this function is to relocate the dynamic linker. */ static void init_rtld(caddr_t mapbase, Elf_Auxinfo **aux_info) { Obj_Entry objtmp; /* Temporary rtld object */ const Elf_Dyn *dyn_rpath; const Elf_Dyn *dyn_soname; const Elf_Dyn *dyn_runpath; #ifdef RTLD_INIT_PAGESIZES_EARLY /* The page size is required by the dynamic memory allocator. */ init_pagesizes(aux_info); #endif /* * Conjure up an Obj_Entry structure for the dynamic linker. * * The "path" member can't be initialized yet because string constants * cannot yet be accessed. Below we will set it correctly. */ memset(&objtmp, 0, sizeof(objtmp)); objtmp.path = NULL; objtmp.rtld = true; objtmp.mapbase = mapbase; #ifdef PIC objtmp.relocbase = mapbase; #endif if (RTLD_IS_DYNAMIC()) { objtmp.dynamic = rtld_dynamic(&objtmp); digest_dynamic1(&objtmp, 1, &dyn_rpath, &dyn_soname, &dyn_runpath); assert(objtmp.needed == NULL); #if !defined(__mips__) /* MIPS has a bogus DT_TEXTREL. */ assert(!objtmp.textrel); #endif /* * Temporarily put the dynamic linker entry into the object list, so * that symbols can be found. */ relocate_objects(&objtmp, true, &objtmp, 0, NULL); } /* Initialize the object list. */ obj_tail = &obj_list; /* Now that non-local variables can be accesses, copy out obj_rtld. */ memcpy(&obj_rtld, &objtmp, sizeof(obj_rtld)); #ifndef RTLD_INIT_PAGESIZES_EARLY /* The page size is required by the dynamic memory allocator. */ init_pagesizes(aux_info); #endif if (aux_info[AT_OSRELDATE] != NULL) osreldate = aux_info[AT_OSRELDATE]->a_un.a_val; digest_dynamic2(&obj_rtld, dyn_rpath, dyn_soname, dyn_runpath); /* Replace the path with a dynamically allocated copy. */ obj_rtld.path = xstrdup(ld_path_rtld); r_debug.r_brk = r_debug_state; r_debug.r_state = RT_CONSISTENT; } /* * Retrieve the array of supported page sizes. The kernel provides the page * sizes in increasing order. */ static void init_pagesizes(Elf_Auxinfo **aux_info) { static size_t psa[MAXPAGESIZES]; int mib[2]; size_t len, size; if (aux_info[AT_PAGESIZES] != NULL && aux_info[AT_PAGESIZESLEN] != NULL) { size = aux_info[AT_PAGESIZESLEN]->a_un.a_val; pagesizes = aux_info[AT_PAGESIZES]->a_un.a_ptr; } else { len = 2; if (sysctlnametomib("hw.pagesizes", mib, &len) == 0) size = sizeof(psa); else { /* As a fallback, retrieve the base page size. */ size = sizeof(psa[0]); if (aux_info[AT_PAGESZ] != NULL) { psa[0] = aux_info[AT_PAGESZ]->a_un.a_val; goto psa_filled; } else { mib[0] = CTL_HW; mib[1] = HW_PAGESIZE; len = 2; } } if (sysctl(mib, len, psa, &size, NULL, 0) == -1) { _rtld_error("sysctl for hw.pagesize(s) failed"); rtld_die(); } psa_filled: pagesizes = psa; } npagesizes = size / sizeof(pagesizes[0]); /* Discard any invalid entries at the end of the array. */ while (npagesizes > 0 && pagesizes[npagesizes - 1] == 0) npagesizes--; } /* * Add the init functions from a needed object list (and its recursive * needed objects) to "list". This is not used directly; it is a helper * function for initlist_add_objects(). The write lock must be held * when this function is called. */ static void initlist_add_neededs(Needed_Entry *needed, Objlist *list) { /* Recursively process the successor needed objects. */ if (needed->next != NULL) initlist_add_neededs(needed->next, list); /* Process the current needed object. */ if (needed->obj != NULL) initlist_add_objects(needed->obj, &needed->obj->next, list); } /* * Scan all of the DAGs rooted in the range of objects from "obj" to * "tail" and add their init functions to "list". This recurses over * the DAGs and ensure the proper init ordering such that each object's * needed libraries are initialized before the object itself. At the * same time, this function adds the objects to the global finalization * list "list_fini" in the opposite order. The write lock must be * held when this function is called. */ static void initlist_add_objects(Obj_Entry *obj, Obj_Entry **tail, Objlist *list) { if (obj->init_scanned || obj->init_done) return; obj->init_scanned = true; /* Recursively process the successor objects. */ if (&obj->next != tail) initlist_add_objects(obj->next, tail, list); /* Recursively process the needed objects. */ if (obj->needed != NULL) initlist_add_neededs(obj->needed, list); if (obj->needed_filtees != NULL) initlist_add_neededs(obj->needed_filtees, list); if (obj->needed_aux_filtees != NULL) initlist_add_neededs(obj->needed_aux_filtees, list); /* Add the object to the init list. */ if (obj->preinit_array != (Elf_Addr)NULL || obj->init != (Elf_Addr)NULL || obj->init_array != (Elf_Addr)NULL) objlist_push_tail(list, obj); /* Add the object to the global fini list in the reverse order. */ if ((obj->fini != (Elf_Addr)NULL || obj->fini_array != (Elf_Addr)NULL) && !obj->on_fini_list) { objlist_push_head(&list_fini, obj); obj->on_fini_list = true; } } #ifndef FPTR_TARGET #define FPTR_TARGET(f) ((Elf_Addr) (f)) #endif static void free_needed_filtees(Needed_Entry *n) { Needed_Entry *needed, *needed1; for (needed = n; needed != NULL; needed = needed->next) { if (needed->obj != NULL) { dlclose(needed->obj); needed->obj = NULL; } } for (needed = n; needed != NULL; needed = needed1) { needed1 = needed->next; free(needed); } } static void unload_filtees(Obj_Entry *obj) { free_needed_filtees(obj->needed_filtees); obj->needed_filtees = NULL; free_needed_filtees(obj->needed_aux_filtees); obj->needed_aux_filtees = NULL; obj->filtees_loaded = false; } static void load_filtee1(Obj_Entry *obj, Needed_Entry *needed, int flags, RtldLockState *lockstate) { for (; needed != NULL; needed = needed->next) { needed->obj = dlopen_object(obj->strtab + needed->name, -1, obj, flags, ((ld_loadfltr || obj->z_loadfltr) ? RTLD_NOW : RTLD_LAZY) | RTLD_LOCAL, lockstate); } } static void load_filtees(Obj_Entry *obj, int flags, RtldLockState *lockstate) { lock_restart_for_upgrade(lockstate); if (!obj->filtees_loaded) { load_filtee1(obj, obj->needed_filtees, flags, lockstate); load_filtee1(obj, obj->needed_aux_filtees, flags, lockstate); obj->filtees_loaded = true; } } static int process_needed(Obj_Entry *obj, Needed_Entry *needed, int flags) { Obj_Entry *obj1; for (; needed != NULL; needed = needed->next) { obj1 = needed->obj = load_object(obj->strtab + needed->name, -1, obj, flags & ~RTLD_LO_NOLOAD); if (obj1 == NULL && !ld_tracing && (flags & RTLD_LO_FILTEES) == 0) return (-1); } return (0); } /* * Given a shared object, traverse its list of needed objects, and load * each of them. Returns 0 on success. Generates an error message and * returns -1 on failure. */ static int load_needed_objects(Obj_Entry *first, int flags) { Obj_Entry *obj; for (obj = first; obj != NULL; obj = obj->next) { if (process_needed(obj, obj->needed, flags) == -1) return (-1); } return (0); } static int load_preload_objects(void) { char *p = ld_preload; Obj_Entry *obj; static const char delim[] = " \t:;"; if (p == NULL) return 0; p += strspn(p, delim); while (*p != '\0') { size_t len = strcspn(p, delim); char savech; savech = p[len]; p[len] = '\0'; obj = load_object(p, -1, NULL, 0); if (obj == NULL) return -1; /* XXX - cleanup */ obj->z_interpose = true; p[len] = savech; p += len; p += strspn(p, delim); } LD_UTRACE(UTRACE_PRELOAD_FINISHED, NULL, NULL, 0, 0, NULL); return 0; } static const char * printable_path(const char *path) { return (path == NULL ? "" : path); } /* * Load a shared object into memory, if it is not already loaded. The * object may be specified by name or by user-supplied file descriptor * fd_u. In the later case, the fd_u descriptor is not closed, but its * duplicate is. * * Returns a pointer to the Obj_Entry for the object. Returns NULL * on failure. */ static Obj_Entry * load_object(const char *name, int fd_u, const Obj_Entry *refobj, int flags) { Obj_Entry *obj; int fd; struct stat sb; char *path; fd = -1; if (name != NULL) { for (obj = obj_list->next; obj != NULL; obj = obj->next) { if (object_match_name(obj, name)) return (obj); } path = find_library(name, refobj, &fd); if (path == NULL) return (NULL); } else path = NULL; if (fd >= 0) { /* * search_library_pathfds() opens a fresh file descriptor for the * library, so there is no need to dup(). */ } else if (fd_u == -1) { /* * If we didn't find a match by pathname, or the name is not * supplied, open the file and check again by device and inode. * This avoids false mismatches caused by multiple links or ".." * in pathnames. * * To avoid a race, we open the file and use fstat() rather than * using stat(). */ if ((fd = open(path, O_RDONLY | O_CLOEXEC | O_VERIFY)) == -1) { _rtld_error("Cannot open \"%s\"", path); free(path); return (NULL); } } else { fd = fcntl(fd_u, F_DUPFD_CLOEXEC, 0); if (fd == -1) { _rtld_error("Cannot dup fd"); free(path); return (NULL); } } if (fstat(fd, &sb) == -1) { _rtld_error("Cannot fstat \"%s\"", printable_path(path)); close(fd); free(path); return NULL; } for (obj = obj_list->next; obj != NULL; obj = obj->next) if (obj->ino == sb.st_ino && obj->dev == sb.st_dev) break; if (obj != NULL && name != NULL) { object_add_name(obj, name); free(path); close(fd); return obj; } if (flags & RTLD_LO_NOLOAD) { free(path); close(fd); return (NULL); } /* First use of this object, so we must map it in */ obj = do_load_object(fd, name, path, &sb, flags); if (obj == NULL) free(path); close(fd); return obj; } static Obj_Entry * do_load_object(int fd, const char *name, char *path, struct stat *sbp, int flags) { Obj_Entry *obj; struct statfs fs; /* * but first, make sure that environment variables haven't been * used to circumvent the noexec flag on a filesystem. */ if (dangerous_ld_env) { if (fstatfs(fd, &fs) != 0) { _rtld_error("Cannot fstatfs \"%s\"", printable_path(path)); return NULL; } if (fs.f_flags & MNT_NOEXEC) { _rtld_error("Cannot execute objects on %s\n", fs.f_mntonname); return NULL; } } dbg("loading \"%s\"", printable_path(path)); obj = map_object(fd, printable_path(path), sbp); if (obj == NULL) return NULL; /* * If DT_SONAME is present in the object, digest_dynamic2 already * added it to the object names. */ if (name != NULL) object_add_name(obj, name); obj->path = path; digest_dynamic(obj, 0); dbg("%s valid_hash_sysv %d valid_hash_gnu %d dynsymcount %d", obj->path, obj->valid_hash_sysv, obj->valid_hash_gnu, obj->dynsymcount); if (obj->z_noopen && (flags & (RTLD_LO_DLOPEN | RTLD_LO_TRACE)) == RTLD_LO_DLOPEN) { dbg("refusing to load non-loadable \"%s\"", obj->path); _rtld_error("Cannot dlopen non-loadable %s", obj->path); munmap(obj->mapbase, obj->mapsize); obj_free(obj); return (NULL); } obj->dlopened = (flags & RTLD_LO_DLOPEN) != 0; *obj_tail = obj; obj_tail = &obj->next; obj_count++; obj_loads++; linkmap_add(obj); /* for GDB & dlinfo() */ max_stack_flags |= obj->stack_flags; dbg(" %p .. %p: %s", obj->mapbase, obj->mapbase + obj->mapsize - 1, obj->path); if (obj->textrel) dbg(" WARNING: %s has impure text", obj->path); LD_UTRACE(UTRACE_LOAD_OBJECT, obj, obj->mapbase, obj->mapsize, 0, obj->path); return obj; } static Obj_Entry * obj_from_addr(const void *addr) { Obj_Entry *obj; for (obj = obj_list; obj != NULL; obj = obj->next) { if (addr < (void *) obj->mapbase) continue; if (addr < (void *) (obj->mapbase + obj->mapsize)) return obj; } return NULL; } static void preinit_main(void) { Elf_Addr *preinit_addr; int index; preinit_addr = (Elf_Addr *)obj_main->preinit_array; if (preinit_addr == NULL) return; for (index = 0; index < obj_main->preinit_array_num; index++) { if (preinit_addr[index] != 0 && preinit_addr[index] != 1) { dbg("calling preinit function for %s at %p", obj_main->path, (void *)preinit_addr[index]); LD_UTRACE(UTRACE_INIT_CALL, obj_main, (void *)preinit_addr[index], 0, 0, obj_main->path); call_init_pointer(obj_main, preinit_addr[index]); } } } /* * Call the finalization functions for each of the objects in "list" * belonging to the DAG of "root" and referenced once. If NULL "root" * is specified, every finalization function will be called regardless * of the reference count and the list elements won't be freed. All of * the objects are expected to have non-NULL fini functions. */ static void objlist_call_fini(Objlist *list, Obj_Entry *root, RtldLockState *lockstate) { Objlist_Entry *elm; char *saved_msg; Elf_Addr *fini_addr; int index; assert(root == NULL || root->refcount == 1); /* * Preserve the current error message since a fini function might * call into the dynamic linker and overwrite it. */ saved_msg = errmsg_save(); do { STAILQ_FOREACH(elm, list, link) { if (root != NULL && (elm->obj->refcount != 1 || objlist_find(&root->dagmembers, elm->obj) == NULL)) continue; /* Remove object from fini list to prevent recursive invocation. */ STAILQ_REMOVE(list, elm, Struct_Objlist_Entry, link); /* * XXX: If a dlopen() call references an object while the * fini function is in progress, we might end up trying to * unload the referenced object in dlclose() or the object * won't be unloaded although its fini function has been * called. */ lock_release(rtld_bind_lock, lockstate); /* * It is legal to have both DT_FINI and DT_FINI_ARRAY defined. * When this happens, DT_FINI_ARRAY is processed first. */ fini_addr = (Elf_Addr *)elm->obj->fini_array; if (fini_addr != NULL && elm->obj->fini_array_num > 0) { for (index = elm->obj->fini_array_num - 1; index >= 0; index--) { if (fini_addr[index] != 0 && fini_addr[index] != 1) { dbg("calling fini function for %s at %p", elm->obj->path, (void *)fini_addr[index]); LD_UTRACE(UTRACE_FINI_CALL, elm->obj, (void *)fini_addr[index], 0, 0, elm->obj->path); call_initfini_pointer(elm->obj, fini_addr[index]); } } } if (elm->obj->fini != (Elf_Addr)NULL) { dbg("calling fini function for %s at %p", elm->obj->path, (void *)elm->obj->fini); LD_UTRACE(UTRACE_FINI_CALL, elm->obj, (void *)elm->obj->fini, 0, 0, elm->obj->path); call_initfini_pointer(elm->obj, elm->obj->fini); } wlock_acquire(rtld_bind_lock, lockstate); /* No need to free anything if process is going down. */ if (root != NULL) free(elm); /* * We must restart the list traversal after every fini call * because a dlclose() call from the fini function or from * another thread might have modified the reference counts. */ break; } } while (elm != NULL); errmsg_restore(saved_msg); } /* * Call the initialization functions for each of the objects in * "list". All of the objects are expected to have non-NULL init * functions. */ static void objlist_call_init(Objlist *list, RtldLockState *lockstate) { Objlist_Entry *elm; Obj_Entry *obj; char *saved_msg; Elf_Addr *init_addr; int index; /* * Clean init_scanned flag so that objects can be rechecked and * possibly initialized earlier if any of vectors called below * cause the change by using dlopen. */ for (obj = obj_list; obj != NULL; obj = obj->next) obj->init_scanned = false; /* * Preserve the current error message since an init function might * call into the dynamic linker and overwrite it. */ saved_msg = errmsg_save(); STAILQ_FOREACH(elm, list, link) { if (elm->obj->init_done) /* Initialized early. */ continue; /* * Race: other thread might try to use this object before current * one completes the initilization. Not much can be done here * without better locking. */ elm->obj->init_done = true; lock_release(rtld_bind_lock, lockstate); /* * It is legal to have both DT_INIT and DT_INIT_ARRAY defined. * When this happens, DT_INIT is processed first. */ if (elm->obj->init != (Elf_Addr)NULL) { dbg("calling init function for %s at %p", elm->obj->path, (void *)elm->obj->init); LD_UTRACE(UTRACE_INIT_CALL, elm->obj, (void *)elm->obj->init, 0, 0, elm->obj->path); call_initfini_pointer(elm->obj, elm->obj->init); } init_addr = (Elf_Addr *)elm->obj->init_array; if (init_addr != NULL) { for (index = 0; index < elm->obj->init_array_num; index++) { if (init_addr[index] != 0 && init_addr[index] != 1) { dbg("calling init function for %s at %p", elm->obj->path, (void *)init_addr[index]); LD_UTRACE(UTRACE_INIT_CALL, elm->obj, (void *)init_addr[index], 0, 0, elm->obj->path); call_init_pointer(elm->obj, init_addr[index]); } } } wlock_acquire(rtld_bind_lock, lockstate); } errmsg_restore(saved_msg); } static void objlist_clear(Objlist *list) { Objlist_Entry *elm; while (!STAILQ_EMPTY(list)) { elm = STAILQ_FIRST(list); STAILQ_REMOVE_HEAD(list, link); free(elm); } } static Objlist_Entry * objlist_find(Objlist *list, const Obj_Entry *obj) { Objlist_Entry *elm; STAILQ_FOREACH(elm, list, link) if (elm->obj == obj) return elm; return NULL; } static void objlist_init(Objlist *list) { STAILQ_INIT(list); } static void objlist_push_head(Objlist *list, Obj_Entry *obj) { Objlist_Entry *elm; elm = NEW(Objlist_Entry); elm->obj = obj; STAILQ_INSERT_HEAD(list, elm, link); } static void objlist_push_tail(Objlist *list, Obj_Entry *obj) { Objlist_Entry *elm; elm = NEW(Objlist_Entry); elm->obj = obj; STAILQ_INSERT_TAIL(list, elm, link); } static void objlist_put_after(Objlist *list, Obj_Entry *listobj, Obj_Entry *obj) { Objlist_Entry *elm, *listelm; STAILQ_FOREACH(listelm, list, link) { if (listelm->obj == listobj) break; } elm = NEW(Objlist_Entry); elm->obj = obj; if (listelm != NULL) STAILQ_INSERT_AFTER(list, listelm, elm, link); else STAILQ_INSERT_TAIL(list, elm, link); } static void objlist_remove(Objlist *list, Obj_Entry *obj) { Objlist_Entry *elm; if ((elm = objlist_find(list, obj)) != NULL) { STAILQ_REMOVE(list, elm, Struct_Objlist_Entry, link); free(elm); } } /* * Relocate dag rooted in the specified object. * Returns 0 on success, or -1 on failure. */ static int relocate_object_dag(Obj_Entry *root, bool bind_now, Obj_Entry *rtldobj, int flags, RtldLockState *lockstate) { Objlist_Entry *elm; int error; error = 0; STAILQ_FOREACH(elm, &root->dagmembers, link) { error = relocate_object(elm->obj, bind_now, rtldobj, flags, lockstate); if (error == -1) break; } return (error); } /* * Relocate single object. * Returns 0 on success, or -1 on failure. */ static int relocate_object(Obj_Entry *obj, bool bind_now, Obj_Entry *rtldobj, int flags, RtldLockState *lockstate) { if (obj->relocated) return (0); obj->relocated = true; if (obj != rtldobj) dbg("relocating \"%s\"", obj->path); if (obj->symtab == NULL || obj->strtab == NULL || !(obj->valid_hash_sysv || obj->valid_hash_gnu)) { _rtld_error("%s: Shared object has no run-time symbol table", obj->path); return (-1); } if (obj->textrel) { /* There are relocations to the write-protected text segment. */ if (mprotect(obj->mapbase, obj->textsize, PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { _rtld_error("%s: Cannot write-enable text segment: %s", obj->path, rtld_strerror(errno)); return (-1); } } /* Process the non-PLT non-IFUNC relocations. */ if (reloc_non_plt(obj, rtldobj, flags, lockstate)) return (-1); if (obj->textrel) { /* Re-protected the text segment. */ if (mprotect(obj->mapbase, obj->textsize, PROT_READ|PROT_EXEC) == -1) { _rtld_error("%s: Cannot write-protect text segment: %s", obj->path, rtld_strerror(errno)); return (-1); } } /* Set the special PLT or GOT entries. */ init_pltgot(obj); /* Process the PLT relocations. */ if (reloc_plt(obj) == -1) return (-1); /* Relocate the jump slots if we are doing immediate binding. */ if (obj->bind_now || bind_now) if (reloc_jmpslots(obj, flags, lockstate) == -1) return (-1); /* * Process the non-PLT IFUNC relocations. The relocations are * processed in two phases, because IFUNC resolvers may * reference other symbols, which must be readily processed * before resolvers are called. */ if (obj->non_plt_gnu_ifunc && reloc_non_plt(obj, rtldobj, flags | SYMLOOK_IFUNC, lockstate)) return (-1); if (obj->relro_size > 0) { if (mprotect(obj->relro_page, obj->relro_size, PROT_READ) == -1) { _rtld_error("%s: Cannot enforce relro protection: %s", obj->path, rtld_strerror(errno)); return (-1); } } /* * Set up the magic number and version in the Obj_Entry. These * were checked in the crt1.o from the original ElfKit, so we * set them for backward compatibility. */ obj->magic = RTLD_MAGIC; obj->version = RTLD_VERSION; return (0); } /* * Relocate newly-loaded shared objects. The argument is a pointer to * the Obj_Entry for the first such object. All objects from the first * to the end of the list of objects are relocated. Returns 0 on success, * or -1 on failure. */ static int relocate_objects(Obj_Entry *first, bool bind_now, Obj_Entry *rtldobj, int flags, RtldLockState *lockstate) { Obj_Entry *obj; int error; for (error = 0, obj = first; obj != NULL; obj = obj->next) { error = relocate_object(obj, bind_now, rtldobj, flags, lockstate); if (error == -1) break; } return (error); } /* * The handling of R_MACHINE_IRELATIVE relocations and jumpslots * referencing STT_GNU_IFUNC symbols is postponed till the other * relocations are done. The indirect functions specified as * ifunc are allowed to call other symbols, so we need to have * objects relocated before asking for resolution from indirects. * * The R_MACHINE_IRELATIVE slots are resolved in greedy fashion, * instead of the usual lazy handling of PLT slots. It is * consistent with how GNU does it. */ static int resolve_object_ifunc(Obj_Entry *obj, bool bind_now, int flags, RtldLockState *lockstate) { if (obj->irelative && reloc_iresolve(obj, lockstate) == -1) return (-1); if ((obj->bind_now || bind_now) && obj->gnu_ifunc && reloc_gnu_ifunc(obj, flags, lockstate) == -1) return (-1); return (0); } static int resolve_objects_ifunc(Obj_Entry *first, bool bind_now, int flags, RtldLockState *lockstate) { Obj_Entry *obj; for (obj = first; obj != NULL; obj = obj->next) { if (resolve_object_ifunc(obj, bind_now, flags, lockstate) == -1) return (-1); } return (0); } static int initlist_objects_ifunc(Objlist *list, bool bind_now, int flags, RtldLockState *lockstate) { Objlist_Entry *elm; STAILQ_FOREACH(elm, list, link) { if (resolve_object_ifunc(elm->obj, bind_now, flags, lockstate) == -1) return (-1); } return (0); } /* * Cleanup procedure. It will be called (by the atexit mechanism) just * before the process exits. */ static void rtld_exit(void) { RtldLockState lockstate; wlock_acquire(rtld_bind_lock, &lockstate); dbg("rtld_exit()"); objlist_call_fini(&list_fini, NULL, &lockstate); /* No need to remove the items from the list, since we are exiting. */ if (!libmap_disable) lm_fini(); lock_release(rtld_bind_lock, &lockstate); } /* * Iterate over a search path, translate each element, and invoke the * callback on the result. */ static void * path_enumerate(const char *path, path_enum_proc callback, void *arg) { const char *trans; if (path == NULL) return (NULL); path += strspn(path, ":;"); while (*path != '\0') { size_t len; char *res; len = strcspn(path, ":;"); trans = lm_findn(NULL, path, len); if (trans) res = callback(trans, strlen(trans), arg); else res = callback(path, len, arg); if (res != NULL) return (res); path += len; path += strspn(path, ":;"); } return (NULL); } struct try_library_args { const char *name; size_t namelen; char *buffer; size_t buflen; }; static void * try_library_path(const char *dir, size_t dirlen, void *param) { struct try_library_args *arg; arg = param; if (*dir == '/' || trust) { char *pathname; if (dirlen + 1 + arg->namelen + 1 > arg->buflen) return (NULL); pathname = arg->buffer; strncpy(pathname, dir, dirlen); pathname[dirlen] = '/'; strcpy(pathname + dirlen + 1, arg->name); dbg(" Trying \"%s\"", pathname); if (access(pathname, F_OK) == 0) { /* We found it */ pathname = xmalloc(dirlen + 1 + arg->namelen + 1); strcpy(pathname, arg->buffer); return (pathname); } } return (NULL); } static char * search_library_path(const char *name, const char *path) { char *p; struct try_library_args arg; if (path == NULL) return NULL; arg.name = name; arg.namelen = strlen(name); arg.buffer = xmalloc(PATH_MAX); arg.buflen = PATH_MAX; p = path_enumerate(path, try_library_path, &arg); free(arg.buffer); return (p); } /* * Finds the library with the given name using the directory descriptors * listed in the LD_LIBRARY_PATH_FDS environment variable. * * Returns a freshly-opened close-on-exec file descriptor for the library, * or -1 if the library cannot be found. */ static char * search_library_pathfds(const char *name, const char *path, int *fdp) { char *envcopy, *fdstr, *found, *last_token; size_t len; int dirfd, fd; dbg("%s('%s', '%s', fdp)", __func__, name, path); /* Don't load from user-specified libdirs into setuid binaries. */ if (!trust) return (NULL); /* We can't do anything if LD_LIBRARY_PATH_FDS isn't set. */ if (path == NULL) return (NULL); /* LD_LIBRARY_PATH_FDS only works with relative paths. */ if (name[0] == '/') { dbg("Absolute path (%s) passed to %s", name, __func__); return (NULL); } /* * Use strtok_r() to walk the FD:FD:FD list. This requires a local * copy of the path, as strtok_r rewrites separator tokens * with '\0'. */ found = NULL; envcopy = xstrdup(path); for (fdstr = strtok_r(envcopy, ":", &last_token); fdstr != NULL; fdstr = strtok_r(NULL, ":", &last_token)) { dirfd = parse_libdir(fdstr); if (dirfd < 0) break; fd = __sys_openat(dirfd, name, O_RDONLY | O_CLOEXEC | O_VERIFY); if (fd >= 0) { *fdp = fd; len = strlen(fdstr) + strlen(name) + 3; found = xmalloc(len); if (rtld_snprintf(found, len, "#%d/%s", dirfd, name) < 0) { _rtld_error("error generating '%d/%s'", dirfd, name); rtld_die(); } dbg("open('%s') => %d", found, fd); break; } } free(envcopy); return (found); } int dlclose(void *handle) { Obj_Entry *root; RtldLockState lockstate; wlock_acquire(rtld_bind_lock, &lockstate); root = dlcheck(handle); if (root == NULL) { lock_release(rtld_bind_lock, &lockstate); return -1; } LD_UTRACE(UTRACE_DLCLOSE_START, handle, NULL, 0, root->dl_refcount, root->path); /* Unreference the object and its dependencies. */ root->dl_refcount--; if (root->refcount == 1) { /* * The object will be no longer referenced, so we must unload it. * First, call the fini functions. */ objlist_call_fini(&list_fini, root, &lockstate); unref_dag(root); /* Finish cleaning up the newly-unreferenced objects. */ GDB_STATE(RT_DELETE,&root->linkmap); unload_object(root); GDB_STATE(RT_CONSISTENT,NULL); } else unref_dag(root); LD_UTRACE(UTRACE_DLCLOSE_STOP, handle, NULL, 0, 0, NULL); lock_release(rtld_bind_lock, &lockstate); return 0; } char * dlerror(void) { char *msg = error_message; error_message = NULL; return msg; } /* * This function is deprecated and has no effect. */ void dllockinit(void *context, void *(*lock_create)(void *context), void (*rlock_acquire)(void *lock), void (*wlock_acquire)(void *lock), void (*lock_release)(void *lock), void (*lock_destroy)(void *lock), void (*context_destroy)(void *context)) { static void *cur_context; static void (*cur_context_destroy)(void *); /* Just destroy the context from the previous call, if necessary. */ if (cur_context_destroy != NULL) cur_context_destroy(cur_context); cur_context = context; cur_context_destroy = context_destroy; } void * dlopen(const char *name, int mode) { return (rtld_dlopen(name, -1, mode)); } void * fdlopen(int fd, int mode) { return (rtld_dlopen(NULL, fd, mode)); } static void * rtld_dlopen(const char *name, int fd, int mode) { RtldLockState lockstate; int lo_flags; LD_UTRACE(UTRACE_DLOPEN_START, NULL, NULL, 0, mode, name); ld_tracing = (mode & RTLD_TRACE) == 0 ? NULL : "1"; if (ld_tracing != NULL) { rlock_acquire(rtld_bind_lock, &lockstate); if (sigsetjmp(lockstate.env, 0) != 0) lock_upgrade(rtld_bind_lock, &lockstate); environ = (char **)*get_program_var_addr("environ", &lockstate); lock_release(rtld_bind_lock, &lockstate); } lo_flags = RTLD_LO_DLOPEN; if (mode & RTLD_NODELETE) lo_flags |= RTLD_LO_NODELETE; if (mode & RTLD_NOLOAD) lo_flags |= RTLD_LO_NOLOAD; if (ld_tracing != NULL) lo_flags |= RTLD_LO_TRACE; return (dlopen_object(name, fd, obj_main, lo_flags, mode & (RTLD_MODEMASK | RTLD_GLOBAL), NULL)); } static void dlopen_cleanup(Obj_Entry *obj) { obj->dl_refcount--; unref_dag(obj); if (obj->refcount == 0) unload_object(obj); } static Obj_Entry * dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags, int mode, RtldLockState *lockstate) { Obj_Entry **old_obj_tail; Obj_Entry *obj; Objlist initlist; RtldLockState mlockstate; int result; objlist_init(&initlist); if (lockstate == NULL && !(lo_flags & RTLD_LO_EARLY)) { wlock_acquire(rtld_bind_lock, &mlockstate); lockstate = &mlockstate; } GDB_STATE(RT_ADD,NULL); old_obj_tail = obj_tail; obj = NULL; if (name == NULL && fd == -1) { obj = obj_main; obj->refcount++; } else { obj = load_object(name, fd, refobj, lo_flags); } if (obj) { obj->dl_refcount++; if (mode & RTLD_GLOBAL && objlist_find(&list_global, obj) == NULL) objlist_push_tail(&list_global, obj); if (*old_obj_tail != NULL) { /* We loaded something new. */ assert(*old_obj_tail == obj); result = load_needed_objects(obj, lo_flags & (RTLD_LO_DLOPEN | RTLD_LO_EARLY)); init_dag(obj); ref_dag(obj); if (result != -1) result = rtld_verify_versions(&obj->dagmembers); if (result != -1 && ld_tracing) goto trace; if (result == -1 || relocate_object_dag(obj, (mode & RTLD_MODEMASK) == RTLD_NOW, &obj_rtld, (lo_flags & RTLD_LO_EARLY) ? SYMLOOK_EARLY : 0, lockstate) == -1) { dlopen_cleanup(obj); obj = NULL; } else if (lo_flags & RTLD_LO_EARLY) { /* * Do not call the init functions for early loaded * filtees. The image is still not initialized enough * for them to work. * * Our object is found by the global object list and * will be ordered among all init calls done right * before transferring control to main. */ } else { /* Make list of init functions to call. */ initlist_add_objects(obj, &obj->next, &initlist); } /* * Process all no_delete or global objects here, given * them own DAGs to prevent their dependencies from being * unloaded. This has to be done after we have loaded all * of the dependencies, so that we do not miss any. */ if (obj != NULL) process_z(obj); } else { /* * Bump the reference counts for objects on this DAG. If * this is the first dlopen() call for the object that was * already loaded as a dependency, initialize the dag * starting at it. */ init_dag(obj); ref_dag(obj); if ((lo_flags & RTLD_LO_TRACE) != 0) goto trace; } if (obj != NULL && ((lo_flags & RTLD_LO_NODELETE) != 0 || obj->z_nodelete) && !obj->ref_nodel) { dbg("obj %s nodelete", obj->path); ref_dag(obj); obj->z_nodelete = obj->ref_nodel = true; } } LD_UTRACE(UTRACE_DLOPEN_STOP, obj, NULL, 0, obj ? obj->dl_refcount : 0, name); GDB_STATE(RT_CONSISTENT,obj ? &obj->linkmap : NULL); if (!(lo_flags & RTLD_LO_EARLY)) { map_stacks_exec(lockstate); } if (initlist_objects_ifunc(&initlist, (mode & RTLD_MODEMASK) == RTLD_NOW, (lo_flags & RTLD_LO_EARLY) ? SYMLOOK_EARLY : 0, lockstate) == -1) { objlist_clear(&initlist); dlopen_cleanup(obj); if (lockstate == &mlockstate) lock_release(rtld_bind_lock, lockstate); return (NULL); } if (!(lo_flags & RTLD_LO_EARLY)) { /* Call the init functions. */ objlist_call_init(&initlist, lockstate); } objlist_clear(&initlist); if (lockstate == &mlockstate) lock_release(rtld_bind_lock, lockstate); return obj; trace: trace_loaded_objects(obj); if (lockstate == &mlockstate) lock_release(rtld_bind_lock, lockstate); exit(0); } static void * do_dlsym(void *handle, const char *name, void *retaddr, const Ver_Entry *ve, int flags) { DoneList donelist; const Obj_Entry *obj, *defobj; const Elf_Sym *def; SymLook req; RtldLockState lockstate; tls_index ti; void *sym; int res; def = NULL; defobj = NULL; symlook_init(&req, name); req.ventry = ve; req.flags = flags | SYMLOOK_IN_PLT; req.lockstate = &lockstate; LD_UTRACE(UTRACE_DLSYM_START, handle, NULL, 0, 0, name); rlock_acquire(rtld_bind_lock, &lockstate); if (sigsetjmp(lockstate.env, 0) != 0) lock_upgrade(rtld_bind_lock, &lockstate); if (handle == NULL || handle == RTLD_NEXT || handle == RTLD_DEFAULT || handle == RTLD_SELF) { if ((obj = obj_from_addr(retaddr)) == NULL) { _rtld_error("Cannot determine caller's shared object"); lock_release(rtld_bind_lock, &lockstate); LD_UTRACE(UTRACE_DLSYM_STOP, handle, NULL, 0, 0, name); return NULL; } if (handle == NULL) { /* Just the caller's shared object. */ res = symlook_obj(&req, obj); if (res == 0) { def = req.sym_out; defobj = req.defobj_out; } } else if (handle == RTLD_NEXT || /* Objects after caller's */ handle == RTLD_SELF) { /* ... caller included */ if (handle == RTLD_NEXT) obj = obj->next; for (; obj != NULL; obj = obj->next) { res = symlook_obj(&req, obj); if (res == 0) { if (def == NULL || ELF_ST_BIND(req.sym_out->st_info) != STB_WEAK) { def = req.sym_out; defobj = req.defobj_out; if (ELF_ST_BIND(def->st_info) != STB_WEAK) break; } } } /* * Search the dynamic linker itself, and possibly resolve the * symbol from there. This is how the application links to * dynamic linker services such as dlopen. */ if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { res = symlook_obj(&req, &obj_rtld); if (res == 0) { def = req.sym_out; defobj = req.defobj_out; } } } else { assert(handle == RTLD_DEFAULT); res = symlook_default(&req, obj); if (res == 0) { defobj = req.defobj_out; def = req.sym_out; } } } else { if ((obj = dlcheck(handle)) == NULL) { lock_release(rtld_bind_lock, &lockstate); LD_UTRACE(UTRACE_DLSYM_STOP, handle, NULL, 0, 0, name); return NULL; } donelist_init(&donelist); if (obj->mainprog) { /* Handle obtained by dlopen(NULL, ...) implies global scope. */ res = symlook_global(&req, &donelist); if (res == 0) { def = req.sym_out; defobj = req.defobj_out; } /* * Search the dynamic linker itself, and possibly resolve the * symbol from there. This is how the application links to * dynamic linker services such as dlopen. */ if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { res = symlook_obj(&req, &obj_rtld); if (res == 0) { def = req.sym_out; defobj = req.defobj_out; } } } else { /* Search the whole DAG rooted at the given object. */ res = symlook_list(&req, &obj->dagmembers, &donelist); if (res == 0) { def = req.sym_out; defobj = req.defobj_out; } } } if (def != NULL) { lock_release(rtld_bind_lock, &lockstate); /* * The value required by the caller is derived from the value * of the symbol. this is simply the relocated value of the * symbol. */ if (ELF_ST_TYPE(def->st_info) == STT_FUNC) sym = make_function_pointer(def, defobj); else if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) sym = rtld_resolve_ifunc(defobj, def); else if (ELF_ST_TYPE(def->st_info) == STT_TLS) { ti.ti_module = defobj->tlsindex; ti.ti_offset = def->st_value; sym = __tls_get_addr(&ti); } else sym = defobj->relocbase + def->st_value; LD_UTRACE(UTRACE_DLSYM_STOP, handle, sym, 0, 0, name); return (sym); } _rtld_error("Undefined symbol \"%s\"", name); lock_release(rtld_bind_lock, &lockstate); LD_UTRACE(UTRACE_DLSYM_STOP, handle, NULL, 0, 0, name); return NULL; } void * dlsym(void *handle, const char *name) { return do_dlsym(handle, name, __builtin_return_address(0), NULL, SYMLOOK_DLSYM); } dlfunc_t dlfunc(void *handle, const char *name) { union { void *d; dlfunc_t f; } rv; rv.d = do_dlsym(handle, name, __builtin_return_address(0), NULL, SYMLOOK_DLSYM); return (rv.f); } void * dlvsym(void *handle, const char *name, const char *version) { Ver_Entry ventry; ventry.name = version; ventry.file = NULL; ventry.hash = elf_hash(version); ventry.flags= 0; return do_dlsym(handle, name, __builtin_return_address(0), &ventry, SYMLOOK_DLSYM); } int _rtld_addr_phdr(const void *addr, struct dl_phdr_info *phdr_info) { const Obj_Entry *obj; RtldLockState lockstate; rlock_acquire(rtld_bind_lock, &lockstate); obj = obj_from_addr(addr); if (obj == NULL) { _rtld_error("No shared object contains address"); lock_release(rtld_bind_lock, &lockstate); return (0); } rtld_fill_dl_phdr_info(obj, phdr_info); lock_release(rtld_bind_lock, &lockstate); return (1); } int dladdr(const void *addr, Dl_info *info) { const Obj_Entry *obj; const Elf_Sym *def; void *symbol_addr; unsigned long symoffset; RtldLockState lockstate; rlock_acquire(rtld_bind_lock, &lockstate); obj = obj_from_addr(addr); if (obj == NULL) { _rtld_error("No shared object contains address"); lock_release(rtld_bind_lock, &lockstate); return 0; } info->dli_fname = obj->path; info->dli_fbase = obj->mapbase; info->dli_saddr = (void *)0; info->dli_sname = NULL; /* * Walk the symbol list looking for the symbol whose address is * closest to the address sent in. */ for (symoffset = 0; symoffset < obj->dynsymcount; symoffset++) { def = obj->symtab + symoffset; /* * For skip the symbol if st_shndx is either SHN_UNDEF or * SHN_COMMON. */ if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON) continue; /* * If the symbol is greater than the specified address, or if it * is further away from addr than the current nearest symbol, * then reject it. */ symbol_addr = obj->relocbase + def->st_value; if (symbol_addr > addr || symbol_addr < info->dli_saddr) continue; /* Update our idea of the nearest symbol. */ info->dli_sname = obj->strtab + def->st_name; info->dli_saddr = symbol_addr; /* Exact match? */ if (info->dli_saddr == addr) break; } lock_release(rtld_bind_lock, &lockstate); return 1; } int dlinfo(void *handle, int request, void *p) { const Obj_Entry *obj; RtldLockState lockstate; int error; rlock_acquire(rtld_bind_lock, &lockstate); if (handle == NULL || handle == RTLD_SELF) { void *retaddr; retaddr = __builtin_return_address(0); /* __GNUC__ only */ if ((obj = obj_from_addr(retaddr)) == NULL) _rtld_error("Cannot determine caller's shared object"); } else obj = dlcheck(handle); if (obj == NULL) { lock_release(rtld_bind_lock, &lockstate); return (-1); } error = 0; switch (request) { case RTLD_DI_LINKMAP: *((struct link_map const **)p) = &obj->linkmap; break; case RTLD_DI_ORIGIN: error = rtld_dirname(obj->path, p); break; case RTLD_DI_SERINFOSIZE: case RTLD_DI_SERINFO: error = do_search_info(obj, request, (struct dl_serinfo *)p); break; default: _rtld_error("Invalid request %d passed to dlinfo()", request); error = -1; } lock_release(rtld_bind_lock, &lockstate); return (error); } static void rtld_fill_dl_phdr_info(const Obj_Entry *obj, struct dl_phdr_info *phdr_info) { phdr_info->dlpi_addr = (Elf_Addr)obj->relocbase; phdr_info->dlpi_name = obj->path; phdr_info->dlpi_phdr = obj->phdr; phdr_info->dlpi_phnum = obj->phsize / sizeof(obj->phdr[0]); phdr_info->dlpi_tls_modid = obj->tlsindex; phdr_info->dlpi_tls_data = obj->tlsinit; phdr_info->dlpi_adds = obj_loads; phdr_info->dlpi_subs = obj_loads - obj_count; } int dl_iterate_phdr(__dl_iterate_hdr_callback callback, void *param) { struct dl_phdr_info phdr_info; const Obj_Entry *obj; RtldLockState bind_lockstate, phdr_lockstate; int error; wlock_acquire(rtld_phdr_lock, &phdr_lockstate); rlock_acquire(rtld_bind_lock, &bind_lockstate); error = 0; for (obj = obj_list; obj != NULL; obj = obj->next) { rtld_fill_dl_phdr_info(obj, &phdr_info); if ((error = callback(&phdr_info, sizeof phdr_info, param)) != 0) break; } if (error == 0) { rtld_fill_dl_phdr_info(&obj_rtld, &phdr_info); error = callback(&phdr_info, sizeof(phdr_info), param); } lock_release(rtld_bind_lock, &bind_lockstate); lock_release(rtld_phdr_lock, &phdr_lockstate); return (error); } static void * fill_search_info(const char *dir, size_t dirlen, void *param) { struct fill_search_info_args *arg; arg = param; if (arg->request == RTLD_DI_SERINFOSIZE) { arg->serinfo->dls_cnt ++; arg->serinfo->dls_size += sizeof(struct dl_serpath) + dirlen + 1; } else { struct dl_serpath *s_entry; s_entry = arg->serpath; s_entry->dls_name = arg->strspace; s_entry->dls_flags = arg->flags; strncpy(arg->strspace, dir, dirlen); arg->strspace[dirlen] = '\0'; arg->strspace += dirlen + 1; arg->serpath++; } return (NULL); } static int do_search_info(const Obj_Entry *obj, int request, struct dl_serinfo *info) { struct dl_serinfo _info; struct fill_search_info_args args; args.request = RTLD_DI_SERINFOSIZE; args.serinfo = &_info; _info.dls_size = __offsetof(struct dl_serinfo, dls_serpath); _info.dls_cnt = 0; path_enumerate(obj->rpath, fill_search_info, &args); path_enumerate(ld_library_path, fill_search_info, &args); path_enumerate(obj->runpath, fill_search_info, &args); path_enumerate(gethints(obj->z_nodeflib), fill_search_info, &args); if (!obj->z_nodeflib) path_enumerate(ld_standard_library_path, fill_search_info, &args); if (request == RTLD_DI_SERINFOSIZE) { info->dls_size = _info.dls_size; info->dls_cnt = _info.dls_cnt; return (0); } if (info->dls_cnt != _info.dls_cnt || info->dls_size != _info.dls_size) { _rtld_error("Uninitialized Dl_serinfo struct passed to dlinfo()"); return (-1); } args.request = RTLD_DI_SERINFO; args.serinfo = info; args.serpath = &info->dls_serpath[0]; args.strspace = (char *)&info->dls_serpath[_info.dls_cnt]; args.flags = LA_SER_RUNPATH; if (path_enumerate(obj->rpath, fill_search_info, &args) != NULL) return (-1); args.flags = LA_SER_LIBPATH; if (path_enumerate(ld_library_path, fill_search_info, &args) != NULL) return (-1); args.flags = LA_SER_RUNPATH; if (path_enumerate(obj->runpath, fill_search_info, &args) != NULL) return (-1); args.flags = LA_SER_CONFIG; if (path_enumerate(gethints(obj->z_nodeflib), fill_search_info, &args) != NULL) return (-1); args.flags = LA_SER_DEFAULT; if (!obj->z_nodeflib && path_enumerate(ld_standard_library_path, fill_search_info, &args) != NULL) return (-1); return (0); } static int rtld_dirname(const char *path, char *bname) { const char *endp; /* Empty or NULL string gets treated as "." */ if (path == NULL || *path == '\0') { bname[0] = '.'; bname[1] = '\0'; return (0); } /* Strip trailing slashes */ endp = path + strlen(path) - 1; while (endp > path && *endp == '/') endp--; /* Find the start of the dir */ while (endp > path && *endp != '/') endp--; /* Either the dir is "/" or there are no slashes */ if (endp == path) { bname[0] = *endp == '/' ? '/' : '.'; bname[1] = '\0'; return (0); } else { do { endp--; } while (endp > path && *endp == '/'); } if (endp - path + 2 > PATH_MAX) { _rtld_error("Filename is too long: %s", path); return(-1); } strncpy(bname, path, endp - path + 1); bname[endp - path + 1] = '\0'; return (0); } static int rtld_dirname_abs(const char *path, char *base) { char *last; if (realpath(path, base) == NULL) return (-1); dbg("%s -> %s", path, base); last = strrchr(base, '/'); if (last == NULL) return (-1); if (last != base) *last = '\0'; return (0); } static void linkmap_add(Obj_Entry *obj) { struct link_map *l = &obj->linkmap; struct link_map *prev; obj->linkmap.l_name = obj->path; obj->linkmap.l_addr = obj->mapbase; obj->linkmap.l_ld = obj->dynamic; #ifdef __mips__ /* GDB needs load offset on MIPS to use the symbols */ obj->linkmap.l_offs = obj->relocbase; #endif if (r_debug.r_map == NULL) { r_debug.r_map = l; return; } /* * Scan to the end of the list, but not past the entry for the * dynamic linker, which we want to keep at the very end. */ for (prev = r_debug.r_map; prev->l_next != NULL && prev->l_next != &obj_rtld.linkmap; prev = prev->l_next) ; /* Link in the new entry. */ l->l_prev = prev; l->l_next = prev->l_next; if (l->l_next != NULL) l->l_next->l_prev = l; prev->l_next = l; } static void linkmap_delete(Obj_Entry *obj) { struct link_map *l = &obj->linkmap; if (l->l_prev == NULL) { if ((r_debug.r_map = l->l_next) != NULL) l->l_next->l_prev = NULL; return; } if ((l->l_prev->l_next = l->l_next) != NULL) l->l_next->l_prev = l->l_prev; } /* * Function for the debugger to set a breakpoint on to gain control. * * The two parameters allow the debugger to easily find and determine * what the runtime loader is doing and to whom it is doing it. * * When the loadhook trap is hit (r_debug_state, set at program * initialization), the arguments can be found on the stack: * * +8 struct link_map *m * +4 struct r_debug *rd * +0 RetAddr */ void r_debug_state(struct r_debug* rd, struct link_map *m) { /* * The following is a hack to force the compiler to emit calls to * this function, even when optimizing. If the function is empty, * the compiler is not obliged to emit any code for calls to it, * even when marked __noinline. However, gdb depends on those * calls being made. */ __compiler_membar(); } /* * A function called after init routines have completed. This can be used to * break before a program's entry routine is called, and can be used when * main is not available in the symbol table. */ void _r_debug_postinit(struct link_map *m) { /* See r_debug_state(). */ __compiler_membar(); } /* * Get address of the pointer variable in the main program. * Prefer non-weak symbol over the weak one. */ static const void ** get_program_var_addr(const char *name, RtldLockState *lockstate) { SymLook req; DoneList donelist; symlook_init(&req, name); req.lockstate = lockstate; donelist_init(&donelist); if (symlook_global(&req, &donelist) != 0) return (NULL); if (ELF_ST_TYPE(req.sym_out->st_info) == STT_FUNC) return ((const void **)make_function_pointer(req.sym_out, req.defobj_out)); else if (ELF_ST_TYPE(req.sym_out->st_info) == STT_GNU_IFUNC) return ((const void **)rtld_resolve_ifunc(req.defobj_out, req.sym_out)); else return ((const void **)(req.defobj_out->relocbase + req.sym_out->st_value)); } /* * Set a pointer variable in the main program to the given value. This * is used to set key variables such as "environ" before any of the * init functions are called. */ static void set_program_var(const char *name, const void *value) { const void **addr; if ((addr = get_program_var_addr(name, NULL)) != NULL) { dbg("\"%s\": *%p <-- %p", name, addr, value); *addr = value; } } /* * Search the global objects, including dependencies and main object, * for the given symbol. */ static int symlook_global(SymLook *req, DoneList *donelist) { SymLook req1; const Objlist_Entry *elm; int res; symlook_init_from_req(&req1, req); /* Search all objects loaded at program start up. */ if (req->defobj_out == NULL || ELF_ST_BIND(req->sym_out->st_info) == STB_WEAK) { res = symlook_list(&req1, &list_main, donelist); if (res == 0 && (req->defobj_out == NULL || ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK)) { req->sym_out = req1.sym_out; req->defobj_out = req1.defobj_out; assert(req->defobj_out != NULL); } } /* Search all DAGs whose roots are RTLD_GLOBAL objects. */ STAILQ_FOREACH(elm, &list_global, link) { if (req->defobj_out != NULL && ELF_ST_BIND(req->sym_out->st_info) != STB_WEAK) break; res = symlook_list(&req1, &elm->obj->dagmembers, donelist); if (res == 0 && (req->defobj_out == NULL || ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK)) { req->sym_out = req1.sym_out; req->defobj_out = req1.defobj_out; assert(req->defobj_out != NULL); } } return (req->sym_out != NULL ? 0 : ESRCH); } /* * Given a symbol name in a referencing object, find the corresponding * definition of the symbol. Returns a pointer to the symbol, or NULL if * no definition was found. Returns a pointer to the Obj_Entry of the * defining object via the reference parameter DEFOBJ_OUT. */ static int symlook_default(SymLook *req, const Obj_Entry *refobj) { DoneList donelist; const Objlist_Entry *elm; SymLook req1; int res; donelist_init(&donelist); symlook_init_from_req(&req1, req); /* Look first in the referencing object if linked symbolically. */ if (refobj->symbolic && !donelist_check(&donelist, refobj)) { res = symlook_obj(&req1, refobj); if (res == 0) { req->sym_out = req1.sym_out; req->defobj_out = req1.defobj_out; assert(req->defobj_out != NULL); } } symlook_global(req, &donelist); /* Search all dlopened DAGs containing the referencing object. */ STAILQ_FOREACH(elm, &refobj->dldags, link) { if (req->sym_out != NULL && ELF_ST_BIND(req->sym_out->st_info) != STB_WEAK) break; res = symlook_list(&req1, &elm->obj->dagmembers, &donelist); if (res == 0 && (req->sym_out == NULL || ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK)) { req->sym_out = req1.sym_out; req->defobj_out = req1.defobj_out; assert(req->defobj_out != NULL); } } /* * Search the dynamic linker itself, and possibly resolve the * symbol from there. This is how the application links to * dynamic linker services such as dlopen. */ if (req->sym_out == NULL || ELF_ST_BIND(req->sym_out->st_info) == STB_WEAK) { res = symlook_obj(&req1, &obj_rtld); if (res == 0) { req->sym_out = req1.sym_out; req->defobj_out = req1.defobj_out; assert(req->defobj_out != NULL); } } return (req->sym_out != NULL ? 0 : ESRCH); } static int symlook_list(SymLook *req, const Objlist *objlist, DoneList *dlp) { const Elf_Sym *def; const Obj_Entry *defobj; const Objlist_Entry *elm; SymLook req1; int res; def = NULL; defobj = NULL; STAILQ_FOREACH(elm, objlist, link) { if (donelist_check(dlp, elm->obj)) continue; symlook_init_from_req(&req1, req); if ((res = symlook_obj(&req1, elm->obj)) == 0) { if (def == NULL || ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK) { def = req1.sym_out; defobj = req1.defobj_out; if (ELF_ST_BIND(def->st_info) != STB_WEAK) break; } } } if (def != NULL) { req->sym_out = def; req->defobj_out = defobj; return (0); } return (ESRCH); } /* * Search the chain of DAGS cointed to by the given Needed_Entry * for a symbol of the given name. Each DAG is scanned completely * before advancing to the next one. Returns a pointer to the symbol, * or NULL if no definition was found. */ static int symlook_needed(SymLook *req, const Needed_Entry *needed, DoneList *dlp) { const Elf_Sym *def; const Needed_Entry *n; const Obj_Entry *defobj; SymLook req1; int res; def = NULL; defobj = NULL; symlook_init_from_req(&req1, req); for (n = needed; n != NULL; n = n->next) { if (n->obj == NULL || (res = symlook_list(&req1, &n->obj->dagmembers, dlp)) != 0) continue; if (def == NULL || ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK) { def = req1.sym_out; defobj = req1.defobj_out; if (ELF_ST_BIND(def->st_info) != STB_WEAK) break; } } if (def != NULL) { req->sym_out = def; req->defobj_out = defobj; return (0); } return (ESRCH); } /* * Search the symbol table of a single shared object for a symbol of * the given name and version, if requested. Returns a pointer to the * symbol, or NULL if no definition was found. If the object is * filter, return filtered symbol from filtee. * * The symbol's hash value is passed in for efficiency reasons; that * eliminates many recomputations of the hash value. */ int symlook_obj(SymLook *req, const Obj_Entry *obj) { DoneList donelist; SymLook req1; int flags, res, mres; /* * If there is at least one valid hash at this point, we prefer to * use the faster GNU version if available. */ if (obj->valid_hash_gnu) mres = symlook_obj1_gnu(req, obj); else if (obj->valid_hash_sysv) mres = symlook_obj1_sysv(req, obj); else return (EINVAL); if (mres == 0) { if (obj->needed_filtees != NULL) { flags = (req->flags & SYMLOOK_EARLY) ? RTLD_LO_EARLY : 0; load_filtees(__DECONST(Obj_Entry *, obj), flags, req->lockstate); donelist_init(&donelist); symlook_init_from_req(&req1, req); res = symlook_needed(&req1, obj->needed_filtees, &donelist); if (res == 0) { req->sym_out = req1.sym_out; req->defobj_out = req1.defobj_out; } return (res); } if (obj->needed_aux_filtees != NULL) { flags = (req->flags & SYMLOOK_EARLY) ? RTLD_LO_EARLY : 0; load_filtees(__DECONST(Obj_Entry *, obj), flags, req->lockstate); donelist_init(&donelist); symlook_init_from_req(&req1, req); res = symlook_needed(&req1, obj->needed_aux_filtees, &donelist); if (res == 0) { req->sym_out = req1.sym_out; req->defobj_out = req1.defobj_out; return (res); } } } return (mres); } /* Symbol match routine common to both hash functions */ static bool matched_symbol(SymLook *req, const Obj_Entry *obj, Sym_Match_Result *result, const unsigned long symnum) { Elf_Versym verndx; const Elf_Sym *symp; const char *strp; symp = obj->symtab + symnum; strp = obj->strtab + symp->st_name; switch (ELF_ST_TYPE(symp->st_info)) { case STT_FUNC: case STT_NOTYPE: case STT_OBJECT: case STT_COMMON: case STT_GNU_IFUNC: if (symp->st_value == 0) return (false); /* fallthrough */ case STT_TLS: if (symp->st_shndx != SHN_UNDEF) break; #ifndef __mips__ else if (((req->flags & SYMLOOK_IN_PLT) == 0) && (ELF_ST_TYPE(symp->st_info) == STT_FUNC)) break; /* fallthrough */ #endif default: return (false); } if (req->name[0] != strp[0] || strcmp(req->name, strp) != 0) return (false); if (req->ventry == NULL) { if (obj->versyms != NULL) { verndx = VER_NDX(obj->versyms[symnum]); if (verndx > obj->vernum) { _rtld_error( "%s: symbol %s references wrong version %d", obj->path, obj->strtab + symnum, verndx); return (false); } /* * If we are not called from dlsym (i.e. this * is a normal relocation from unversioned * binary), accept the symbol immediately if * it happens to have first version after this * shared object became versioned. Otherwise, * if symbol is versioned and not hidden, * remember it. If it is the only symbol with * this name exported by the shared object, it * will be returned as a match by the calling * function. If symbol is global (verndx < 2) * accept it unconditionally. */ if ((req->flags & SYMLOOK_DLSYM) == 0 && verndx == VER_NDX_GIVEN) { result->sym_out = symp; return (true); } else if (verndx >= VER_NDX_GIVEN) { if ((obj->versyms[symnum] & VER_NDX_HIDDEN) == 0) { if (result->vsymp == NULL) result->vsymp = symp; result->vcount++; } return (false); } } result->sym_out = symp; return (true); } if (obj->versyms == NULL) { if (object_match_name(obj, req->ventry->name)) { _rtld_error("%s: object %s should provide version %s " "for symbol %s", obj_rtld.path, obj->path, req->ventry->name, obj->strtab + symnum); return (false); } } else { verndx = VER_NDX(obj->versyms[symnum]); if (verndx > obj->vernum) { _rtld_error("%s: symbol %s references wrong version %d", obj->path, obj->strtab + symnum, verndx); return (false); } if (obj->vertab[verndx].hash != req->ventry->hash || strcmp(obj->vertab[verndx].name, req->ventry->name)) { /* * Version does not match. Look if this is a * global symbol and if it is not hidden. If * global symbol (verndx < 2) is available, * use it. Do not return symbol if we are * called by dlvsym, because dlvsym looks for * a specific version and default one is not * what dlvsym wants. */ if ((req->flags & SYMLOOK_DLSYM) || (verndx >= VER_NDX_GIVEN) || (obj->versyms[symnum] & VER_NDX_HIDDEN)) return (false); } } result->sym_out = symp; return (true); } /* * Search for symbol using SysV hash function. * obj->buckets is known not to be NULL at this point; the test for this was * performed with the obj->valid_hash_sysv assignment. */ static int symlook_obj1_sysv(SymLook *req, const Obj_Entry *obj) { unsigned long symnum; Sym_Match_Result matchres; matchres.sym_out = NULL; matchres.vsymp = NULL; matchres.vcount = 0; for (symnum = obj->buckets[req->hash % obj->nbuckets]; symnum != STN_UNDEF; symnum = obj->chains[symnum]) { if (symnum >= obj->nchains) return (ESRCH); /* Bad object */ if (matched_symbol(req, obj, &matchres, symnum)) { req->sym_out = matchres.sym_out; req->defobj_out = obj; return (0); } } if (matchres.vcount == 1) { req->sym_out = matchres.vsymp; req->defobj_out = obj; return (0); } return (ESRCH); } /* Search for symbol using GNU hash function */ static int symlook_obj1_gnu(SymLook *req, const Obj_Entry *obj) { Elf_Addr bloom_word; const Elf32_Word *hashval; Elf32_Word bucket; Sym_Match_Result matchres; unsigned int h1, h2; unsigned long symnum; matchres.sym_out = NULL; matchres.vsymp = NULL; matchres.vcount = 0; /* Pick right bitmask word from Bloom filter array */ bloom_word = obj->bloom_gnu[(req->hash_gnu / __ELF_WORD_SIZE) & obj->maskwords_bm_gnu]; /* Calculate modulus word size of gnu hash and its derivative */ h1 = req->hash_gnu & (__ELF_WORD_SIZE - 1); h2 = ((req->hash_gnu >> obj->shift2_gnu) & (__ELF_WORD_SIZE - 1)); /* Filter out the "definitely not in set" queries */ if (((bloom_word >> h1) & (bloom_word >> h2) & 1) == 0) return (ESRCH); /* Locate hash chain and corresponding value element*/ bucket = obj->buckets_gnu[req->hash_gnu % obj->nbuckets_gnu]; if (bucket == 0) return (ESRCH); hashval = &obj->chain_zero_gnu[bucket]; do { if (((*hashval ^ req->hash_gnu) >> 1) == 0) { symnum = hashval - obj->chain_zero_gnu; if (matched_symbol(req, obj, &matchres, symnum)) { req->sym_out = matchres.sym_out; req->defobj_out = obj; return (0); } } } while ((*hashval++ & 1) == 0); if (matchres.vcount == 1) { req->sym_out = matchres.vsymp; req->defobj_out = obj; return (0); } return (ESRCH); } static void trace_loaded_objects(Obj_Entry *obj) { char *fmt1, *fmt2, *fmt, *main_local, *list_containers; int c; if ((main_local = getenv(LD_ "TRACE_LOADED_OBJECTS_PROGNAME")) == NULL) main_local = ""; if ((fmt1 = getenv(LD_ "TRACE_LOADED_OBJECTS_FMT1")) == NULL) fmt1 = "\t%o => %p (%x)\n"; if ((fmt2 = getenv(LD_ "TRACE_LOADED_OBJECTS_FMT2")) == NULL) fmt2 = "\t%o (%x)\n"; list_containers = getenv(LD_ "TRACE_LOADED_OBJECTS_ALL"); for (; obj; obj = obj->next) { Needed_Entry *needed; char *name, *path; bool is_lib; if (list_containers && obj->needed != NULL) rtld_printf("%s:\n", obj->path); for (needed = obj->needed; needed; needed = needed->next) { if (needed->obj != NULL) { if (needed->obj->traced && !list_containers) continue; needed->obj->traced = true; path = needed->obj->path; } else path = "not found"; name = (char *)obj->strtab + needed->name; is_lib = strncmp(name, "lib", 3) == 0; /* XXX - bogus */ fmt = is_lib ? fmt1 : fmt2; while ((c = *fmt++) != '\0') { switch (c) { default: rtld_putchar(c); continue; case '\\': switch (c = *fmt) { case '\0': continue; case 'n': rtld_putchar('\n'); break; case 't': rtld_putchar('\t'); break; } break; case '%': switch (c = *fmt) { case '\0': continue; case '%': default: rtld_putchar(c); break; case 'A': rtld_putstr(main_local); break; case 'a': rtld_putstr(obj_main->path); break; case 'o': rtld_putstr(name); break; #if 0 case 'm': rtld_printf("%d", sodp->sod_major); break; case 'n': rtld_printf("%d", sodp->sod_minor); break; #endif case 'p': rtld_putstr(path); break; case 'x': rtld_printf("%p", needed->obj ? needed->obj->mapbase : 0); break; } break; } ++fmt; } } } } /* * Unload a dlopened object and its dependencies from memory and from * our data structures. It is assumed that the DAG rooted in the * object has already been unreferenced, and that the object has a * reference count of 0. */ static void unload_object(Obj_Entry *root) { Obj_Entry *obj; Obj_Entry **linkp; assert(root->refcount == 0); /* * Pass over the DAG removing unreferenced objects from * appropriate lists. */ unlink_object(root); /* Unmap all objects that are no longer referenced. */ linkp = &obj_list->next; while ((obj = *linkp) != NULL) { if (obj->refcount == 0) { LD_UTRACE(UTRACE_UNLOAD_OBJECT, obj, obj->mapbase, obj->mapsize, 0, obj->path); dbg("unloading \"%s\"", obj->path); unload_filtees(root); munmap(obj->mapbase, obj->mapsize); linkmap_delete(obj); *linkp = obj->next; obj_count--; obj_free(obj); } else linkp = &obj->next; } obj_tail = linkp; } static void unlink_object(Obj_Entry *root) { Objlist_Entry *elm; if (root->refcount == 0) { /* Remove the object from the RTLD_GLOBAL list. */ objlist_remove(&list_global, root); /* Remove the object from all objects' DAG lists. */ STAILQ_FOREACH(elm, &root->dagmembers, link) { objlist_remove(&elm->obj->dldags, root); if (elm->obj != root) unlink_object(elm->obj); } } } static void ref_dag(Obj_Entry *root) { Objlist_Entry *elm; assert(root->dag_inited); STAILQ_FOREACH(elm, &root->dagmembers, link) elm->obj->refcount++; } static void unref_dag(Obj_Entry *root) { Objlist_Entry *elm; assert(root->dag_inited); STAILQ_FOREACH(elm, &root->dagmembers, link) elm->obj->refcount--; } /* * Common code for MD __tls_get_addr(). */ static void *tls_get_addr_slow(Elf_Addr **, int, size_t) __noinline; static void * tls_get_addr_slow(Elf_Addr **dtvp, int index, size_t offset) { Elf_Addr *newdtv, *dtv; RtldLockState lockstate; int to_copy; dtv = *dtvp; /* Check dtv generation in case new modules have arrived */ if (dtv[0] != tls_dtv_generation) { wlock_acquire(rtld_bind_lock, &lockstate); newdtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr)); to_copy = dtv[1]; if (to_copy > tls_max_index) to_copy = tls_max_index; memcpy(&newdtv[2], &dtv[2], to_copy * sizeof(Elf_Addr)); newdtv[0] = tls_dtv_generation; newdtv[1] = tls_max_index; free(dtv); lock_release(rtld_bind_lock, &lockstate); dtv = *dtvp = newdtv; } /* Dynamically allocate module TLS if necessary */ if (dtv[index + 1] == 0) { /* Signal safe, wlock will block out signals. */ wlock_acquire(rtld_bind_lock, &lockstate); if (!dtv[index + 1]) dtv[index + 1] = (Elf_Addr)allocate_module_tls(index); lock_release(rtld_bind_lock, &lockstate); } return ((void *)(dtv[index + 1] + offset)); } void * tls_get_addr_common(Elf_Addr **dtvp, int index, size_t offset) { Elf_Addr *dtv; dtv = *dtvp; /* Check dtv generation in case new modules have arrived */ if (__predict_true(dtv[0] == tls_dtv_generation && dtv[index + 1] != 0)) return ((void *)(dtv[index + 1] + offset)); return (tls_get_addr_slow(dtvp, index, offset)); } #if defined(__aarch64__) || defined(__arm__) || defined(__mips__) || \ defined(__powerpc__) /* * Allocate Static TLS using the Variant I method. */ void * allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign) { Obj_Entry *obj; char *tcb; Elf_Addr **tls; Elf_Addr *dtv; Elf_Addr addr; int i; if (oldtcb != NULL && tcbsize == TLS_TCB_SIZE) return (oldtcb); assert(tcbsize >= TLS_TCB_SIZE); tcb = xcalloc(1, tls_static_space - TLS_TCB_SIZE + tcbsize); tls = (Elf_Addr **)(tcb + tcbsize - TLS_TCB_SIZE); if (oldtcb != NULL) { memcpy(tls, oldtcb, tls_static_space); free(oldtcb); /* Adjust the DTV. */ dtv = tls[0]; for (i = 0; i < dtv[1]; i++) { if (dtv[i+2] >= (Elf_Addr)oldtcb && dtv[i+2] < (Elf_Addr)oldtcb + tls_static_space) { dtv[i+2] = dtv[i+2] - (Elf_Addr)oldtcb + (Elf_Addr)tls; } } } else { dtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr)); tls[0] = dtv; dtv[0] = tls_dtv_generation; dtv[1] = tls_max_index; for (obj = objs; obj; obj = obj->next) { if (obj->tlsoffset > 0) { addr = (Elf_Addr)tls + obj->tlsoffset; if (obj->tlsinitsize > 0) memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize); if (obj->tlssize > obj->tlsinitsize) memset((void*) (addr + obj->tlsinitsize), 0, obj->tlssize - obj->tlsinitsize); dtv[obj->tlsindex + 1] = addr; } } } return (tcb); } void free_tls(void *tcb, size_t tcbsize, size_t tcbalign) { Elf_Addr *dtv; Elf_Addr tlsstart, tlsend; int dtvsize, i; assert(tcbsize >= TLS_TCB_SIZE); tlsstart = (Elf_Addr)tcb + tcbsize - TLS_TCB_SIZE; tlsend = tlsstart + tls_static_space; dtv = *(Elf_Addr **)tlsstart; dtvsize = dtv[1]; for (i = 0; i < dtvsize; i++) { if (dtv[i+2] && (dtv[i+2] < tlsstart || dtv[i+2] >= tlsend)) { free((void*)dtv[i+2]); } } free(dtv); free(tcb); } #endif #if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) /* * Allocate Static TLS using the Variant II method. */ void * allocate_tls(Obj_Entry *objs, void *oldtls, size_t tcbsize, size_t tcbalign) { Obj_Entry *obj; size_t size, ralign; char *tls; Elf_Addr *dtv, *olddtv; Elf_Addr segbase, oldsegbase, addr; int i; ralign = tcbalign; if (tls_static_max_align > ralign) ralign = tls_static_max_align; size = round(tls_static_space, ralign) + round(tcbsize, ralign); assert(tcbsize >= 2*sizeof(Elf_Addr)); tls = malloc_aligned(size, ralign); dtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr)); segbase = (Elf_Addr)(tls + round(tls_static_space, ralign)); ((Elf_Addr*)segbase)[0] = segbase; ((Elf_Addr*)segbase)[1] = (Elf_Addr) dtv; dtv[0] = tls_dtv_generation; dtv[1] = tls_max_index; if (oldtls) { /* * Copy the static TLS block over whole. */ oldsegbase = (Elf_Addr) oldtls; memcpy((void *)(segbase - tls_static_space), (const void *)(oldsegbase - tls_static_space), tls_static_space); /* * If any dynamic TLS blocks have been created tls_get_addr(), * move them over. */ olddtv = ((Elf_Addr**)oldsegbase)[1]; for (i = 0; i < olddtv[1]; i++) { if (olddtv[i+2] < oldsegbase - size || olddtv[i+2] > oldsegbase) { dtv[i+2] = olddtv[i+2]; olddtv[i+2] = 0; } } /* * We assume that this block was the one we created with * allocate_initial_tls(). */ free_tls(oldtls, 2*sizeof(Elf_Addr), sizeof(Elf_Addr)); } else { for (obj = objs; obj; obj = obj->next) { if (obj->tlsoffset) { addr = segbase - obj->tlsoffset; memset((void*) (addr + obj->tlsinitsize), 0, obj->tlssize - obj->tlsinitsize); if (obj->tlsinit) memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize); dtv[obj->tlsindex + 1] = addr; } } } return (void*) segbase; } void free_tls(void *tls, size_t tcbsize, size_t tcbalign) { Elf_Addr* dtv; size_t size, ralign; int dtvsize, i; Elf_Addr tlsstart, tlsend; /* * Figure out the size of the initial TLS block so that we can * find stuff which ___tls_get_addr() allocated dynamically. */ ralign = tcbalign; if (tls_static_max_align > ralign) ralign = tls_static_max_align; size = round(tls_static_space, ralign); dtv = ((Elf_Addr**)tls)[1]; dtvsize = dtv[1]; tlsend = (Elf_Addr) tls; tlsstart = tlsend - size; for (i = 0; i < dtvsize; i++) { if (dtv[i + 2] != 0 && (dtv[i + 2] < tlsstart || dtv[i + 2] > tlsend)) { free_aligned((void *)dtv[i + 2]); } } free_aligned((void *)tlsstart); free((void*) dtv); } #endif /* * Allocate TLS block for module with given index. */ void * allocate_module_tls(int index) { Obj_Entry* obj; char* p; for (obj = obj_list; obj; obj = obj->next) { if (obj->tlsindex == index) break; } if (!obj) { _rtld_error("Can't find module with TLS index %d", index); rtld_die(); } p = malloc_aligned(obj->tlssize, obj->tlsalign); memcpy(p, obj->tlsinit, obj->tlsinitsize); memset(p + obj->tlsinitsize, 0, obj->tlssize - obj->tlsinitsize); return p; } bool allocate_tls_offset(Obj_Entry *obj) { size_t off; if (obj->tls_done) return true; if (obj->tlssize == 0) { obj->tls_done = true; return true; } if (tls_last_offset == 0) off = calculate_first_tls_offset(obj->tlssize, obj->tlsalign); else off = calculate_tls_offset(tls_last_offset, tls_last_size, obj->tlssize, obj->tlsalign); /* * If we have already fixed the size of the static TLS block, we * must stay within that size. When allocating the static TLS, we * leave a small amount of space spare to be used for dynamically * loading modules which use static TLS. */ if (tls_static_space != 0) { if (calculate_tls_end(off, obj->tlssize) > tls_static_space) return false; } else if (obj->tlsalign > tls_static_max_align) { tls_static_max_align = obj->tlsalign; } tls_last_offset = obj->tlsoffset = off; tls_last_size = obj->tlssize; obj->tls_done = true; return true; } void free_tls_offset(Obj_Entry *obj) { /* * If we were the last thing to allocate out of the static TLS * block, we give our space back to the 'allocator'. This is a * simplistic workaround to allow libGL.so.1 to be loaded and * unloaded multiple times. */ if (calculate_tls_end(obj->tlsoffset, obj->tlssize) == calculate_tls_end(tls_last_offset, tls_last_size)) { tls_last_offset -= obj->tlssize; tls_last_size = 0; } } void * _rtld_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign) { void *ret; RtldLockState lockstate; wlock_acquire(rtld_bind_lock, &lockstate); ret = allocate_tls(obj_list, oldtls, tcbsize, tcbalign); lock_release(rtld_bind_lock, &lockstate); return (ret); } void _rtld_free_tls(void *tcb, size_t tcbsize, size_t tcbalign) { RtldLockState lockstate; wlock_acquire(rtld_bind_lock, &lockstate); free_tls(tcb, tcbsize, tcbalign); lock_release(rtld_bind_lock, &lockstate); } static void object_add_name(Obj_Entry *obj, const char *name) { Name_Entry *entry; size_t len; len = strlen(name); entry = malloc(sizeof(Name_Entry) + len); if (entry != NULL) { strcpy(entry->name, name); STAILQ_INSERT_TAIL(&obj->names, entry, link); } } static int object_match_name(const Obj_Entry *obj, const char *name) { Name_Entry *entry; STAILQ_FOREACH(entry, &obj->names, link) { if (strcmp(name, entry->name) == 0) return (1); } return (0); } static Obj_Entry * locate_dependency(const Obj_Entry *obj, const char *name) { const Objlist_Entry *entry; const Needed_Entry *needed; STAILQ_FOREACH(entry, &list_main, link) { if (object_match_name(entry->obj, name)) return entry->obj; } for (needed = obj->needed; needed != NULL; needed = needed->next) { if (strcmp(obj->strtab + needed->name, name) == 0 || (needed->obj != NULL && object_match_name(needed->obj, name))) { /* * If there is DT_NEEDED for the name we are looking for, * we are all set. Note that object might not be found if * dependency was not loaded yet, so the function can * return NULL here. This is expected and handled * properly by the caller. */ return (needed->obj); } } _rtld_error("%s: Unexpected inconsistency: dependency %s not found", obj->path, name); rtld_die(); } static int check_object_provided_version(Obj_Entry *refobj, const Obj_Entry *depobj, const Elf_Vernaux *vna) { const Elf_Verdef *vd; const char *vername; vername = refobj->strtab + vna->vna_name; vd = depobj->verdef; if (vd == NULL) { _rtld_error("%s: version %s required by %s not defined", depobj->path, vername, refobj->path); return (-1); } for (;;) { if (vd->vd_version != VER_DEF_CURRENT) { _rtld_error("%s: Unsupported version %d of Elf_Verdef entry", depobj->path, vd->vd_version); return (-1); } if (vna->vna_hash == vd->vd_hash) { const Elf_Verdaux *aux = (const Elf_Verdaux *) ((char *)vd + vd->vd_aux); if (strcmp(vername, depobj->strtab + aux->vda_name) == 0) return (0); } if (vd->vd_next == 0) break; vd = (const Elf_Verdef *) ((char *)vd + vd->vd_next); } if (vna->vna_flags & VER_FLG_WEAK) return (0); _rtld_error("%s: version %s required by %s not found", depobj->path, vername, refobj->path); return (-1); } static int rtld_verify_object_versions(Obj_Entry *obj) { const Elf_Verneed *vn; const Elf_Verdef *vd; const Elf_Verdaux *vda; const Elf_Vernaux *vna; const Obj_Entry *depobj; int maxvernum, vernum; if (obj->ver_checked) return (0); obj->ver_checked = true; maxvernum = 0; /* * Walk over defined and required version records and figure out * max index used by any of them. Do very basic sanity checking * while there. */ vn = obj->verneed; while (vn != NULL) { if (vn->vn_version != VER_NEED_CURRENT) { _rtld_error("%s: Unsupported version %d of Elf_Verneed entry", obj->path, vn->vn_version); return (-1); } vna = (const Elf_Vernaux *) ((char *)vn + vn->vn_aux); for (;;) { vernum = VER_NEED_IDX(vna->vna_other); if (vernum > maxvernum) maxvernum = vernum; if (vna->vna_next == 0) break; vna = (const Elf_Vernaux *) ((char *)vna + vna->vna_next); } if (vn->vn_next == 0) break; vn = (const Elf_Verneed *) ((char *)vn + vn->vn_next); } vd = obj->verdef; while (vd != NULL) { if (vd->vd_version != VER_DEF_CURRENT) { _rtld_error("%s: Unsupported version %d of Elf_Verdef entry", obj->path, vd->vd_version); return (-1); } vernum = VER_DEF_IDX(vd->vd_ndx); if (vernum > maxvernum) maxvernum = vernum; if (vd->vd_next == 0) break; vd = (const Elf_Verdef *) ((char *)vd + vd->vd_next); } if (maxvernum == 0) return (0); /* * Store version information in array indexable by version index. * Verify that object version requirements are satisfied along the * way. */ obj->vernum = maxvernum + 1; obj->vertab = xcalloc(obj->vernum, sizeof(Ver_Entry)); vd = obj->verdef; while (vd != NULL) { if ((vd->vd_flags & VER_FLG_BASE) == 0) { vernum = VER_DEF_IDX(vd->vd_ndx); assert(vernum <= maxvernum); vda = (const Elf_Verdaux *)((char *)vd + vd->vd_aux); obj->vertab[vernum].hash = vd->vd_hash; obj->vertab[vernum].name = obj->strtab + vda->vda_name; obj->vertab[vernum].file = NULL; obj->vertab[vernum].flags = 0; } if (vd->vd_next == 0) break; vd = (const Elf_Verdef *) ((char *)vd + vd->vd_next); } vn = obj->verneed; while (vn != NULL) { depobj = locate_dependency(obj, obj->strtab + vn->vn_file); if (depobj == NULL) return (-1); vna = (const Elf_Vernaux *) ((char *)vn + vn->vn_aux); for (;;) { if (check_object_provided_version(obj, depobj, vna)) return (-1); vernum = VER_NEED_IDX(vna->vna_other); assert(vernum <= maxvernum); obj->vertab[vernum].hash = vna->vna_hash; obj->vertab[vernum].name = obj->strtab + vna->vna_name; obj->vertab[vernum].file = obj->strtab + vn->vn_file; obj->vertab[vernum].flags = (vna->vna_other & VER_NEED_HIDDEN) ? VER_INFO_HIDDEN : 0; if (vna->vna_next == 0) break; vna = (const Elf_Vernaux *) ((char *)vna + vna->vna_next); } if (vn->vn_next == 0) break; vn = (const Elf_Verneed *) ((char *)vn + vn->vn_next); } return 0; } static int rtld_verify_versions(const Objlist *objlist) { Objlist_Entry *entry; int rc; rc = 0; STAILQ_FOREACH(entry, objlist, link) { /* * Skip dummy objects or objects that have their version requirements * already checked. */ if (entry->obj->strtab == NULL || entry->obj->vertab != NULL) continue; if (rtld_verify_object_versions(entry->obj) == -1) { rc = -1; if (ld_tracing == NULL) break; } } if (rc == 0 || ld_tracing != NULL) rc = rtld_verify_object_versions(&obj_rtld); return rc; } const Ver_Entry * fetch_ventry(const Obj_Entry *obj, unsigned long symnum) { Elf_Versym vernum; if (obj->vertab) { vernum = VER_NDX(obj->versyms[symnum]); if (vernum >= obj->vernum) { _rtld_error("%s: symbol %s has wrong verneed value %d", obj->path, obj->strtab + symnum, vernum); } else if (obj->vertab[vernum].hash != 0) { return &obj->vertab[vernum]; } } return NULL; } int _rtld_get_stack_prot(void) { return (stack_prot); } int _rtld_is_dlopened(void *arg) { Obj_Entry *obj; RtldLockState lockstate; int res; rlock_acquire(rtld_bind_lock, &lockstate); obj = dlcheck(arg); if (obj == NULL) obj = obj_from_addr(arg); if (obj == NULL) { _rtld_error("No shared object contains address"); lock_release(rtld_bind_lock, &lockstate); return (-1); } res = obj->dlopened ? 1 : 0; lock_release(rtld_bind_lock, &lockstate); return (res); } static void map_stacks_exec(RtldLockState *lockstate) { void (*thr_map_stacks_exec)(void); if ((max_stack_flags & PF_X) == 0 || (stack_prot & PROT_EXEC) != 0) return; thr_map_stacks_exec = (void (*)(void))(uintptr_t) get_program_var_addr("__pthread_map_stacks_exec", lockstate); if (thr_map_stacks_exec != NULL) { stack_prot |= PROT_EXEC; thr_map_stacks_exec(); } } void symlook_init(SymLook *dst, const char *name) { bzero(dst, sizeof(*dst)); dst->name = name; dst->hash = elf_hash(name); dst->hash_gnu = gnu_hash(name); } static void symlook_init_from_req(SymLook *dst, const SymLook *src) { dst->name = src->name; dst->hash = src->hash; dst->hash_gnu = src->hash_gnu; dst->ventry = src->ventry; dst->flags = src->flags; dst->defobj_out = NULL; dst->sym_out = NULL; dst->lockstate = src->lockstate; } /* * Parse a file descriptor number without pulling in more of libc (e.g. atoi). */ static int parse_libdir(const char *str) { static const int RADIX = 10; /* XXXJA: possibly support hex? */ const char *orig; int fd; char c; orig = str; fd = 0; for (c = *str; c != '\0'; c = *++str) { if (c < '0' || c > '9') return (-1); fd *= RADIX; fd += c - '0'; } /* Make sure we actually parsed something. */ if (str == orig) { _rtld_error("failed to parse directory FD from '%s'", str); return (-1); } return (fd); } /* * Overrides for libc_pic-provided functions. */ int __getosreldate(void) { size_t len; int oid[2]; int error, osrel; if (osreldate != 0) return (osreldate); oid[0] = CTL_KERN; oid[1] = KERN_OSRELDATE; osrel = 0; len = sizeof(osrel); error = sysctl(oid, 2, &osrel, &len, NULL, 0); if (error == 0 && osrel > 0 && len == sizeof(osrel)) osreldate = osrel; return (osreldate); } void exit(int status) { _exit(status); } void (*__cleanup)(void); int __isthreaded = 0; int _thread_autoinit_dummy_decl = 1; /* * No unresolved symbols for rtld. */ void __pthread_cxa_finalize(struct dl_phdr_info *a) { } void __stack_chk_fail(void) { _rtld_error("stack overflow detected; terminated"); rtld_die(); } __weak_reference(__stack_chk_fail, __stack_chk_fail_local); void __chk_fail(void) { _rtld_error("buffer overflow detected; terminated"); rtld_die(); } const char * rtld_strerror(int errnum) { if (errnum < 0 || errnum >= sys_nerr) return ("Unknown error"); return (sys_errlist[errnum]); } Index: user/alc/PQ_LAUNDRY/share/man/man4/ioat.4 =================================================================== --- user/alc/PQ_LAUNDRY/share/man/man4/ioat.4 (revision 292448) +++ user/alc/PQ_LAUNDRY/share/man/man4/ioat.4 (revision 292449) @@ -1,245 +1,247 @@ .\" Copyright (c) 2015 EMC / Isilon Storage Division .\" 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 AUTHORS 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 AUTHORS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" -.Dd December 14, 2015 +.Dd December 17, 2015 .Dt IOAT 4 .Os .Sh NAME .Nm I/OAT .Nd Intel I/O Acceleration Technology .Sh SYNOPSIS To compile this driver into your kernel, place the following line in your kernel configuration file: .Bd -ragged -offset indent .Cd "device ioat" .Ed .Pp Or, to load the driver as a module at boot, place the following line in .Xr loader.conf 5 : .Bd -literal -offset indent ioat_load="YES" .Ed .Pp In .Xr loader.conf 5 : .Pp .Cd hw.ioat.force_legacy_interrupts=0 .Pp In .Xr loader.conf 5 or .Xr sysctl.conf 5 : .Pp .Cd hw.ioat.enable_ioat_test=0 .Cd hw.ioat.debug_level=0 (only critical errors; maximum of 3) .Pp .Ft typedef void .Fn (*bus_dmaengine_callback_t) "void *arg" "int error" .Pp .Ft bus_dmaengine_t .Fn ioat_get_dmaengine "uint32_t channel_index" .Ft void .Fn ioat_put_dmaengine "bus_dmaengine_t dmaengine" +.Ft int +.Fn ioat_get_hwversion "bus_dmaengine_t dmaengine" .Ft int .Fn ioat_set_interrupt_coalesce "bus_dmaengine_t dmaengine" "uint16_t delay" .Ft uint16_t .Fn ioat_get_max_coalesce_period "bus_dmaengine_t dmaengine" .Ft void .Fn ioat_acquire "bus_dmaengine_t dmaengine" .Ft void .Fn ioat_release "bus_dmaengine_t dmaengine" .Ft struct bus_dmadesc * .Fo ioat_copy .Fa "bus_dmaengine_t dmaengine" .Fa "bus_addr_t dst" .Fa "bus_addr_t src" .Fa "bus_size_t len" .Fa "bus_dmaengine_callback_t callback_fn" .Fa "void *callback_arg" .Fa "uint32_t flags" .Fc .Ft struct bus_dmadesc * .Fo ioat_copy_8k_aligned .Fa "bus_dmaengine_t dmaengine" .Fa "bus_addr_t dst1" .Fa "bus_addr_t dst2" .Fa "bus_addr_t src1" .Fa "bus_addr_t src2" .Fa "bus_dmaengine_callback_t callback_fn" .Fa "void *callback_arg" .Fa "uint32_t flags" .Fc .Ft struct bus_dmadesc * .Fo ioat_blockfill .Fa "bus_dmaengine_t dmaengine" .Fa "bus_addr_t dst" .Fa "uint64_t fillpattern" .Fa "bus_size_t len" .Fa "bus_dmaengine_callback_t callback_fn" .Fa "void *callback_arg" .Fa "uint32_t flags" .Fc .Ft struct bus_dmadesc * .Fo ioat_null .Fa "bus_dmaengine_t dmaengine" .Fa "bus_dmaengine_callback_t callback_fn" .Fa "void *callback_arg" .Fa "uint32_t flags" .Fc .Sh DESCRIPTION The .Nm driver provides a kernel API to a variety of DMA engines on some Intel server platforms. .Pp There is a number of DMA channels per CPU package. (Typically 4 or 8.) Each may be used independently. Operations on a single channel proceed sequentially. .Pp Blockfill operations can be used to write a 64-bit pattern to memory. .Pp Copy operations can be used to offload memory copies to the DMA engines. .Pp Null operations do nothing, but may be used to test the interrupt and callback mechanism. .Pp All operations can optionally trigger an interrupt at completion with the .Ar DMA_EN_INT flag. For example, a user might submit multiple operations to the same channel and only enable an interrupt and callback for the last operation. .Pp The hardware can delay and coalesce interrupts on a given channel for a configurable period of time, in microseconds. This may be desired to reduce the processing and interrupt overhead per descriptor, especially for workflows consisting of many small operations. Software can control this on a per-channel basis with the .Fn ioat_set_interrupt_coalesce API. The .Fn ioat_get_max_coalesce_period API can be used to determine the maximum coalescing period supported by the hardware, in microseconds. Current platforms support up to a 16.383 millisecond coalescing period. Optimal configuration will vary by workflow and desired operation latency. .Pp All operations are safe to use in a non-blocking context with the .Ar DMA_NO_WAIT flag. (Of course, allocations may fail and operations requested with .Ar DMA_NO_WAIT may return NULL.) .Pp All operations, as well as .Fn ioat_get_dmaengine , can return NULL in special circumstances. For example, if the .Nm driver is being unloaded, or the administrator has induced a hardware reset, or a usage error has resulted in a hardware error state that needs to be recovered from. .Pp It is invalid to attempt to submit new DMA operations in a .Fa bus_dmaengine_callback_t context. .Sh USAGE A typical user will lookup the DMA engine object for a given channel with .Fn ioat_get_dmaengine . When the user wants to offload a copy, they will first .Fn ioat_acquire the .Ar bus_dmaengine_t object for exclusive access to enqueue operations on that channel. Then, they will submit one or more operations using .Fn ioat_blockfill , .Fn ioat_copy , or .Fn ioat_null . After queuing one or more individual DMA operations, they will .Fn ioat_release the .Ar bus_dmaengine_t to drop their exclusive access to the channel. The routine they provided for the .Fa callback_fn argument will be invoked with the provided .Fa callback_arg when the operation is complete. When they are finished with the .Ar bus_dmaengine_t , the user should .Fn ioat_put_dmaengine . .Pp Users MUST NOT block between .Fn ioat_acquire and .Fn ioat_release . Users SHOULD NOT hold .Ar bus_dmaengine_t references for a very long time to enable fault recovery and kernel module unload. .Pp For an example of usage, see .Pa src/sys/dev/ioat/ioat_test.c . .Sh FILES .Bl -tag .It Pa /dev/ioat_test test device for .Xr ioatcontrol 8 .El .Sh SEE ALSO .Xr ioatcontrol 8 .Sh HISTORY The .Nm driver first appeared in .Fx 11.0 . .Sh AUTHORS The .Nm driver was developed by .An \&Jim Harris Aq Mt jimharris@FreeBSD.org , .An \&Carl Delsey Aq Mt carl.r.delsey@intel.com , and .An \&Conrad Meyer Aq Mt cem@FreeBSD.org . This manual page was written by .An \&Conrad Meyer Aq Mt cem@FreeBSD.org . .Sh CAVEATS Copy operation takes bus addresses as parameters, not virtual addresses. .Pp Buffers for individual copy operations must be physically contiguous. .Pp Copies larger than max transfer size (1MB, but may vary by hardware) are not supported. Future versions will likely support this by breaking up the transfer into smaller sizes. .Sh BUGS The .Nm driver only supports blockfill, copy, and null operations at this time. The driver does not yet support advanced DMA modes, such as XOR, that some I/OAT devices support. Index: user/alc/PQ_LAUNDRY/share/man/man4 =================================================================== --- user/alc/PQ_LAUNDRY/share/man/man4 (revision 292448) +++ user/alc/PQ_LAUNDRY/share/man/man4 (revision 292449) Property changes on: user/alc/PQ_LAUNDRY/share/man/man4 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/share/man/man4:r292390-292448 Index: user/alc/PQ_LAUNDRY/share =================================================================== --- user/alc/PQ_LAUNDRY/share (revision 292448) +++ user/alc/PQ_LAUNDRY/share (revision 292449) Property changes on: user/alc/PQ_LAUNDRY/share ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/share:r292390-292448 Index: user/alc/PQ_LAUNDRY/sys/arm/allwinner/a20/a20_mp.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/allwinner/a20/a20_mp.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/allwinner/a20/a20_mp.c (revision 292449) @@ -1,162 +1,162 @@ /*- * Copyright (c) 2014 Ganbold Tsagaankhuu * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #define CPUCFG_BASE 0x01c25c00 #define CPUCFG_SIZE 0x400 #define CPU0_RST_CTL 0x40 #define CPU0_CTL 0x44 #define CPU0_STATUS 0x48 #define CPU1_RST_CTL 0x80 #define CPU1_CTL 0x84 #define CPU1_STATUS 0x88 #define CPUCFG_GENCTL 0x184 #define CPUCFG_P_REG0 0x1a4 #define CPU1_PWR_CLAMP 0x1b0 #define CPU1_PWROFF_REG 0x1b4 #define CPUCFG_DBGCTL0 0x1e0 #define CPUCFG_DBGCTL1 0x1e4 void platform_mp_init_secondary(void) { - arm_pic_init_secondary(); + intr_pic_init_secondary(); } void platform_mp_setmaxid(void) { int ncpu; if (mp_ncpus != 0) return; /* Read the number of cores from the CP15 L2 Control Register. */ __asm __volatile("mrc p15, 1, %0, c9, c0, 2" : "=r" (ncpu)); ncpu = ((ncpu >> 24) & 0x3) + 1; mp_ncpus = ncpu; mp_maxid = ncpu - 1; } int platform_mp_probe(void) { if (mp_ncpus == 0) platform_mp_setmaxid(); return (mp_ncpus > 1); } void platform_mp_start_ap(void) { bus_space_handle_t cpucfg; uint32_t val; if (bus_space_map(fdtbus_bs_tag, CPUCFG_BASE, CPUCFG_SIZE, 0, &cpucfg) != 0) panic("Couldn't map the CPUCFG\n"); cpu_idcache_wbinv_all(); cpu_l2cache_wbinv_all(); bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_P_REG0, pmap_kextract((vm_offset_t)mpentry)); /* * Assert nCOREPORESET low and set L1RSTDISABLE low. * Ensure DBGPWRDUP is set to LOW to prevent any external * debug access to the processor. */ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_RST_CTL, 0); /* Set L1RSTDISABLE low */ val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPUCFG_GENCTL); val &= ~(1 << 1); bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_GENCTL, val); /* Set DBGPWRDUP low */ val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1); val &= ~(1 << 1); bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1, val); /* Release power clamp */ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0xff); bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x7f); bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x3f); bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x1f); bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x0f); bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x07); bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x03); bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x01); bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWR_CLAMP, 0x00); DELAY(10000); /* Clear power-off gating */ val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPU1_PWROFF_REG); val &= ~(1 << 0); bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_PWROFF_REG, val); DELAY(1000); /* De-assert cpu core reset */ bus_space_write_4(fdtbus_bs_tag, cpucfg, CPU1_RST_CTL, 3); /* Assert DBGPWRDUP signal */ val = bus_space_read_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1); val |= (1 << 1); bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_DBGCTL1, val); armv7_sev(); bus_space_unmap(fdtbus_bs_tag, cpucfg, CPUCFG_SIZE); } void platform_ipi_send(cpuset_t cpus, u_int ipi) { pic_ipi_send(cpus, ipi); } Index: user/alc/PQ_LAUNDRY/sys/arm/altera/socfpga/socfpga_mp.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/altera/socfpga/socfpga_mp.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/altera/socfpga/socfpga_mp.c (revision 292449) @@ -1,183 +1,183 @@ /*- * Copyright (c) 2014 Ruslan Bukin * All rights reserved. * * This software was developed by SRI International and the University of * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) * ("CTSRD"), as part of the DARPA CRASH research programme. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #define SCU_PHYSBASE 0xFFFEC000 #define SCU_SIZE 0x100 #define SCU_CONTROL_REG 0x00 #define SCU_CONTROL_ENABLE (1 << 0) #define SCU_CONFIG_REG 0x04 #define SCU_CONFIG_REG_NCPU_MASK 0x03 #define SCU_CPUPOWER_REG 0x08 #define SCU_INV_TAGS_REG 0x0c #define SCU_DIAG_CONTROL 0x30 #define SCU_DIAG_DISABLE_MIGBIT (1 << 0) #define SCU_FILTER_START_REG 0x40 #define SCU_FILTER_END_REG 0x44 #define SCU_SECURE_ACCESS_REG 0x50 #define SCU_NONSECURE_ACCESS_REG 0x54 #define RSTMGR_PHYSBASE 0xFFD05000 #define RSTMGR_SIZE 0x100 #define MPUMODRST 0x10 #define MPUMODRST_CPU1 (1 << 1) #define RAM_PHYSBASE 0x0 #define RAM_SIZE 0x1000 extern char *mpentry_addr; static void socfpga_trampoline(void); static void socfpga_trampoline(void) { __asm __volatile( "ldr pc, 1f\n" ".globl mpentry_addr\n" "mpentry_addr:\n" "1: .space 4\n"); } void platform_mp_init_secondary(void) { - arm_pic_init_secondary(); + intr_pic_init_secondary(); } void platform_mp_setmaxid(void) { int hwcpu, ncpu; /* If we've already set this don't bother to do it again. */ if (mp_ncpus != 0) return; hwcpu = 2; ncpu = hwcpu; TUNABLE_INT_FETCH("hw.ncpu", &ncpu); if (ncpu < 1 || ncpu > hwcpu) ncpu = hwcpu; mp_ncpus = ncpu; mp_maxid = ncpu - 1; } int platform_mp_probe(void) { if (mp_ncpus == 0) platform_mp_setmaxid(); return (mp_ncpus > 1); } void platform_mp_start_ap(void) { bus_space_handle_t scu, rst, ram; int reg; if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0) panic("Couldn't map the SCU\n"); if (bus_space_map(fdtbus_bs_tag, RSTMGR_PHYSBASE, RSTMGR_SIZE, 0, &rst) != 0) panic("Couldn't map the reset manager (RSTMGR)\n"); if (bus_space_map(fdtbus_bs_tag, RAM_PHYSBASE, RAM_SIZE, 0, &ram) != 0) panic("Couldn't map the first physram page\n"); /* Invalidate SCU cache tags */ bus_space_write_4(fdtbus_bs_tag, scu, SCU_INV_TAGS_REG, 0x0000ffff); /* * Erratum ARM/MP: 764369 (problems with cache maintenance). * Setting the "disable-migratory bit" in the undocumented SCU * Diagnostic Control Register helps work around the problem. */ reg = bus_space_read_4(fdtbus_bs_tag, scu, SCU_DIAG_CONTROL); reg |= (SCU_DIAG_DISABLE_MIGBIT); bus_space_write_4(fdtbus_bs_tag, scu, SCU_DIAG_CONTROL, reg); /* Put CPU1 to reset state */ bus_space_write_4(fdtbus_bs_tag, rst, MPUMODRST, MPUMODRST_CPU1); /* Enable the SCU, then clean the cache on this core */ reg = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG); reg |= (SCU_CONTROL_ENABLE); bus_space_write_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG, reg); /* Set up trampoline code */ mpentry_addr = (char *)pmap_kextract((vm_offset_t)mpentry); bus_space_write_region_4(fdtbus_bs_tag, ram, 0, (uint32_t *)&socfpga_trampoline, 8); cpu_idcache_wbinv_all(); cpu_l2cache_wbinv_all(); /* Put CPU1 out from reset */ bus_space_write_4(fdtbus_bs_tag, rst, MPUMODRST, 0); armv7_sev(); bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE); bus_space_unmap(fdtbus_bs_tag, rst, RSTMGR_SIZE); bus_space_unmap(fdtbus_bs_tag, ram, RAM_SIZE); } void platform_ipi_send(cpuset_t cpus, u_int ipi) { pic_ipi_send(cpus, ipi); } Index: user/alc/PQ_LAUNDRY/sys/arm/amlogic/aml8726/aml8726_mp.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/amlogic/aml8726/aml8726_mp.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/amlogic/aml8726/aml8726_mp.c (revision 292449) @@ -1,660 +1,660 @@ /*- * Copyright 2015 John Wehle * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Amlogic aml8726 multiprocessor support. * * Some processors require powering on which involves poking registers * on the aobus and cbus ... it's expected that these locations are set * in stone. * * Locking is not used as these routines should only be called by the BP * during startup and should complete prior to the APs being released (the * issue being to ensure that a register such as AML_SOC_CPU_CLK_CNTL_REG * is not concurrently modified). */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const char *scu_compatible[] = { "arm,cortex-a5-scu", "arm,cortex-a9-scu", NULL }; static const char *scu_errata_764369[] = { "arm,cortex-a9-scu", NULL }; static const char *cpucfg_compatible[] = { "amlogic,aml8726-cpuconfig", NULL }; static struct { boolean_t errata_764369; u_long scu_size; struct resource scu_res; u_long cpucfg_size; struct resource cpucfg_res; struct resource aobus_res; struct resource cbus_res; } aml8726_smp; #define AML_SCU_CONTROL_REG 0 #define AML_SCU_CONTROL_ENABLE 1 #define AML_SCU_CONFIG_REG 4 #define AML_SCU_CONFIG_NCPU_MASK 0x3 #define AML_SCU_CPU_PWR_STATUS_REG 8 #define AML_SCU_CPU_PWR_STATUS_CPU3_MASK (3 << 24) #define AML_SCU_CPU_PWR_STATUS_CPU2_MASK (3 << 16) #define AML_SCU_CPU_PWR_STATUS_CPU1_MASK (3 << 8) #define AML_SCU_CPU_PWR_STATUS_CPU0_MASK 3 #define AML_SCU_INV_TAGS_REG 12 #define AML_SCU_DIAG_CONTROL_REG 48 #define AML_SCU_DIAG_CONTROL_DISABLE_MIGBIT 1 #define AML_CPUCONF_CONTROL_REG 0 #define AML_CPUCONF_CPU1_ADDR_REG 4 #define AML_CPUCONF_CPU2_ADDR_REG 8 #define AML_CPUCONF_CPU3_ADDR_REG 12 /* aobus */ #define AML_M8_CPU_PWR_CNTL0_REG 0xe0 #define AML_M8B_CPU_PWR_CNTL0_MODE_CPU3_MASK (3 << 22) #define AML_M8B_CPU_PWR_CNTL0_MODE_CPU2_MASK (3 << 20) #define AML_M8B_CPU_PWR_CNTL0_MODE_CPU1_MASK (3 << 18) #define AML_M8_CPU_PWR_CNTL0_ISO_CPU3 (1 << 3) #define AML_M8_CPU_PWR_CNTL0_ISO_CPU2 (1 << 2) #define AML_M8_CPU_PWR_CNTL0_ISO_CPU1 (1 << 1) #define AML_M8_CPU_PWR_CNTL1_REG 0xe4 #define AML_M8B_CPU_PWR_CNTL1_PWR_CPU3 (1 << 19) #define AML_M8B_CPU_PWR_CNTL1_PWR_CPU2 (1 << 18) #define AML_M8B_CPU_PWR_CNTL1_PWR_CPU1 (1 << 17) #define AML_M8_CPU_PWR_CNTL1_MODE_CPU3_MASK (3 << 8) #define AML_M8_CPU_PWR_CNTL1_MODE_CPU2_MASK (3 << 6) #define AML_M8_CPU_PWR_CNTL1_MODE_CPU1_MASK (3 << 4) #define AML_M8B_CPU_PWR_MEM_PD0_REG 0xf4 #define AML_M8B_CPU_PWR_MEM_PD0_CPU3 (0xf << 20) #define AML_M8B_CPU_PWR_MEM_PD0_CPU2 (0xf << 24) #define AML_M8B_CPU_PWR_MEM_PD0_CPU1 (0xf << 28) /* cbus */ #define AML_SOC_CPU_CLK_CNTL_REG 0x419c #define AML_M8_CPU_CLK_CNTL_RESET_CPU3 (1 << 27) #define AML_M8_CPU_CLK_CNTL_RESET_CPU2 (1 << 26) #define AML_M8_CPU_CLK_CNTL_RESET_CPU1 (1 << 25) #define SCU_WRITE_4(reg, value) bus_write_4(&aml8726_smp.scu_res, \ (reg), (value)) #define SCU_READ_4(reg) bus_read_4(&aml8726_smp.scu_res, (reg)) #define SCU_BARRIER(reg) bus_barrier(&aml8726_smp.scu_res, \ (reg), 4, (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) #define CPUCONF_WRITE_4(reg, value) bus_write_4(&aml8726_smp.cpucfg_res, \ (reg), (value)) #define CPUCONF_READ_4(reg) bus_read_4(&aml8726_smp.cpucfg_res, \ (reg)) #define CPUCONF_BARRIER(reg) bus_barrier(&aml8726_smp.cpucfg_res, \ (reg), 4, (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) #define AOBUS_WRITE_4(reg, value) bus_write_4(&aml8726_smp.aobus_res, \ (reg), (value)) #define AOBUS_READ_4(reg) bus_read_4(&aml8726_smp.aobus_res, \ (reg)) #define AOBUS_BARRIER(reg) bus_barrier(&aml8726_smp.aobus_res, \ (reg), 4, (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) #define CBUS_WRITE_4(reg, value) bus_write_4(&aml8726_smp.cbus_res, \ (reg), (value)) #define CBUS_READ_4(reg) bus_read_4(&aml8726_smp.cbus_res, \ (reg)) #define CBUS_BARRIER(reg) bus_barrier(&aml8726_smp.cbus_res, \ (reg), 4, (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)) static phandle_t find_node_for_device(const char *device, const char **compatible) { int i; phandle_t node; /* * Try to access the node directly i.e. through /aliases/. */ if ((node = OF_finddevice(device)) != 0) for (i = 0; compatible[i]; i++) if (fdt_is_compatible_strict(node, compatible[i])) return node; /* * Find the node the long way. */ for (i = 0; compatible[i]; i++) { if ((node = OF_finddevice("/soc")) == 0) return (0); if ((node = fdt_find_compatible(node, compatible[i], 1)) != 0) return node; } return (0); } static int alloc_resource_for_node(phandle_t node, struct resource *res, u_long *size) { int err; u_long pbase, psize; u_long start; if ((err = fdt_get_range(OF_parent(node), 0, &pbase, &psize)) != 0 || (err = fdt_regsize(node, &start, size)) != 0) return (err); start += pbase; memset(res, 0, sizeof(*res)); res->r_bustag = fdtbus_bs_tag; err = bus_space_map(res->r_bustag, start, *size, 0, &res->r_bushandle); return (err); } static void power_on_cpu(int cpu) { uint32_t scpsr; uint32_t value; if (cpu <= 0) return; /* * Power on the CPU if the intricate details are known, otherwise * just hope for the best (it may have already be powered on by * the hardware / firmware). */ switch (aml8726_soc_hw_rev) { case AML_SOC_HW_REV_M8: case AML_SOC_HW_REV_M8B: /* * Set the SCU power status for the CPU to normal mode. */ scpsr = SCU_READ_4(AML_SCU_CPU_PWR_STATUS_REG); scpsr &= ~(AML_SCU_CPU_PWR_STATUS_CPU1_MASK << ((cpu - 1) * 8)); SCU_WRITE_4(AML_SCU_CPU_PWR_STATUS_REG, scpsr); SCU_BARRIER(AML_SCU_CPU_PWR_STATUS_REG); if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) { /* * Reset may cause the current power status from the * actual CPU to be written to the SCU (over-writing * the value we've just written) so set it to normal * mode as well. */ value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL0_REG); value &= ~(AML_M8B_CPU_PWR_CNTL0_MODE_CPU1_MASK << ((cpu - 1) * 2)); AOBUS_WRITE_4(AML_M8_CPU_PWR_CNTL0_REG, value); AOBUS_BARRIER(AML_M8_CPU_PWR_CNTL0_REG); } DELAY(5); /* * Assert reset. */ value = CBUS_READ_4(AML_SOC_CPU_CLK_CNTL_REG); value |= AML_M8_CPU_CLK_CNTL_RESET_CPU1 << (cpu - 1); CBUS_WRITE_4(AML_SOC_CPU_CLK_CNTL_REG, value); CBUS_BARRIER(AML_SOC_CPU_CLK_CNTL_REG); if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) { /* * Release RAM pull-down. */ value = AOBUS_READ_4(AML_M8B_CPU_PWR_MEM_PD0_REG); value &= ~((uint32_t)AML_M8B_CPU_PWR_MEM_PD0_CPU1 >> ((cpu - 1) * 4)); AOBUS_WRITE_4(AML_M8B_CPU_PWR_MEM_PD0_REG, value); AOBUS_BARRIER(AML_M8B_CPU_PWR_MEM_PD0_REG); } /* * Power on CPU. */ value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL1_REG); value &= ~(AML_M8_CPU_PWR_CNTL1_MODE_CPU1_MASK << ((cpu - 1) * 2)); AOBUS_WRITE_4(AML_M8_CPU_PWR_CNTL1_REG, value); AOBUS_BARRIER(AML_M8_CPU_PWR_CNTL1_REG); DELAY(10); if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) { /* * Wait for power on confirmation. */ for ( ; ; ) { value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL1_REG); value &= AML_M8B_CPU_PWR_CNTL1_PWR_CPU1 << (cpu - 1); if (value) break; DELAY(10); } } /* * Release peripheral clamp. */ value = AOBUS_READ_4(AML_M8_CPU_PWR_CNTL0_REG); value &= ~(AML_M8_CPU_PWR_CNTL0_ISO_CPU1 << (cpu - 1)); AOBUS_WRITE_4(AML_M8_CPU_PWR_CNTL0_REG, value); AOBUS_BARRIER(AML_M8_CPU_PWR_CNTL0_REG); /* * Release reset. */ value = CBUS_READ_4(AML_SOC_CPU_CLK_CNTL_REG); value &= ~(AML_M8_CPU_CLK_CNTL_RESET_CPU1 << (cpu - 1)); CBUS_WRITE_4(AML_SOC_CPU_CLK_CNTL_REG, value); CBUS_BARRIER(AML_SOC_CPU_CLK_CNTL_REG); if (aml8726_soc_hw_rev == AML_SOC_HW_REV_M8B) { /* * The Amlogic Linux platform code sets the SCU power * status for the CPU again for some reason so we * follow suit (perhaps in case the reset caused * a stale power status from the actual CPU to be * written to the SCU). */ SCU_WRITE_4(AML_SCU_CPU_PWR_STATUS_REG, scpsr); SCU_BARRIER(AML_SCU_CPU_PWR_STATUS_REG); } break; default: break; } } void platform_mp_init_secondary(void) { /* * Consider modifying the timer driver to support * per-cpu timers and then enabling the timer for * each AP. */ - arm_pic_init_secondary(); + intr_pic_init_secondary(); } void platform_mp_setmaxid(void) { int err; int i; int ncpu; phandle_t cpucfg_node; phandle_t scu_node; uint32_t value; if (mp_ncpus != 0) return; ncpu = 1; /* * Is the hardware necessary for SMP present? */ if ((scu_node = find_node_for_device("scu", scu_compatible)) == 0) goto moveon; if ((cpucfg_node = find_node_for_device("cpuconfig", cpucfg_compatible)) == 0) goto moveon; if (alloc_resource_for_node(scu_node, &aml8726_smp.scu_res, &aml8726_smp.scu_size) != 0) panic("Could not allocate resource for SCU"); if (alloc_resource_for_node(cpucfg_node, &aml8726_smp.cpucfg_res, &aml8726_smp.cpucfg_size) != 0) panic("Could not allocate resource for CPUCONFIG"); /* * Strictly speaking the aobus and cbus may not be required in * order to start an AP (it depends on the processor), however * always mapping them in simplifies the code. */ aml8726_smp.aobus_res.r_bustag = fdtbus_bs_tag; err = bus_space_map(aml8726_smp.aobus_res.r_bustag, AML_SOC_AOBUS_BASE_ADDR, 0x100000, 0, &aml8726_smp.aobus_res.r_bushandle); if (err) panic("Could not allocate resource for AOBUS"); aml8726_smp.cbus_res.r_bustag = fdtbus_bs_tag; err = bus_space_map(aml8726_smp.cbus_res.r_bustag, AML_SOC_CBUS_BASE_ADDR, 0x100000, 0, &aml8726_smp.cbus_res.r_bushandle); if (err) panic("Could not allocate resource for CBUS"); aml8726_smp.errata_764369 = false; for (i = 0; scu_errata_764369[i]; i++) if (fdt_is_compatible_strict(scu_node, scu_errata_764369[i])) { aml8726_smp.errata_764369 = true; break; } /* * Read the number of CPUs present. */ value = SCU_READ_4(AML_SCU_CONFIG_REG); ncpu = (value & AML_SCU_CONFIG_NCPU_MASK) + 1; moveon: mp_ncpus = ncpu; mp_maxid = ncpu - 1; } int platform_mp_probe(void) { if (mp_ncpus == 0) platform_mp_setmaxid(); return (mp_ncpus > 1); } void platform_mp_start_ap(void) { int i; uint32_t reg; uint32_t value; vm_paddr_t paddr; if (mp_ncpus < 2) return; /* * Invalidate SCU cache tags. The 0x0000ffff constant invalidates * all ways on all cores 0-3. Per the ARM docs, it's harmless to * write to the bits for cores that are not present. */ SCU_WRITE_4(AML_SCU_INV_TAGS_REG, 0x0000ffff); if (aml8726_smp.errata_764369) { /* * Erratum ARM/MP: 764369 (problems with cache maintenance). * Setting the "disable-migratory bit" in the undocumented SCU * Diagnostic Control Register helps work around the problem. */ value = SCU_READ_4(AML_SCU_DIAG_CONTROL_REG); value |= AML_SCU_DIAG_CONTROL_DISABLE_MIGBIT; SCU_WRITE_4(AML_SCU_DIAG_CONTROL_REG, value); } /* * Enable the SCU, then clean the cache on this core. After these * two operations the cache tag ram in the SCU is coherent with * the contents of the cache on this core. The other cores aren't * running yet so their caches can't contain valid data yet, however * we've initialized their SCU tag ram above, so they will be * coherent from startup. */ value = SCU_READ_4(AML_SCU_CONTROL_REG); value |= AML_SCU_CONTROL_ENABLE; SCU_WRITE_4(AML_SCU_CONTROL_REG, value); SCU_BARRIER(AML_SCU_CONTROL_REG); cpu_idcache_wbinv_all(); /* Set the boot address and power on each AP. */ paddr = pmap_kextract((vm_offset_t)mpentry); for (i = 1; i < mp_ncpus; i++) { reg = AML_CPUCONF_CPU1_ADDR_REG + ((i - 1) * 4); CPUCONF_WRITE_4(reg, paddr); CPUCONF_BARRIER(reg); power_on_cpu(i); } /* * Enable the APs. * * The Amlogic Linux platform code sets the lsb for some reason * in addition to the enable bit for each AP so we follow suit * (the lsb may be the enable bit for the BP, though in that case * it should already be set since it's currently running). */ value = CPUCONF_READ_4(AML_CPUCONF_CONTROL_REG); value |= 1; for (i = 1; i < mp_ncpus; i++) value |= (1 << i); CPUCONF_WRITE_4(AML_CPUCONF_CONTROL_REG, value); CPUCONF_BARRIER(AML_CPUCONF_CONTROL_REG); /* Wakeup the now enabled APs */ armv7_sev(); /* * Free the resources which are not needed after startup. */ bus_space_unmap(aml8726_smp.scu_res.r_bustag, aml8726_smp.scu_res.r_bushandle, aml8726_smp.scu_size); bus_space_unmap(aml8726_smp.cpucfg_res.r_bustag, aml8726_smp.cpucfg_res.r_bushandle, aml8726_smp.cpucfg_size); bus_space_unmap(aml8726_smp.aobus_res.r_bustag, aml8726_smp.aobus_res.r_bushandle, 0x100000); bus_space_unmap(aml8726_smp.cbus_res.r_bustag, aml8726_smp.cbus_res.r_bushandle, 0x100000); memset(&aml8726_smp, 0, sizeof(aml8726_smp)); } void platform_ipi_send(cpuset_t cpus, u_int ipi) { pic_ipi_send(cpus, ipi); } /* * Stub drivers for cosmetic purposes. */ struct aml8726_scu_softc { device_t dev; }; static int aml8726_scu_probe(device_t dev) { int i; for (i = 0; scu_compatible[i]; i++) if (ofw_bus_is_compatible(dev, scu_compatible[i])) break; if (!scu_compatible[i]) return (ENXIO); device_set_desc(dev, "ARM Snoop Control Unit"); return (BUS_PROBE_DEFAULT); } static int aml8726_scu_attach(device_t dev) { struct aml8726_scu_softc *sc = device_get_softc(dev); sc->dev = dev; return (0); } static int aml8726_scu_detach(device_t dev) { return (0); } static device_method_t aml8726_scu_methods[] = { /* Device interface */ DEVMETHOD(device_probe, aml8726_scu_probe), DEVMETHOD(device_attach, aml8726_scu_attach), DEVMETHOD(device_detach, aml8726_scu_detach), DEVMETHOD_END }; static driver_t aml8726_scu_driver = { "scu", aml8726_scu_methods, sizeof(struct aml8726_scu_softc), }; static devclass_t aml8726_scu_devclass; EARLY_DRIVER_MODULE(scu, simplebus, aml8726_scu_driver, aml8726_scu_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_MIDDLE); struct aml8726_cpucfg_softc { device_t dev; }; static int aml8726_cpucfg_probe(device_t dev) { int i; for (i = 0; cpucfg_compatible[i]; i++) if (ofw_bus_is_compatible(dev, cpucfg_compatible[i])) break; if (!cpucfg_compatible[i]) return (ENXIO); device_set_desc(dev, "Amlogic CPU Config"); return (BUS_PROBE_DEFAULT); } static int aml8726_cpucfg_attach(device_t dev) { struct aml8726_cpucfg_softc *sc = device_get_softc(dev); sc->dev = dev; return (0); } static int aml8726_cpucfg_detach(device_t dev) { return (0); } static device_method_t aml8726_cpucfg_methods[] = { /* Device interface */ DEVMETHOD(device_probe, aml8726_cpucfg_probe), DEVMETHOD(device_attach, aml8726_cpucfg_attach), DEVMETHOD(device_detach, aml8726_cpucfg_detach), DEVMETHOD_END }; static driver_t aml8726_cpucfg_driver = { "cpuconfig", aml8726_cpucfg_methods, sizeof(struct aml8726_cpucfg_softc), }; static devclass_t aml8726_cpucfg_devclass; EARLY_DRIVER_MODULE(cpuconfig, simplebus, aml8726_cpucfg_driver, aml8726_cpucfg_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_MIDDLE); Index: user/alc/PQ_LAUNDRY/sys/arm/annapurna/alpine/alpine_machdep_mp.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/annapurna/alpine/alpine_machdep_mp.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/annapurna/alpine/alpine_machdep_mp.c (revision 292449) @@ -1,333 +1,333 @@ /*- * Copyright (c) 2013 Ruslan Bukin * Copyright (c) 2015 Semihalf * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define AL_CPU_RESUME_WATERMARK_REG 0x00 #define AL_CPU_RESUME_FLAGS_REG 0x04 #define AL_CPU_RESUME_PCPU_RADDR_REG(cpu) (0x08 + 0x04 + 8*(cpu)) #define AL_CPU_RESUME_PCPU_FLAGS(cpu) (0x08 + 8*(cpu)) /* Per-CPU flags */ #define AL_CPU_RESUME_FLG_PERCPU_DONT_RESUME (1 << 2) /* The expected magic number for validating the resume addresses */ #define AL_CPU_RESUME_MAGIC_NUM 0xf0e1d200 #define AL_CPU_RESUME_MAGIC_NUM_MASK 0xffffff00 /* The expected minimal version number for validating the capabilities */ #define AL_CPU_RESUME_MIN_VER 0x000000c3 #define AL_CPU_RESUME_MIN_VER_MASK 0x000000ff /* Field controlling the boot-up of companion cores */ #define AL_NB_INIT_CONTROL (0x8) #define AL_NB_CONFIG_STATUS_PWR_CTRL(cpu) (0x2020 + (cpu)*0x100) #define SERDES_NUM_GROUPS 4 #define SERDES_GROUP_SIZE 0x400 extern bus_addr_t al_devmap_pa; extern bus_addr_t al_devmap_size; extern void mpentry(void); int alpine_serdes_resource_get(uint32_t group, bus_space_tag_t *tag, bus_addr_t *baddr); static int platform_mp_get_core_cnt(void); static int alpine_get_cpu_resume_base(u_long *pbase, u_long *psize); static int alpine_get_nb_base(u_long *pbase, u_long *psize); static int alpine_get_serdes_base(u_long *pbase, u_long *psize); int alpine_serdes_resource_get(uint32_t group, bus_space_tag_t *tag, bus_addr_t *baddr); static boolean_t alpine_validate_cpu(u_int, phandle_t, u_int, pcell_t *); static boolean_t alpine_validate_cpu(u_int id, phandle_t child, u_int addr_cell, pcell_t *reg) { return fdt_is_compatible(child, "arm,cortex-a15"); } static int platform_mp_get_core_cnt(void) { static int ncores = 0; int nchilds; uint32_t reg; /* Calculate ncores value only once */ if (ncores) return (ncores); reg = cp15_l2ctlr_get(); ncores = CPUV7_L2CTLR_NPROC(reg); nchilds = ofw_cpu_early_foreach(alpine_validate_cpu, false); /* Limit CPUs if DTS has configured less than available */ if ((nchilds > 0) && (nchilds < ncores)) { printf("SMP: limiting number of active CPUs to %d out of %d\n", nchilds, ncores); ncores = nchilds; } return (ncores); } void platform_mp_init_secondary(void) { - arm_pic_init_secondary(); + intr_pic_init_secondary(); } void platform_mp_setmaxid(void) { mp_ncpus = platform_mp_get_core_cnt(); mp_maxid = mp_ncpus - 1; } int platform_mp_probe(void) { return (1); } static int alpine_get_cpu_resume_base(u_long *pbase, u_long *psize) { phandle_t node; u_long base = 0; u_long size = 0; if (pbase == NULL || psize == NULL) return (EINVAL); if ((node = OF_finddevice("/")) == -1) return (EFAULT); if ((node = ofw_bus_find_compatible(node, "annapurna-labs,al-cpu-resume")) == 0) return (EFAULT); if (fdt_regsize(node, &base, &size)) return (EFAULT); *pbase = base; *psize = size; return (0); } static int alpine_get_nb_base(u_long *pbase, u_long *psize) { phandle_t node; u_long base = 0; u_long size = 0; if (pbase == NULL || psize == NULL) return (EINVAL); if ((node = OF_finddevice("/")) == -1) return (EFAULT); if ((node = ofw_bus_find_compatible(node, "annapurna-labs,al-nb-service")) == 0) return (EFAULT); if (fdt_regsize(node, &base, &size)) return (EFAULT); *pbase = base; *psize = size; return (0); } void platform_mp_start_ap(void) { uint32_t physaddr; vm_offset_t vaddr; uint32_t val; uint32_t start_mask; u_long cpu_resume_base; u_long nb_base; u_long cpu_resume_size; u_long nb_size; bus_addr_t cpu_resume_baddr; bus_addr_t nb_baddr; int a; if (alpine_get_cpu_resume_base(&cpu_resume_base, &cpu_resume_size)) panic("Couldn't resolve cpu_resume_base address\n"); if (alpine_get_nb_base(&nb_base, &nb_size)) panic("Couldn't resolve_nb_base address\n"); /* Proceed with start addresses for additional CPUs */ if (bus_space_map(fdtbus_bs_tag, al_devmap_pa + cpu_resume_base, cpu_resume_size, 0, &cpu_resume_baddr)) panic("Couldn't map CPU-resume area"); if (bus_space_map(fdtbus_bs_tag, al_devmap_pa + nb_base, nb_size, 0, &nb_baddr)) panic("Couldn't map NB-service area"); /* Proceed with start addresses for additional CPUs */ val = bus_space_read_4(fdtbus_bs_tag, cpu_resume_baddr, AL_CPU_RESUME_WATERMARK_REG); if (((val & AL_CPU_RESUME_MAGIC_NUM_MASK) != AL_CPU_RESUME_MAGIC_NUM) || ((val & AL_CPU_RESUME_MIN_VER_MASK) < AL_CPU_RESUME_MIN_VER)) { panic("CPU-resume device is not compatible"); } vaddr = (vm_offset_t)mpentry; physaddr = pmap_kextract(vaddr); for (a = 1; a < platform_mp_get_core_cnt(); a++) { /* Power up the core */ bus_space_write_4(fdtbus_bs_tag, nb_baddr, AL_NB_CONFIG_STATUS_PWR_CTRL(a), 0); mb(); /* Enable resume */ val = bus_space_read_4(fdtbus_bs_tag, cpu_resume_baddr, AL_CPU_RESUME_PCPU_FLAGS(a)); val &= ~AL_CPU_RESUME_FLG_PERCPU_DONT_RESUME; bus_space_write_4(fdtbus_bs_tag, cpu_resume_baddr, AL_CPU_RESUME_PCPU_FLAGS(a), val); mb(); /* Set resume physical address */ bus_space_write_4(fdtbus_bs_tag, cpu_resume_baddr, AL_CPU_RESUME_PCPU_RADDR_REG(a), physaddr); mb(); } /* Release cores from reset */ if (bus_space_map(fdtbus_bs_tag, al_devmap_pa + nb_base, nb_size, 0, &nb_baddr)) panic("Couldn't map NB-service area"); start_mask = (1 << platform_mp_get_core_cnt()) - 1; /* Release cores from reset */ val = bus_space_read_4(fdtbus_bs_tag, nb_baddr, AL_NB_INIT_CONTROL); val |= start_mask; bus_space_write_4(fdtbus_bs_tag, nb_baddr, AL_NB_INIT_CONTROL, val); dsb(); bus_space_unmap(fdtbus_bs_tag, nb_baddr, nb_size); bus_space_unmap(fdtbus_bs_tag, cpu_resume_baddr, cpu_resume_size); } static int alpine_get_serdes_base(u_long *pbase, u_long *psize) { phandle_t node; u_long base = 0; u_long size = 0; if (pbase == NULL || psize == NULL) return (EINVAL); if ((node = OF_finddevice("/")) == -1) return (EFAULT); if ((node = ofw_bus_find_compatible(node, "annapurna-labs,al-serdes")) == 0) return (EFAULT); if (fdt_regsize(node, &base, &size)) return (EFAULT); *pbase = base; *psize = size; return (0); } int alpine_serdes_resource_get(uint32_t group, bus_space_tag_t *tag, bus_addr_t *baddr) { u_long serdes_base, serdes_size; int ret; static bus_addr_t baddr_mapped[SERDES_NUM_GROUPS]; if (group >= SERDES_NUM_GROUPS) return (EINVAL); if (baddr_mapped[group]) { *tag = fdtbus_bs_tag; *baddr = baddr_mapped[group]; return (0); } ret = alpine_get_serdes_base(&serdes_base, &serdes_size); if (ret) return (ret); ret = bus_space_map(fdtbus_bs_tag, al_devmap_pa + serdes_base + group * SERDES_GROUP_SIZE, (SERDES_NUM_GROUPS - group) * SERDES_GROUP_SIZE, 0, baddr); if (ret) return (ret); baddr_mapped[group] = *baddr; return (0); } void platform_ipi_send(cpuset_t cpus, u_int ipi) { pic_ipi_send(cpus, ipi); } Index: user/alc/PQ_LAUNDRY/sys/arm/arm/pic_if.m =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/arm/pic_if.m (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/arm/pic_if.m (nonexistent) @@ -1,124 +0,0 @@ -#- -# Copyright (c) 2012 Jakub Wojciech Klama -# Copyright (c) 2015 Svatopluk Kraus -# Copyright (c) 2015 Michal Meloun -# 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 AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# $FreeBSD$ -# - -#include -#include -#include -#include - -INTERFACE pic; - -CODE { - static int null_pic_bind(device_t dev, struct arm_irqsrc *isrc) - { - return (EOPNOTSUPP); - } - - static void null_pic_disable_intr(device_t dev, struct arm_irqsrc *isrc) - { - return; - } - - static void null_pic_enable_intr(device_t dev, struct arm_irqsrc *isrc) - { - return; - } - - static void null_pic_init_secondary(device_t dev) - { - return; - } - - static void null_pic_ipi_send(device_t dev, cpuset_t cpus, u_int ipi) - { - return; - } -}; - -METHOD int register { - device_t dev; - struct arm_irqsrc *isrc; - boolean_t *is_percpu; -}; - -METHOD int unregister { - device_t dev; - struct arm_irqsrc *isrc; -}; - -METHOD void disable_intr { - device_t dev; - struct arm_irqsrc *isrc; -} DEFAULT null_pic_disable_intr; - -METHOD void disable_source { - device_t dev; - struct arm_irqsrc *isrc; -}; - -METHOD void enable_source { - device_t dev; - struct arm_irqsrc *isrc; -}; - -METHOD void enable_intr { - device_t dev; - struct arm_irqsrc *isrc; -} DEFAULT null_pic_enable_intr; - -METHOD void pre_ithread { - device_t dev; - struct arm_irqsrc *isrc; -}; - -METHOD void post_ithread { - device_t dev; - struct arm_irqsrc *isrc; -}; - -METHOD void post_filter { - device_t dev; - struct arm_irqsrc *isrc; -}; - -METHOD int bind { - device_t dev; - struct arm_irqsrc *isrc; -} DEFAULT null_pic_bind; - -METHOD void init_secondary { - device_t dev; -} DEFAULT null_pic_init_secondary; - -METHOD void ipi_send { - device_t dev; - struct arm_irqsrc *isrc; - cpuset_t cpus; -} DEFAULT null_pic_ipi_send; Property changes on: user/alc/PQ_LAUNDRY/sys/arm/arm/pic_if.m ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/arm/arm/intrng.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/arm/intrng.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/arm/intrng.c (nonexistent) @@ -1,1458 +0,0 @@ -/*- - * Copyright (c) 2012-2014 Jakub Wojciech Klama . - * Copyright (c) 2015 Svatopluk Kraus - * Copyright (c) 2015 Michal Meloun - * 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 AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include -__FBSDID("$FreeBSD$"); - -/* - * ARM Interrupt Framework - * - * TODO: - to support IPI (PPI) enabling on other CPUs if already started - * - to complete things for removable PICs - */ - -#include "opt_ddb.h" -#include "opt_platform.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#ifdef DDB -#include -#endif - -#include "pic_if.h" - -#define INTRNAME_LEN (2*MAXCOMLEN + 1) - -#ifdef DEBUG -#define debugf(fmt, args...) do { printf("%s(): ", __func__); \ - printf(fmt,##args); } while (0) -#else -#define debugf(fmt, args...) -#endif - -MALLOC_DECLARE(M_INTRNG); -MALLOC_DEFINE(M_INTRNG, "intrng", "ARM interrupt handling"); - -/* Main ARM interrupt handler called from assembler -> 'hidden' for C code. */ -void arm_irq_handler(struct trapframe *tf); - -/* Root interrupt controller stuff. */ -static struct arm_irqsrc *irq_root_isrc; -static device_t irq_root_dev; -static arm_irq_filter_t *irq_root_filter; -static void *irq_root_arg; -static u_int irq_root_ipicount; - -/* Interrupt controller definition. */ -struct arm_pic { - SLIST_ENTRY(arm_pic) pic_next; - intptr_t pic_xref; /* hardware identification */ - device_t pic_dev; -}; - -static struct mtx pic_list_lock; -static SLIST_HEAD(, arm_pic) pic_list; - -static struct arm_pic *pic_lookup(device_t dev, intptr_t xref); - -/* Interrupt source definition. */ -static struct mtx isrc_table_lock; -static struct arm_irqsrc *irq_sources[NIRQ]; -u_int irq_next_free; - -#define IRQ_INVALID nitems(irq_sources) - -#ifdef SMP -static boolean_t irq_assign_cpu = FALSE; - -static struct arm_irqsrc ipi_sources[ARM_IPI_COUNT]; -static u_int ipi_next_num; -#endif - -/* - * - 2 counters for each I/O interrupt. - * - MAXCPU counters for each IPI counters for SMP. - */ -#ifdef SMP -#define INTRCNT_COUNT (NIRQ * 2 + ARM_IPI_COUNT * MAXCPU) -#else -#define INTRCNT_COUNT (NIRQ * 2) -#endif - -/* Data for MI statistics reporting. */ -u_long intrcnt[INTRCNT_COUNT]; -char intrnames[INTRCNT_COUNT * INTRNAME_LEN]; -size_t sintrcnt = sizeof(intrcnt); -size_t sintrnames = sizeof(intrnames); -static u_int intrcnt_index; - -/* - * Interrupt framework initialization routine. - */ -static void -arm_irq_init(void *dummy __unused) -{ - - SLIST_INIT(&pic_list); - mtx_init(&pic_list_lock, "arm pic list", NULL, MTX_DEF); - mtx_init(&isrc_table_lock, "arm isrc table", NULL, MTX_DEF); -} -SYSINIT(arm_irq_init, SI_SUB_INTR, SI_ORDER_FIRST, arm_irq_init, NULL); - -static void -intrcnt_setname(const char *name, int index) -{ - - snprintf(intrnames + INTRNAME_LEN * index, INTRNAME_LEN, "%-*s", - INTRNAME_LEN - 1, name); -} - -/* - * Update name for interrupt source with interrupt event. - */ -static void -intrcnt_updatename(struct arm_irqsrc *isrc) -{ - - /* QQQ: What about stray counter name? */ - mtx_assert(&isrc_table_lock, MA_OWNED); - intrcnt_setname(isrc->isrc_event->ie_fullname, isrc->isrc_index); -} - -/* - * Virtualization for interrupt source interrupt counter increment. - */ -static inline void -isrc_increment_count(struct arm_irqsrc *isrc) -{ - - /* - * XXX - It should be atomic for PPI interrupts. It was proven that - * the lost is measurable easily for timer PPI interrupts. - */ - isrc->isrc_count[0]++; - /*atomic_add_long(&isrc->isrc_count[0], 1);*/ -} - -/* - * Virtualization for interrupt source interrupt stray counter increment. - */ -static inline void -isrc_increment_straycount(struct arm_irqsrc *isrc) -{ - - isrc->isrc_count[1]++; -} - -/* - * Virtualization for interrupt source interrupt name update. - */ -static void -isrc_update_name(struct arm_irqsrc *isrc, const char *name) -{ - char str[INTRNAME_LEN]; - - mtx_assert(&isrc_table_lock, MA_OWNED); - - if (name != NULL) { - snprintf(str, INTRNAME_LEN, "%s: %s", isrc->isrc_name, name); - intrcnt_setname(str, isrc->isrc_index); - snprintf(str, INTRNAME_LEN, "stray %s: %s", isrc->isrc_name, - name); - intrcnt_setname(str, isrc->isrc_index + 1); - } else { - snprintf(str, INTRNAME_LEN, "%s:", isrc->isrc_name); - intrcnt_setname(str, isrc->isrc_index); - snprintf(str, INTRNAME_LEN, "stray %s:", isrc->isrc_name); - intrcnt_setname(str, isrc->isrc_index + 1); - } -} - -/* - * Virtualization for interrupt source interrupt counters setup. - */ -static void -isrc_setup_counters(struct arm_irqsrc *isrc) -{ - u_int index; - - /* - * XXX - it does not work well with removable controllers and - * interrupt sources !!! - */ - index = atomic_fetchadd_int(&intrcnt_index, 2); - isrc->isrc_index = index; - isrc->isrc_count = &intrcnt[index]; - isrc_update_name(isrc, NULL); -} - -#ifdef SMP -/* - * Virtualization for interrupt source IPI counter increment. - */ -static inline void -isrc_increment_ipi_count(struct arm_irqsrc *isrc, u_int cpu) -{ - - isrc->isrc_count[cpu]++; -} - -/* - * Virtualization for interrupt source IPI counters setup. - */ -static void -isrc_setup_ipi_counters(struct arm_irqsrc *isrc, const char *name) -{ - u_int index, i; - char str[INTRNAME_LEN]; - - index = atomic_fetchadd_int(&intrcnt_index, MAXCPU); - isrc->isrc_index = index; - isrc->isrc_count = &intrcnt[index]; - - for (i = 0; i < MAXCPU; i++) { - /* - * We do not expect any race in IPI case here, - * so locking is not needed. - */ - snprintf(str, INTRNAME_LEN, "cpu%d:%s", i, name); - intrcnt_setname(str, index + i); - } -} -#endif - -/* - * Main ARM interrupt dispatch handler. It's called straight - * from the assembler, where CPU interrupt is served. - */ -void -arm_irq_handler(struct trapframe *tf) -{ - struct trapframe * oldframe; - struct thread * td; - - KASSERT(irq_root_filter != NULL, ("%s: no filter", __func__)); - - PCPU_INC(cnt.v_intr); - critical_enter(); - td = curthread; - oldframe = td->td_intr_frame; - td->td_intr_frame = tf; - irq_root_filter(irq_root_arg); - td->td_intr_frame = oldframe; - critical_exit(); -} - -/* - * ARM interrupt controller dispatch function for interrupts. It should - * be called straight from the interrupt controller, when associated interrupt - * source is learned. - */ -void -arm_irq_dispatch(struct arm_irqsrc *isrc, struct trapframe *tf) -{ - - KASSERT(isrc != NULL, ("%s: no source", __func__)); - - isrc_increment_count(isrc); - -#ifdef INTR_SOLO - if (isrc->isrc_filter != NULL) { - int error; - error = isrc->isrc_filter(isrc->isrc_arg, tf); - PIC_POST_FILTER(isrc->isrc_dev, isrc); - if (error == FILTER_HANDLED) - return; - } else -#endif - if (isrc->isrc_event != NULL) { - if (intr_event_handle(isrc->isrc_event, tf) == 0) - return; - } - - isrc_increment_straycount(isrc); - PIC_DISABLE_SOURCE(isrc->isrc_dev, isrc); - - device_printf(isrc->isrc_dev, "stray irq <%s> disabled", - isrc->isrc_name); -} - -/* - * Allocate interrupt source. - */ -static struct arm_irqsrc * -isrc_alloc(u_int type, u_int extsize) -{ - struct arm_irqsrc *isrc; - - isrc = malloc(sizeof(*isrc) + extsize, M_INTRNG, M_WAITOK | M_ZERO); - isrc->isrc_irq = IRQ_INVALID; /* just to be safe */ - isrc->isrc_type = type; - isrc->isrc_nspc_type = ARM_IRQ_NSPC_NONE; - isrc->isrc_trig = INTR_TRIGGER_CONFORM; - isrc->isrc_pol = INTR_POLARITY_CONFORM; - CPU_ZERO(&isrc->isrc_cpu); - return (isrc); -} - -/* - * Free interrupt source. - */ -static void -isrc_free(struct arm_irqsrc *isrc) -{ - - free(isrc, M_INTRNG); -} - -void -arm_irq_set_name(struct arm_irqsrc *isrc, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsnprintf(isrc->isrc_name, ARM_ISRC_NAMELEN, fmt, ap); - va_end(ap); -} - -/* - * Alloc unique interrupt number (resource handle) for interrupt source. - * - * There could be various strategies how to allocate free interrupt number - * (resource handle) for new interrupt source. - * - * 1. Handles are always allocated forward, so handles are not recycled - * immediately. However, if only one free handle left which is reused - * constantly... - */ -static int -isrc_alloc_irq_locked(struct arm_irqsrc *isrc) -{ - u_int maxirqs, irq; - - mtx_assert(&isrc_table_lock, MA_OWNED); - - maxirqs = nitems(irq_sources); - if (irq_next_free >= maxirqs) - return (ENOSPC); - - for (irq = irq_next_free; irq < maxirqs; irq++) { - if (irq_sources[irq] == NULL) - goto found; - } - for (irq = 0; irq < irq_next_free; irq++) { - if (irq_sources[irq] == NULL) - goto found; - } - - irq_next_free = maxirqs; - return (ENOSPC); - -found: - isrc->isrc_irq = irq; - irq_sources[irq] = isrc; - - arm_irq_set_name(isrc, "irq%u", irq); - isrc_setup_counters(isrc); - - irq_next_free = irq + 1; - if (irq_next_free >= maxirqs) - irq_next_free = 0; - return (0); -} -#ifdef notyet -/* - * Free unique interrupt number (resource handle) from interrupt source. - */ -static int -isrc_free_irq(struct arm_irqsrc *isrc) -{ - u_int maxirqs; - - mtx_assert(&isrc_table_lock, MA_NOTOWNED); - - maxirqs = nitems(irq_sources); - if (isrc->isrc_irq >= maxirqs) - return (EINVAL); - - mtx_lock(&isrc_table_lock); - if (irq_sources[isrc->isrc_irq] != isrc) { - mtx_unlock(&isrc_table_lock); - return (EINVAL); - } - - irq_sources[isrc->isrc_irq] = NULL; - isrc->isrc_irq = IRQ_INVALID; /* just to be safe */ - mtx_unlock(&isrc_table_lock); - - return (0); -} -#endif -/* - * Lookup interrupt source by interrupt number (resource handle). - */ -static struct arm_irqsrc * -isrc_lookup(u_int irq) -{ - - if (irq < nitems(irq_sources)) - return (irq_sources[irq]); - return (NULL); -} - -/* - * Lookup interrupt source by namespace description. - */ -static struct arm_irqsrc * -isrc_namespace_lookup(device_t dev, uint16_t type, uint16_t num) -{ - u_int irq; - struct arm_irqsrc *isrc; - - mtx_assert(&isrc_table_lock, MA_OWNED); - - for (irq = 0; irq < nitems(irq_sources); irq++) { - isrc = irq_sources[irq]; - if (isrc != NULL && isrc->isrc_dev == dev && - isrc->isrc_nspc_type == type && isrc->isrc_nspc_num == num) - return (isrc); - } - return (NULL); -} - -/* - * Map interrupt source according to namespace into framework. If such mapping - * does not exist, create it. Return unique interrupt number (resource handle) - * associated with mapped interrupt source. - */ -u_int -arm_namespace_map_irq(device_t dev, uint16_t type, uint16_t num) -{ - struct arm_irqsrc *isrc, *new_isrc; - int error; - - new_isrc = isrc_alloc(ARM_ISRCT_NAMESPACE, 0); - - mtx_lock(&isrc_table_lock); - isrc = isrc_namespace_lookup(dev, type, num); - if (isrc != NULL) { - mtx_unlock(&isrc_table_lock); - isrc_free(new_isrc); - return (isrc->isrc_irq); /* already mapped */ - } - - error = isrc_alloc_irq_locked(new_isrc); - if (error != 0) { - mtx_unlock(&isrc_table_lock); - isrc_free(new_isrc); - return (IRQ_INVALID); /* no space left */ - } - - new_isrc->isrc_dev = dev; - new_isrc->isrc_nspc_type = type; - new_isrc->isrc_nspc_num = num; - mtx_unlock(&isrc_table_lock); - - return (new_isrc->isrc_irq); -} - -#ifdef FDT -/* - * Lookup interrupt source by FDT description. - */ -static struct arm_irqsrc * -isrc_fdt_lookup(intptr_t xref, pcell_t *cells, u_int ncells) -{ - u_int irq, cellsize; - struct arm_irqsrc *isrc; - - mtx_assert(&isrc_table_lock, MA_OWNED); - - cellsize = ncells * sizeof(*cells); - for (irq = 0; irq < nitems(irq_sources); irq++) { - isrc = irq_sources[irq]; - if (isrc != NULL && isrc->isrc_type == ARM_ISRCT_FDT && - isrc->isrc_xref == xref && isrc->isrc_ncells == ncells && - memcmp(isrc->isrc_cells, cells, cellsize) == 0) - return (isrc); - } - return (NULL); -} - -/* - * Map interrupt source according to FDT data into framework. If such mapping - * does not exist, create it. Return unique interrupt number (resource handle) - * associated with mapped interrupt source. - */ -u_int -arm_fdt_map_irq(phandle_t node, pcell_t *cells, u_int ncells) -{ - struct arm_irqsrc *isrc, *new_isrc; - u_int cellsize; - intptr_t xref; - int error; - - xref = (intptr_t)node; /* It's so simple for now. */ - - cellsize = ncells * sizeof(*cells); - new_isrc = isrc_alloc(ARM_ISRCT_FDT, cellsize); - - mtx_lock(&isrc_table_lock); - isrc = isrc_fdt_lookup(xref, cells, ncells); - if (isrc != NULL) { - mtx_unlock(&isrc_table_lock); - isrc_free(new_isrc); - return (isrc->isrc_irq); /* already mapped */ - } - - error = isrc_alloc_irq_locked(new_isrc); - if (error != 0) { - mtx_unlock(&isrc_table_lock); - isrc_free(new_isrc); - return (IRQ_INVALID); /* no space left */ - } - - new_isrc->isrc_xref = xref; - new_isrc->isrc_ncells = ncells; - memcpy(new_isrc->isrc_cells, cells, cellsize); - mtx_unlock(&isrc_table_lock); - - return (new_isrc->isrc_irq); -} -#endif - -/* - * Register interrupt source into interrupt controller. - */ -static int -isrc_register(struct arm_irqsrc *isrc) -{ - struct arm_pic *pic; - boolean_t is_percpu; - int error; - - if (isrc->isrc_flags & ARM_ISRCF_REGISTERED) - return (0); - - if (isrc->isrc_dev == NULL) { - pic = pic_lookup(NULL, isrc->isrc_xref); - if (pic == NULL || pic->pic_dev == NULL) - return (ESRCH); - isrc->isrc_dev = pic->pic_dev; - } - - error = PIC_REGISTER(isrc->isrc_dev, isrc, &is_percpu); - if (error != 0) - return (error); - - mtx_lock(&isrc_table_lock); - isrc->isrc_flags |= ARM_ISRCF_REGISTERED; - if (is_percpu) - isrc->isrc_flags |= ARM_ISRCF_PERCPU; - isrc_update_name(isrc, NULL); - mtx_unlock(&isrc_table_lock); - return (0); -} - -#ifdef INTR_SOLO -/* - * Setup filter into interrupt source. - */ -static int -iscr_setup_filter(struct arm_irqsrc *isrc, const char *name, - arm_irq_filter_t *filter, void *arg, void **cookiep) -{ - - if (filter == NULL) - return (EINVAL); - - mtx_lock(&isrc_table_lock); - /* - * Make sure that we do not mix the two ways - * how we handle interrupt sources. - */ - if (isrc->isrc_filter != NULL || isrc->isrc_event != NULL) { - mtx_unlock(&isrc_table_lock); - return (EBUSY); - } - isrc->isrc_filter = filter; - isrc->isrc_arg = arg; - isrc_update_name(isrc, name); - mtx_unlock(&isrc_table_lock); - - *cookiep = isrc; - return (0); -} -#endif - -/* - * Interrupt source pre_ithread method for MI interrupt framework. - */ -static void -arm_isrc_pre_ithread(void *arg) -{ - struct arm_irqsrc *isrc = arg; - - PIC_PRE_ITHREAD(isrc->isrc_dev, isrc); -} - -/* - * Interrupt source post_ithread method for MI interrupt framework. - */ -static void -arm_isrc_post_ithread(void *arg) -{ - struct arm_irqsrc *isrc = arg; - - PIC_POST_ITHREAD(isrc->isrc_dev, isrc); -} - -/* - * Interrupt source post_filter method for MI interrupt framework. - */ -static void -arm_isrc_post_filter(void *arg) -{ - struct arm_irqsrc *isrc = arg; - - PIC_POST_FILTER(isrc->isrc_dev, isrc); -} - -/* - * Interrupt source assign_cpu method for MI interrupt framework. - */ -static int -arm_isrc_assign_cpu(void *arg, int cpu) -{ -#ifdef SMP - struct arm_irqsrc *isrc = arg; - int error; - - if (isrc->isrc_dev != irq_root_dev) - return (EINVAL); - - mtx_lock(&isrc_table_lock); - if (cpu == NOCPU) { - CPU_ZERO(&isrc->isrc_cpu); - isrc->isrc_flags &= ~ARM_ISRCF_BOUND; - } else { - CPU_SETOF(cpu, &isrc->isrc_cpu); - isrc->isrc_flags |= ARM_ISRCF_BOUND; - } - - /* - * In NOCPU case, it's up to PIC to either leave ISRC on same CPU or - * re-balance it to another CPU or enable it on more CPUs. However, - * PIC is expected to change isrc_cpu appropriately to keep us well - * informed if the call is successfull. - */ - if (irq_assign_cpu) { - error = PIC_BIND(isrc->isrc_dev, isrc); - if (error) { - CPU_ZERO(&isrc->isrc_cpu); - mtx_unlock(&isrc_table_lock); - return (error); - } - } - mtx_unlock(&isrc_table_lock); - return (0); -#else - return (EOPNOTSUPP); -#endif -} - -/* - * Create interrupt event for interrupt source. - */ -static int -isrc_event_create(struct arm_irqsrc *isrc) -{ - struct intr_event *ie; - int error; - - error = intr_event_create(&ie, isrc, 0, isrc->isrc_irq, - arm_isrc_pre_ithread, arm_isrc_post_ithread, arm_isrc_post_filter, - arm_isrc_assign_cpu, "%s:", isrc->isrc_name); - if (error) - return (error); - - mtx_lock(&isrc_table_lock); - /* - * Make sure that we do not mix the two ways - * how we handle interrupt sources. Let contested event wins. - */ - if (isrc->isrc_filter != NULL || isrc->isrc_event != NULL) { - mtx_unlock(&isrc_table_lock); - intr_event_destroy(ie); - return (isrc->isrc_event != NULL ? EBUSY : 0); - } - isrc->isrc_event = ie; - mtx_unlock(&isrc_table_lock); - - return (0); -} -#ifdef notyet -/* - * Destroy interrupt event for interrupt source. - */ -static void -isrc_event_destroy(struct arm_irqsrc *isrc) -{ - struct intr_event *ie; - - mtx_lock(&isrc_table_lock); - ie = isrc->isrc_event; - isrc->isrc_event = NULL; - mtx_unlock(&isrc_table_lock); - - if (ie != NULL) - intr_event_destroy(ie); -} -#endif -/* - * Add handler to interrupt source. - */ -static int -isrc_add_handler(struct arm_irqsrc *isrc, const char *name, - driver_filter_t filter, driver_intr_t handler, void *arg, - enum intr_type flags, void **cookiep) -{ - int error; - - if (isrc->isrc_event == NULL) { - error = isrc_event_create(isrc); - if (error) - return (error); - } - - error = intr_event_add_handler(isrc->isrc_event, name, filter, handler, - arg, intr_priority(flags), flags, cookiep); - if (error == 0) { - mtx_lock(&isrc_table_lock); - intrcnt_updatename(isrc); - mtx_unlock(&isrc_table_lock); - } - - return (error); -} - -/* - * Lookup interrupt controller locked. - */ -static struct arm_pic * -pic_lookup_locked(device_t dev, intptr_t xref) -{ - struct arm_pic *pic; - - mtx_assert(&pic_list_lock, MA_OWNED); - - SLIST_FOREACH(pic, &pic_list, pic_next) { - if (pic->pic_xref != xref) - continue; - if (pic->pic_xref != 0 || pic->pic_dev == dev) - return (pic); - } - return (NULL); -} - -/* - * Lookup interrupt controller. - */ -static struct arm_pic * -pic_lookup(device_t dev, intptr_t xref) -{ - struct arm_pic *pic; - - mtx_lock(&pic_list_lock); - pic = pic_lookup_locked(dev, xref); - mtx_unlock(&pic_list_lock); - - return (pic); -} - -/* - * Create interrupt controller. - */ -static struct arm_pic * -pic_create(device_t dev, intptr_t xref) -{ - struct arm_pic *pic; - - mtx_lock(&pic_list_lock); - pic = pic_lookup_locked(dev, xref); - if (pic != NULL) { - mtx_unlock(&pic_list_lock); - return (pic); - } - pic = malloc(sizeof(*pic), M_INTRNG, M_NOWAIT | M_ZERO); - pic->pic_xref = xref; - pic->pic_dev = dev; - SLIST_INSERT_HEAD(&pic_list, pic, pic_next); - mtx_unlock(&pic_list_lock); - - return (pic); -} -#ifdef notyet -/* - * Destroy interrupt controller. - */ -static void -pic_destroy(device_t dev, intptr_t xref) -{ - struct arm_pic *pic; - - mtx_lock(&pic_list_lock); - pic = pic_lookup_locked(dev, xref); - if (pic == NULL) { - mtx_unlock(&pic_list_lock); - return; - } - SLIST_REMOVE(&pic_list, pic, arm_pic, pic_next); - mtx_unlock(&pic_list_lock); - - free(pic, M_INTRNG); -} -#endif -/* - * Register interrupt controller. - */ -int -arm_pic_register(device_t dev, intptr_t xref) -{ - struct arm_pic *pic; - - pic = pic_create(dev, xref); - if (pic == NULL) - return (ENOMEM); - if (pic->pic_dev != dev) - return (EINVAL); /* XXX it could be many things. */ - - debugf("PIC %p registered for %s \n", pic, - device_get_nameunit(dev), xref); - return (0); -} - -/* - * Unregister interrupt controller. - */ -int -arm_pic_unregister(device_t dev, intptr_t xref) -{ - - panic("%s: not implemented", __func__); -} - -/* - * Mark interrupt controller (itself) as a root one. - * - * Note that only an interrupt controller can really know its position - * in interrupt controller's tree. So root PIC must claim itself as a root. - * - * In FDT case, according to ePAPR approved version 1.1 from 08 April 2011, - * page 30: - * "The root of the interrupt tree is determined when traversal - * of the interrupt tree reaches an interrupt controller node without - * an interrupts property and thus no explicit interrupt parent." - */ -int -arm_pic_claim_root(device_t dev, intptr_t xref, arm_irq_filter_t *filter, - void *arg, u_int ipicount) -{ - int error; - u_int rootirq; - - if (pic_lookup(dev, xref) == NULL) { - device_printf(dev, "not registered\n"); - return (EINVAL); - } - if (filter == NULL) { - device_printf(dev, "filter missing\n"); - return (EINVAL); - } - - /* - * Only one interrupt controllers could be on the root for now. - * Note that we further suppose that there is not threaded interrupt - * routine (handler) on the root. See arm_irq_handler(). - */ - if (irq_root_dev != NULL) { - device_printf(dev, "another root already set\n"); - return (EBUSY); - } - - rootirq = arm_namespace_map_irq(device_get_parent(dev), 0, 0); - if (rootirq == IRQ_INVALID) { - device_printf(dev, "failed to map an irq for the root pic\n"); - return (ENOMEM); - } - - /* Create the isrc. */ - irq_root_isrc = isrc_lookup(rootirq); - - /* XXX "register" with the PIC. We are the "pic" here, so fake it. */ - irq_root_isrc->isrc_flags |= ARM_ISRCF_REGISTERED; - - error = arm_irq_add_handler(device_get_parent(dev), - (void*)filter, NULL, arg, rootirq, INTR_TYPE_CLK, NULL); - if (error != 0) { - device_printf(dev, "failed to install root pic handler\n"); - return (error); - } - irq_root_dev = dev; - irq_root_filter = filter; - irq_root_arg = arg; - irq_root_ipicount = ipicount; - - debugf("irq root set to %s\n", device_get_nameunit(dev)); - return (0); -} - -int -arm_irq_add_handler(device_t dev, driver_filter_t filt, driver_intr_t hand, - void *arg, u_int irq, int flags, void **cookiep) -{ - const char *name; - struct arm_irqsrc *isrc; - int error; - - name = device_get_nameunit(dev); - -#ifdef INTR_SOLO - /* - * Standard handling is done thru MI interrupt framework. However, - * some interrupts could request solely own special handling. This - * non standard handling can be used for interrupt controllers without - * handler (filter only), so in case that interrupt controllers are - * chained, MI interrupt framework is called only in leaf controller. - * - * Note that root interrupt controller routine is served as well, - * however in arm_irq_handler(), i.e. main system dispatch routine. - */ - if (flags & INTR_SOLO && hand != NULL) { - debugf("irq %u cannot solo on %s\n", irq, name); - return (EINVAL); - } -#endif - - isrc = isrc_lookup(irq); - if (isrc == NULL) { - debugf("irq %u without source on %s\n", irq, name); - return (EINVAL); - } - - error = isrc_register(isrc); - if (error != 0) { - debugf("irq %u map error %d on %s\n", irq, error, name); - return (error); - } - -#ifdef INTR_SOLO - if (flags & INTR_SOLO) { - error = iscr_setup_filter(isrc, name, (arm_irq_filter_t *)filt, - arg, cookiep); - debugf("irq %u setup filter error %d on %s\n", irq, error, - name); - } else -#endif - { - error = isrc_add_handler(isrc, name, filt, hand, arg, flags, - cookiep); - debugf("irq %u add handler error %d on %s\n", irq, error, name); - } - if (error != 0) - return (error); - - mtx_lock(&isrc_table_lock); - isrc->isrc_handlers++; - if (isrc->isrc_handlers == 1) { - PIC_ENABLE_INTR(isrc->isrc_dev, isrc); - PIC_ENABLE_SOURCE(isrc->isrc_dev, isrc); - } - mtx_unlock(&isrc_table_lock); - return (0); -} - -int -arm_irq_remove_handler(device_t dev, u_int irq, void *cookie) -{ - struct arm_irqsrc *isrc; - int error; - - isrc = isrc_lookup(irq); - if (isrc == NULL || isrc->isrc_handlers == 0) - return (EINVAL); - - if (isrc->isrc_filter != NULL) { - if (isrc != cookie) - return (EINVAL); - - mtx_lock(&isrc_table_lock); - isrc->isrc_filter = NULL; - isrc->isrc_arg = NULL; - isrc->isrc_handlers = 0; - PIC_DISABLE_SOURCE(isrc->isrc_dev, isrc); - PIC_DISABLE_INTR(isrc->isrc_dev, isrc); - isrc_update_name(isrc, NULL); - mtx_unlock(&isrc_table_lock); - return (0); - } - - if (isrc != intr_handler_source(cookie)) - return (EINVAL); - - error = intr_event_remove_handler(cookie); - if (error == 0) { - mtx_lock(&isrc_table_lock); - isrc->isrc_handlers--; - if (isrc->isrc_handlers == 0) { - PIC_DISABLE_SOURCE(isrc->isrc_dev, isrc); - PIC_DISABLE_INTR(isrc->isrc_dev, isrc); - } - intrcnt_updatename(isrc); - mtx_unlock(&isrc_table_lock); - } - return (error); -} - -int -arm_irq_config(u_int irq, enum intr_trigger trig, enum intr_polarity pol) -{ - struct arm_irqsrc *isrc; - - isrc = isrc_lookup(irq); - if (isrc == NULL) - return (EINVAL); - - if (isrc->isrc_handlers != 0) - return (EBUSY); /* interrrupt is enabled (active) */ - - /* - * Once an interrupt is enabled, we do not change its configuration. - * A controller PIC_ENABLE_INTR() method is called when an interrupt - * is going to be enabled. In this method, a controller should setup - * the interrupt according to saved configuration parameters. - */ - isrc->isrc_trig = trig; - isrc->isrc_pol = pol; - - return (0); -} - -int -arm_irq_describe(u_int irq, void *cookie, const char *descr) -{ - struct arm_irqsrc *isrc; - int error; - - isrc = isrc_lookup(irq); - if (isrc == NULL || isrc->isrc_handlers == 0) - return (EINVAL); - - if (isrc->isrc_filter != NULL) { - if (isrc != cookie) - return (EINVAL); - - mtx_lock(&isrc_table_lock); - isrc_update_name(isrc, descr); - mtx_unlock(&isrc_table_lock); - return (0); - } - - error = intr_event_describe_handler(isrc->isrc_event, cookie, descr); - if (error == 0) { - mtx_lock(&isrc_table_lock); - intrcnt_updatename(isrc); - mtx_unlock(&isrc_table_lock); - } - return (error); -} - -#ifdef SMP -int -arm_irq_bind(u_int irq, int cpu) -{ - struct arm_irqsrc *isrc; - - isrc = isrc_lookup(irq); - if (isrc == NULL || isrc->isrc_handlers == 0) - return (EINVAL); - - if (isrc->isrc_filter != NULL) - return (arm_isrc_assign_cpu(isrc, cpu)); - - return (intr_event_bind(isrc->isrc_event, cpu)); -} - -/* - * Return the CPU that the next interrupt source should use. - * For now just returns the next CPU according to round-robin. - */ -u_int -arm_irq_next_cpu(u_int last_cpu, cpuset_t *cpumask) -{ - - if (!irq_assign_cpu || mp_ncpus == 1) - return (PCPU_GET(cpuid)); - - do { - last_cpu++; - if (last_cpu > mp_maxid) - last_cpu = 0; - } while (!CPU_ISSET(last_cpu, cpumask)); - return (last_cpu); -} - -/* - * Distribute all the interrupt sources among the available - * CPUs once the AP's have been launched. - */ -static void -arm_irq_shuffle(void *arg __unused) -{ - struct arm_irqsrc *isrc; - u_int i; - - if (mp_ncpus == 1) - return; - - mtx_lock(&isrc_table_lock); - irq_assign_cpu = TRUE; - for (i = 0; i < NIRQ; i++) { - isrc = irq_sources[i]; - if (isrc == NULL || isrc->isrc_handlers == 0 || - isrc->isrc_flags & ARM_ISRCF_PERCPU) - continue; - - if (isrc->isrc_event != NULL && - isrc->isrc_flags & ARM_ISRCF_BOUND && - isrc->isrc_event->ie_cpu != CPU_FFS(&isrc->isrc_cpu) - 1) - panic("%s: CPU inconsistency", __func__); - - if ((isrc->isrc_flags & ARM_ISRCF_BOUND) == 0) - CPU_ZERO(&isrc->isrc_cpu); /* start again */ - - /* - * We are in wicked position here if the following call fails - * for bound ISRC. The best thing we can do is to clear - * isrc_cpu so inconsistency with ie_cpu will be detectable. - */ - if (PIC_BIND(isrc->isrc_dev, isrc) != 0) - CPU_ZERO(&isrc->isrc_cpu); - } - mtx_unlock(&isrc_table_lock); -} -SYSINIT(arm_irq_shuffle, SI_SUB_SMP, SI_ORDER_SECOND, arm_irq_shuffle, NULL); - -#else -u_int -arm_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask) -{ - - return (PCPU_GET(cpuid)); -} -#endif - -void dosoftints(void); -void -dosoftints(void) -{ -} - -/* - * arm_irq_memory_barrier() - * - * Ensure all writes to device memory have reached devices before proceeding. - * - * This is intended to be called from the post-filter and post-thread routines - * of an interrupt controller implementation. A peripheral device driver should - * use bus_space_barrier() if it needs to ensure a write has reached the - * hardware for some reason other than clearing interrupt conditions. - * - * The need for this function arises from the ARM weak memory ordering model. - * Writes to locations mapped with the Device attribute bypass any caches, but - * are buffered. Multiple writes to the same device will be observed by that - * device in the order issued by the cpu. Writes to different devices may - * appear at those devices in a different order than issued by the cpu. That - * is, if the cpu writes to device A then device B, the write to device B could - * complete before the write to device A. - * - * Consider a typical device interrupt handler which services the interrupt and - * writes to a device status-acknowledge register to clear the interrupt before - * returning. That write is posted to the L2 controller which "immediately" - * places it in a store buffer and automatically drains that buffer. This can - * be less immediate than you'd think... There may be no free slots in the store - * buffers, so an existing buffer has to be drained first to make room. The - * target bus may be busy with other traffic (such as DMA for various devices), - * delaying the drain of the store buffer for some indeterminate time. While - * all this delay is happening, execution proceeds on the CPU, unwinding its way - * out of the interrupt call stack to the point where the interrupt driver code - * is ready to EOI and unmask the interrupt. The interrupt controller may be - * accessed via a faster bus than the hardware whose handler just ran; the write - * to unmask and EOI the interrupt may complete quickly while the device write - * to ack and clear the interrupt source is still lingering in a store buffer - * waiting for access to a slower bus. With the interrupt unmasked at the - * interrupt controller but still active at the device, as soon as interrupts - * are enabled on the core the device re-interrupts immediately: now you've got - * a spurious interrupt on your hands. - * - * The right way to fix this problem is for every device driver to use the - * proper bus_space_barrier() calls in its interrupt handler. For ARM a single - * barrier call at the end of the handler would work. This would have to be - * done to every driver in the system, not just arm-specific drivers. - * - * Another potential fix is to map all device memory as Strongly-Ordered rather - * than Device memory, which takes the store buffers out of the picture. This - * has a pretty big impact on overall system performance, because each strongly - * ordered memory access causes all L2 store buffers to be drained. - * - * A compromise solution is to have the interrupt controller implementation call - * this function to establish a barrier between writes to the interrupt-source - * device and writes to the interrupt controller device. - * - * This takes the interrupt number as an argument, and currently doesn't use it. - * The plan is that maybe some day there is a way to flag certain interrupts as - * "memory barrier safe" and we can avoid this overhead with them. - */ -void -arm_irq_memory_barrier(uintptr_t irq) -{ - - dsb(); - cpu_l2cache_drain_writebuf(); -} - -#ifdef SMP -/* - * Lookup IPI source. - */ -static struct arm_irqsrc * -arm_ipi_lookup(u_int ipi) -{ - - if (ipi >= ARM_IPI_COUNT) - panic("%s: no such IPI %u", __func__, ipi); - - return (&ipi_sources[ipi]); -} - -/* - * ARM interrupt controller dispatch function for IPIs. It should - * be called straight from the interrupt controller, when associated - * interrupt source is learned. Or from anybody who has an interrupt - * source mapped. - */ -void -arm_ipi_dispatch(struct arm_irqsrc *isrc, struct trapframe *tf) -{ - void *arg; - - KASSERT(isrc != NULL, ("%s: no source", __func__)); - - isrc_increment_ipi_count(isrc, PCPU_GET(cpuid)); - - /* - * Supply ipi filter with trapframe argument - * if none is registered. - */ - arg = isrc->isrc_arg != NULL ? isrc->isrc_arg : tf; - isrc->isrc_ipifilter(arg); -} - -/* - * Map IPI into interrupt controller. - * - * Not SMP coherent. - */ -static int -ipi_map(struct arm_irqsrc *isrc, u_int ipi) -{ - boolean_t is_percpu; - int error; - - if (ipi >= ARM_IPI_COUNT) - panic("%s: no such IPI %u", __func__, ipi); - - KASSERT(irq_root_dev != NULL, ("%s: no root attached", __func__)); - - isrc->isrc_type = ARM_ISRCT_NAMESPACE; - isrc->isrc_nspc_type = ARM_IRQ_NSPC_IPI; - isrc->isrc_nspc_num = ipi_next_num; - - error = PIC_REGISTER(irq_root_dev, isrc, &is_percpu); - - debugf("ipi %u mapped to %u on %s - error %d\n", ipi, ipi_next_num, - device_get_nameunit(irq_root_dev), error); - - if (error == 0) { - isrc->isrc_dev = irq_root_dev; - ipi_next_num++; - } - return (error); -} - -/* - * Setup IPI handler to interrupt source. - * - * Note that there could be more ways how to send and receive IPIs - * on a platform like fast interrupts for example. In that case, - * one can call this function with ASIF_NOALLOC flag set and then - * call arm_ipi_dispatch() when appropriate. - * - * Not SMP coherent. - */ -int -arm_ipi_set_handler(u_int ipi, const char *name, arm_ipi_filter_t *filter, - void *arg, u_int flags) -{ - struct arm_irqsrc *isrc; - int error; - - if (filter == NULL) - return(EINVAL); - - isrc = arm_ipi_lookup(ipi); - if (isrc->isrc_ipifilter != NULL) - return (EEXIST); - - if ((flags & AISHF_NOALLOC) == 0) { - error = ipi_map(isrc, ipi); - if (error != 0) - return (error); - } - - isrc->isrc_ipifilter = filter; - isrc->isrc_arg = arg; - isrc->isrc_handlers = 1; - isrc_setup_ipi_counters(isrc, name); - - if (isrc->isrc_dev != NULL) { - mtx_lock(&isrc_table_lock); - PIC_ENABLE_INTR(isrc->isrc_dev, isrc); - PIC_ENABLE_SOURCE(isrc->isrc_dev, isrc); - mtx_unlock(&isrc_table_lock); - } - return (0); -} - -/* - * Send IPI thru interrupt controller. - */ -void -pic_ipi_send(cpuset_t cpus, u_int ipi) -{ - struct arm_irqsrc *isrc; - - isrc = arm_ipi_lookup(ipi); - - KASSERT(irq_root_dev != NULL, ("%s: no root attached", __func__)); - PIC_IPI_SEND(irq_root_dev, isrc, cpus); -} - -/* - * Init interrupt controller on another CPU. - */ -void -arm_pic_init_secondary(void) -{ - - /* - * QQQ: Only root PIC is aware of other CPUs ??? - */ - KASSERT(irq_root_dev != NULL, ("%s: no root attached", __func__)); - - //mtx_lock(&isrc_table_lock); - PIC_INIT_SECONDARY(irq_root_dev); - //mtx_unlock(&isrc_table_lock); -} -#endif - -#ifdef DDB -DB_SHOW_COMMAND(irqs, db_show_irqs) -{ - u_int i, irqsum; - struct arm_irqsrc *isrc; - -#ifdef SMP - for (i = 0; i <= mp_maxid; i++) { - struct pcpu *pc; - u_int ipi, ipisum; - - pc = pcpu_find(i); - if (pc != NULL) { - for (ipisum = 0, ipi = 0; ipi < ARM_IPI_COUNT; ipi++) { - isrc = arm_ipi_lookup(ipi); - if (isrc->isrc_count != NULL) - ipisum += isrc->isrc_count[i]; - } - printf ("cpu%u: total %u ipis %u\n", i, - pc->pc_cnt.v_intr, ipisum); - } - } - db_printf("\n"); -#endif - - for (irqsum = 0, i = 0; i < NIRQ; i++) { - isrc = irq_sources[i]; - if (isrc == NULL) - continue; - - db_printf("irq%-3u <%s>: cpu %02lx%s cnt %lu\n", i, - isrc->isrc_name, isrc->isrc_cpu.__bits[0], - isrc->isrc_flags & ARM_ISRCF_BOUND ? " (bound)" : "", - isrc->isrc_count[0]); - irqsum += isrc->isrc_count[0]; - } - db_printf("irq total %u\n", irqsum); -} -#endif Property changes on: user/alc/PQ_LAUNDRY/sys/arm/arm/intrng.c ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/arm/arm/exception.S =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/arm/exception.S (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/arm/exception.S (revision 292449) @@ -1,504 +1,504 @@ /* $NetBSD: exception.S,v 1.13 2003/10/31 16:30:15 scw Exp $ */ /*- * Copyright (c) 1994-1997 Mark Brinicombe. * Copyright (c) 1994 Brini. * All rights reserved. * * This code is derived from software written for Brini by Mark Brinicombe * * 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 Brini. * 4. The name of the company nor the name of the author may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. * * RiscBSD kernel project * * exception.S * * Low level handlers for exception vectors * * Created : 24/09/94 * * Based on kate/display/abort.s * */ #include "assym.s" #include #include #include #include #include __FBSDID("$FreeBSD$"); #ifdef KDTRACE_HOOKS .bss .align 4 .global _C_LABEL(dtrace_invop_jump_addr) _C_LABEL(dtrace_invop_jump_addr): .word 0 .word 0 #endif .text .align 2 /* * ASM macros for pushing and pulling trapframes from the stack * * These macros are used to handle the irqframe and trapframe structures * defined above. */ /* * PUSHFRAME - macro to push a trap frame on the stack in the current mode * Since the current mode is used, the SVC lr field is not defined. * * NOTE: r13 and r14 are stored separately as a work around for the * SA110 rev 2 STM^ bug */ #if __ARM_ARCH < 6 #define PUSHFRAME \ sub sp, sp, #4; /* Align the stack */ \ str lr, [sp, #-4]!; /* Push the return address */ \ sub sp, sp, #(4*17); /* Adjust the stack pointer */ \ stmia sp, {r0-r12}; /* Push the user mode registers */ \ add r0, sp, #(4*13); /* Adjust the stack pointer */ \ stmia r0, {r13-r14}^; /* Push the user mode registers */ \ mov r0, r0; /* NOP for previous instruction */ \ mrs r0, spsr; /* Put the SPSR on the stack */ \ str r0, [sp, #-4]!; \ ldr r0, =ARM_RAS_START; \ mov r1, #0; \ str r1, [r0]; \ mov r1, #0xffffffff; \ str r1, [r0, #4]; #else #define PUSHFRAME \ sub sp, sp, #4; /* Align the stack */ \ str lr, [sp, #-4]!; /* Push the return address */ \ sub sp, sp, #(4*17); /* Adjust the stack pointer */ \ stmia sp, {r0-r12}; /* Push the user mode registers */ \ add r0, sp, #(4*13); /* Adjust the stack pointer */ \ stmia r0, {r13-r14}^; /* Push the user mode registers */ \ mov r0, r0; /* NOP for previous instruction */ \ mrs r0, spsr; /* Put the SPSR on the stack */ \ str r0, [sp, #-4]!; #endif /* * PULLFRAME - macro to pull a trap frame from the stack in the current mode * Since the current mode is used, the SVC lr field is ignored. */ #if __ARM_ARCH < 6 #define PULLFRAME \ ldr r0, [sp], #4; /* Get the SPSR from stack */ \ msr spsr_fsxc, r0; \ ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ mov r0, r0; /* NOP for previous instruction */ \ add sp, sp, #(4*17); /* Adjust the stack pointer */ \ ldr lr, [sp], #4; /* Pull the return address */ \ add sp, sp, #4 /* Align the stack */ #else #define PULLFRAME \ ldr r0, [sp], #4 ; /* Get the SPSR from stack */ \ msr spsr_fsxc, r0; \ clrex; \ ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ mov r0, r0; /* NOP for previous instruction */ \ add sp, sp, #(4*17); /* Adjust the stack pointer */ \ ldr lr, [sp], #4; /* Pull the return address */ \ add sp, sp, #4 /* Align the stack */ #endif /* * PUSHFRAMEINSVC - macro to push a trap frame on the stack in SVC32 mode * This should only be used if the processor is not currently in SVC32 * mode. The processor mode is switched to SVC mode and the trap frame is * stored. The SVC lr field is used to store the previous value of * lr in SVC mode. * * NOTE: r13 and r14 are stored separately as a work around for the * SA110 rev 2 STM^ bug */ #if __ARM_ARCH < 6 #define PUSHFRAMEINSVC \ stmdb sp, {r0-r3}; /* Save 4 registers */ \ mov r0, lr; /* Save xxx32 r14 */ \ mov r1, sp; /* Save xxx32 sp */ \ mrs r3, spsr; /* Save xxx32 spsr */ \ mrs r2, cpsr; /* Get the CPSR */ \ bic r2, r2, #(PSR_MODE); /* Fix for SVC mode */ \ orr r2, r2, #(PSR_SVC32_MODE); \ msr cpsr_c, r2; /* Punch into SVC mode */ \ mov r2, sp; /* Save SVC sp */ \ bic sp, sp, #7; /* Align sp to an 8-byte addrress */ \ sub sp, sp, #(4 * 17); /* Pad trapframe to keep alignment */ \ /* and for dtrace to emulate push/pop */ \ str r0, [sp, #-4]!; /* Push return address */ \ str lr, [sp, #-4]!; /* Push SVC lr */ \ str r2, [sp, #-4]!; /* Push SVC sp */ \ msr spsr_fsxc, r3; /* Restore correct spsr */ \ ldmdb r1, {r0-r3}; /* Restore 4 regs from xxx mode */ \ sub sp, sp, #(4*15); /* Adjust the stack pointer */ \ stmia sp, {r0-r12}; /* Push the user mode registers */ \ add r0, sp, #(4*13); /* Adjust the stack pointer */ \ stmia r0, {r13-r14}^; /* Push the user mode registers */ \ mov r0, r0; /* NOP for previous instruction */ \ ldr r5, =ARM_RAS_START; /* Check if there's any RAS */ \ ldr r4, [r5, #4]; /* reset it to point at the */ \ cmp r4, #0xffffffff; /* end of memory if necessary; */ \ movne r1, #0xffffffff; /* leave value in r4 for later */ \ strne r1, [r5, #4]; /* comparision against PC. */ \ ldr r3, [r5]; /* Retrieve global RAS_START */ \ cmp r3, #0; /* and reset it if non-zero. */ \ movne r1, #0; /* If non-zero RAS_START and */ \ strne r1, [r5]; /* PC was lower than RAS_END, */ \ ldrne r1, [r0, #16]; /* adjust the saved PC so that */ \ cmpne r4, r1; /* execution later resumes at */ \ strhi r3, [r0, #16]; /* the RAS_START location. */ \ mrs r0, spsr; \ str r0, [sp, #-4]! #else #define PUSHFRAMEINSVC \ stmdb sp, {r0-r3}; /* Save 4 registers */ \ mov r0, lr; /* Save xxx32 r14 */ \ mov r1, sp; /* Save xxx32 sp */ \ mrs r3, spsr; /* Save xxx32 spsr */ \ mrs r2, cpsr; /* Get the CPSR */ \ bic r2, r2, #(PSR_MODE); /* Fix for SVC mode */ \ orr r2, r2, #(PSR_SVC32_MODE); \ msr cpsr_c, r2; /* Punch into SVC mode */ \ mov r2, sp; /* Save SVC sp */ \ bic sp, sp, #7; /* Align sp to an 8-byte addrress */ \ sub sp, sp, #(4 * 17); /* Pad trapframe to keep alignment */ \ /* and for dtrace to emulate push/pop */ \ str r0, [sp, #-4]!; /* Push return address */ \ str lr, [sp, #-4]!; /* Push SVC lr */ \ str r2, [sp, #-4]!; /* Push SVC sp */ \ msr spsr_fsxc, r3; /* Restore correct spsr */ \ ldmdb r1, {r0-r3}; /* Restore 4 regs from xxx mode */ \ sub sp, sp, #(4*15); /* Adjust the stack pointer */ \ stmia sp, {r0-r12}; /* Push the user mode registers */ \ add r0, sp, #(4*13); /* Adjust the stack pointer */ \ stmia r0, {r13-r14}^; /* Push the user mode registers */ \ mov r0, r0; /* NOP for previous instruction */ \ mrs r0, spsr; /* Put the SPSR on the stack */ \ str r0, [sp, #-4]! #endif /* * PULLFRAMEFROMSVCANDEXIT - macro to pull a trap frame from the stack * in SVC32 mode and restore the saved processor mode and PC. * This should be used when the SVC lr register needs to be restored on * exit. */ #if __ARM_ARCH < 6 #define PULLFRAMEFROMSVCANDEXIT \ ldr r0, [sp], #4; /* Get the SPSR from stack */ \ msr spsr_fsxc, r0; /* restore SPSR */ \ ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ mov r0, r0; /* NOP for previous instruction */ \ add sp, sp, #(4*15); /* Adjust the stack pointer */ \ ldmia sp, {sp, lr, pc}^ /* Restore lr and exit */ #else #define PULLFRAMEFROMSVCANDEXIT \ ldr r0, [sp], #4; /* Get the SPSR from stack */ \ msr spsr_fsxc, r0; /* restore SPSR */ \ clrex; \ ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ mov r0, r0; /* NOP for previous instruction */ \ add sp, sp, #(4*15); /* Adjust the stack pointer */ \ ldmia sp, {sp, lr, pc}^ /* Restore lr and exit */ #endif /* * Unwind hints so we can unwind past functions that use * PULLFRAMEFROMSVCANDEXIT. They are run in reverse order. * As the last thing we do is restore the stack pointer * we can ignore the padding at the end of struct trapframe. */ #define UNWINDSVCFRAME \ .save {r13-r15}; /* Restore sp, lr, pc */ \ .pad #(2*4); /* Skip user sp and lr */ \ .save {r0-r12}; /* Restore r0-r12 */ \ .pad #(4) /* Skip spsr */ #define DO_AST \ ldr r0, [sp]; /* Get the SPSR from stack */ \ mrs r4, cpsr; /* save CPSR */ \ orr r1, r4, #(PSR_I|PSR_F); \ msr cpsr_c, r1; /* Disable interrupts */ \ and r0, r0, #(PSR_MODE); /* Returning to USR mode? */ \ teq r0, #(PSR_USR32_MODE); \ bne 2f; /* Nope, get out now */ \ bic r4, r4, #(PSR_I|PSR_F); \ 1: GET_CURTHREAD_PTR(r5); \ ldr r1, [r5, #(TD_FLAGS)]; \ and r1, r1, #(TDF_ASTPENDING|TDF_NEEDRESCHED); \ teq r1, #0; \ beq 2f; /* Nope. Just bail */ \ msr cpsr_c, r4; /* Restore interrupts */ \ mov r0, sp; \ bl _C_LABEL(ast); /* ast(frame) */ \ orr r0, r4, #(PSR_I|PSR_F); \ msr cpsr_c, r0; \ b 1b; \ 2: /* * Entry point for a Software Interrupt (SWI). * * The hardware switches to svc32 mode on a swi, so we're already on the * right stack; just build a trapframe and call the handler. */ ASENTRY_NP(swi_entry) PUSHFRAME /* Build the trapframe on the */ mov r0, sp /* scv32 stack, pass it to the */ bl _C_LABEL(swi_handler) /* swi handler. */ /* * The fork_trampoline() code in swtch.S aranges for the MI fork_exit() * to return to swi_exit here, to return to userland. The net effect is * that a newly created thread appears to return from a SWI just like * the parent thread that created it. */ ASEENTRY_NP(swi_exit) DO_AST /* Handle pending signals. */ PULLFRAME /* Deallocate trapframe. */ movs pc, lr /* Return to userland. */ STOP_UNWINDING /* Don't unwind into user mode. */ EEND(swi_exit) END(swi_entry) /* * Standard exception exit handler. * * This is used to return from all exceptions except SWI. It uses DO_AST and * PULLFRAMEFROMSVCANDEXIT and can only be called if the exception entry code * used PUSHFRAMEINSVC. * * If the return is to user mode, this uses DO_AST to deliver any pending * signals and/or handle TDF_NEEDRESCHED first. */ ASENTRY_NP(exception_exit) DO_AST /* Handle pending signals. */ PULLFRAMEFROMSVCANDEXIT /* Return. */ UNWINDSVCFRAME /* Special unwinding for exceptions. */ END(exception_exit) /* * Entry point for a Prefetch Abort exception. * * The hardware switches to the abort mode stack; we switch to svc32 before * calling the handler, then return directly to the original mode/stack * on exit (without transitioning back through the abort mode stack). */ ASENTRY_NP(prefetch_abort_entry) #ifdef __XSCALE__ nop /* Make absolutely sure any pending */ nop /* imprecise aborts have occurred. */ #endif sub lr, lr, #4 /* Adjust the lr. Transition to scv32 */ PUSHFRAMEINSVC /* mode stack, build trapframe there. */ adr lr, exception_exit /* Return from handler via standard */ mov r0, sp /* exception exit routine. Pass the */ mov r1, #1 /* Type flag */ b _C_LABEL(abort_handler) END(prefetch_abort_entry) /* * Entry point for a Data Abort exception. * * The hardware switches to the abort mode stack; we switch to svc32 before * calling the handler, then return directly to the original mode/stack * on exit (without transitioning back through the abort mode stack). */ ASENTRY_NP(data_abort_entry) #ifdef __XSCALE__ nop /* Make absolutely sure any pending */ nop /* imprecise aborts have occurred. */ #endif sub lr, lr, #8 /* Adjust the lr. Transition to scv32 */ PUSHFRAMEINSVC /* mode stack, build trapframe there. */ adr lr, exception_exit /* Exception exit routine */ mov r0, sp /* Trapframe to the handler */ mov r1, #0 /* Type flag */ b _C_LABEL(abort_handler) END(data_abort_entry) /* * Entry point for an Undefined Instruction exception. * * The hardware switches to the undefined mode stack; we switch to svc32 before * calling the handler, then return directly to the original mode/stack * on exit (without transitioning back through the undefined mode stack). */ ASENTRY_NP(undefined_entry) PUSHFRAMEINSVC /* mode stack, build trapframe there. */ mov r4, r0 /* R0 contains SPSR */ adr lr, exception_exit /* Return from handler via standard */ mov r0, sp /* exception exit routine. pass frame */ ldr r2, [sp, #(TF_PC)] /* load pc */ #if __ARM_ARCH >= 7 tst r4, #(PSR_T) /* test if PSR_T */ subne r2, r2, #(THUMB_INSN_SIZE) subeq r2, r2, #(INSN_SIZE) #else sub r2, r2, #(INSN_SIZE) /* fix pc */ #endif str r2, [sp, #TF_PC] /* store pc */ #ifdef KDTRACE_HOOKS /* Check if dtrace is enabled */ ldr r1, =_C_LABEL(dtrace_invop_jump_addr) ldr r3, [r1] cmp r3, #0 beq undefinedinstruction and r4, r4, #(PSR_MODE) /* Mask out unneeded bits */ cmp r4, #(PSR_USR32_MODE) /* Check if we came from usermode */ beq undefinedinstruction ldr r4, [r2] /* load instrution */ ldr r1, =FBT_BREAKPOINT /* load fbt inv op */ cmp r1, r4 bne undefinedinstruction bx r3 /* call invop_jump_addr */ #endif b undefinedinstruction /* call stadnard handler */ END(undefined_entry) /* * Entry point for a normal IRQ. * * The hardware switches to the IRQ mode stack; we switch to svc32 before * calling the handler, then return directly to the original mode/stack * on exit (without transitioning back through the IRQ mode stack). */ ASENTRY_NP(irq_entry) sub lr, lr, #4 /* Adjust the lr. Transition to scv32 */ PUSHFRAMEINSVC /* mode stack, build trapframe there. */ adr lr, exception_exit /* Return from handler via standard */ mov r0, sp /* exception exit routine. Pass the */ - b _C_LABEL(arm_irq_handler)/* trapframe to the handler. */ + b _C_LABEL(intr_irq_handler)/* trapframe to the handler. */ END(irq_entry) /* * Entry point for an FIQ interrupt. * * We don't currently support FIQ handlers very much. Something can * install itself in the FIQ vector using code (that may or may not work * these days) in fiq.c. If nobody does that and an FIQ happens, this * default handler just disables FIQs and otherwise ignores it. */ ASENTRY_NP(fiq_entry) mrs r8, cpsr /* FIQ handling isn't supported, */ bic r8, #(PSR_F) /* just disable FIQ and return. */ msr cpsr_c, r8 /* The r8 we trash here is the */ subs pc, lr, #4 /* banked FIQ-mode r8. */ END(fiq_entry) /* * Entry point for an Address Exception exception. * This is an arm26 exception that should never happen. */ ASENTRY_NP(addr_exception_entry) mov r3, lr mrs r2, spsr mrs r1, cpsr adr r0, Laddr_exception_msg b _C_LABEL(panic) Laddr_exception_msg: .asciz "Address Exception CPSR=0x%08x SPSR=0x%08x LR=0x%08x\n" .balign 4 END(addr_exception_entry) /* * Entry point for the system Reset vector. * This should never happen, so panic. */ ASENTRY_NP(reset_entry) mov r1, lr adr r0, Lreset_panicmsg b _C_LABEL(panic) /* NOTREACHED */ Lreset_panicmsg: .asciz "Reset vector called, LR = 0x%08x" .balign 4 END(reset_entry) /* * page0 and page0_data -- An image of the ARM vectors which is copied to * the ARM vectors page (high or low) as part of CPU initialization. The * code that does the copy assumes that page0_data holds one 32-bit word * of data for each of the predefined ARM vectors. It also assumes that * page0_data follows the vectors in page0, but other stuff can appear * between the two. We currently leave room between the two for some fiq * handler code to be copied in. */ .global _C_LABEL(page0), _C_LABEL(page0_data) _C_LABEL(page0): ldr pc, .Lreset_entry ldr pc, .Lundefined_entry ldr pc, .Lswi_entry ldr pc, .Lprefetch_abort_entry ldr pc, .Ldata_abort_entry ldr pc, .Laddr_exception_entry ldr pc, .Lirq_entry .fiqv: ldr pc, .Lfiq_entry .space 256 /* room for some fiq handler code */ _C_LABEL(page0_data): .Lreset_entry: .word reset_entry .Lundefined_entry: .word undefined_entry .Lswi_entry: .word swi_entry .Lprefetch_abort_entry: .word prefetch_abort_entry .Ldata_abort_entry: .word data_abort_entry .Laddr_exception_entry: .word addr_exception_entry .Lirq_entry: .word irq_entry .Lfiq_entry: .word fiq_entry /* * These items are used by the code in fiq.c to install what it calls the * "null" handler. It's actually our default vector entry that just jumps * to the default handler which just disables FIQs and returns. */ .global _C_LABEL(fiq_nullhandler_code), _C_LABEL(fiq_nullhandler_size) _C_LABEL(fiq_nullhandler_code): .word .fiqv _C_LABEL(fiq_nullhandler_size): .word 4 Index: user/alc/PQ_LAUNDRY/sys/arm/arm/gic.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/arm/gic.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/arm/gic.c (revision 292449) @@ -1,1163 +1,1163 @@ /*- * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * * Developed by Damjan Marion * * Based on OMAP4 GIC code by Ben Gray * * 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 company nor the name of the author may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_platform.h" #include "opt_platform.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef ARM_INTRNG #include #endif #include #include #include #include #include #include #include #ifdef ARM_INTRNG #include "pic_if.h" #endif #define GIC_DEBUG_SPURIOUS /* We are using GICv2 register naming */ /* Distributor Registers */ #define GICD_CTLR 0x000 /* v1 ICDDCR */ #define GICD_TYPER 0x004 /* v1 ICDICTR */ #define GICD_IIDR 0x008 /* v1 ICDIIDR */ #define GICD_IGROUPR(n) (0x0080 + ((n) * 4)) /* v1 ICDISER */ #define GICD_ISENABLER(n) (0x0100 + ((n) * 4)) /* v1 ICDISER */ #define GICD_ICENABLER(n) (0x0180 + ((n) * 4)) /* v1 ICDICER */ #define GICD_ISPENDR(n) (0x0200 + ((n) * 4)) /* v1 ICDISPR */ #define GICD_ICPENDR(n) (0x0280 + ((n) * 4)) /* v1 ICDICPR */ #define GICD_ICACTIVER(n) (0x0380 + ((n) * 4)) /* v1 ICDABR */ #define GICD_IPRIORITYR(n) (0x0400 + ((n) * 4)) /* v1 ICDIPR */ #define GICD_ITARGETSR(n) (0x0800 + ((n) * 4)) /* v1 ICDIPTR */ #define GICD_ICFGR(n) (0x0C00 + ((n) * 4)) /* v1 ICDICFR */ #define GICD_SGIR(n) (0x0F00 + ((n) * 4)) /* v1 ICDSGIR */ /* CPU Registers */ #define GICC_CTLR 0x0000 /* v1 ICCICR */ #define GICC_PMR 0x0004 /* v1 ICCPMR */ #define GICC_BPR 0x0008 /* v1 ICCBPR */ #define GICC_IAR 0x000C /* v1 ICCIAR */ #define GICC_EOIR 0x0010 /* v1 ICCEOIR */ #define GICC_RPR 0x0014 /* v1 ICCRPR */ #define GICC_HPPIR 0x0018 /* v1 ICCHPIR */ #define GICC_ABPR 0x001C /* v1 ICCABPR */ #define GICC_IIDR 0x00FC /* v1 ICCIIDR*/ #define GIC_FIRST_SGI 0 /* Irqs 0-15 are SGIs/IPIs. */ #define GIC_LAST_SGI 15 #define GIC_FIRST_PPI 16 /* Irqs 16-31 are private (per */ #define GIC_LAST_PPI 31 /* core) peripheral interrupts. */ #define GIC_FIRST_SPI 32 /* Irqs 32+ are shared peripherals. */ /* First bit is a polarity bit (0 - low, 1 - high) */ #define GICD_ICFGR_POL_LOW (0 << 0) #define GICD_ICFGR_POL_HIGH (1 << 0) #define GICD_ICFGR_POL_MASK 0x1 /* Second bit is a trigger bit (0 - level, 1 - edge) */ #define GICD_ICFGR_TRIG_LVL (0 << 1) #define GICD_ICFGR_TRIG_EDGE (1 << 1) #define GICD_ICFGR_TRIG_MASK 0x2 #ifndef GIC_DEFAULT_ICFGR_INIT #define GIC_DEFAULT_ICFGR_INIT 0x00000000 #endif #ifdef ARM_INTRNG static u_int gic_irq_cpu; static int arm_gic_intr(void *); -static int arm_gic_bind(device_t dev, struct arm_irqsrc *isrc); +static int arm_gic_bind(device_t dev, struct intr_irqsrc *isrc); #endif struct arm_gic_softc { device_t gic_dev; #ifdef ARM_INTRNG void * gic_intrhand; - struct arm_irqsrc ** gic_irqs; + struct intr_irqsrc ** gic_irqs; #endif struct resource * gic_res[3]; bus_space_tag_t gic_c_bst; bus_space_tag_t gic_d_bst; bus_space_handle_t gic_c_bsh; bus_space_handle_t gic_d_bsh; uint8_t ver; struct mtx mutex; uint32_t nirqs; #ifdef GIC_DEBUG_SPURIOUS uint32_t last_irq[MAXCPU]; #endif }; static struct resource_spec arm_gic_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Distributor registers */ { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* CPU Interrupt Intf. registers */ #ifdef ARM_INTRNG { SYS_RES_IRQ, 0, RF_ACTIVE | RF_OPTIONAL }, /* Parent interrupt */ #endif { -1, 0 } }; static struct arm_gic_softc *gic_sc = NULL; #define gic_c_read_4(_sc, _reg) \ bus_space_read_4((_sc)->gic_c_bst, (_sc)->gic_c_bsh, (_reg)) #define gic_c_write_4(_sc, _reg, _val) \ bus_space_write_4((_sc)->gic_c_bst, (_sc)->gic_c_bsh, (_reg), (_val)) #define gic_d_read_4(_sc, _reg) \ bus_space_read_4((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg)) #define gic_d_write_1(_sc, _reg, _val) \ bus_space_write_1((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg), (_val)) #define gic_d_write_4(_sc, _reg, _val) \ bus_space_write_4((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg), (_val)) #ifndef ARM_INTRNG static int gic_config_irq(int irq, enum intr_trigger trig, enum intr_polarity pol); static void gic_post_filter(void *); #endif static struct ofw_compat_data compat_data[] = { {"arm,gic", true}, /* Non-standard, used in FreeBSD dts. */ {"arm,gic-400", true}, {"arm,cortex-a15-gic", true}, {"arm,cortex-a9-gic", true}, {"arm,cortex-a7-gic", true}, {"arm,arm11mp-gic", true}, {"brcm,brahma-b15-gic", true}, {NULL, false} }; static int arm_gic_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) return (ENXIO); device_set_desc(dev, "ARM Generic Interrupt Controller"); return (BUS_PROBE_DEFAULT); } #ifdef ARM_INTRNG static inline void gic_irq_unmask(struct arm_gic_softc *sc, u_int irq) { gic_d_write_4(sc, GICD_ISENABLER(irq >> 5), (1UL << (irq & 0x1F))); } static inline void gic_irq_mask(struct arm_gic_softc *sc, u_int irq) { gic_d_write_4(sc, GICD_ICENABLER(irq >> 5), (1UL << (irq & 0x1F))); } #endif #ifdef SMP #ifdef ARM_INTRNG static void arm_gic_init_secondary(device_t dev) { struct arm_gic_softc *sc = device_get_softc(dev); - struct arm_irqsrc *isrc; + struct intr_irqsrc *isrc; u_int irq; for (irq = 0; irq < sc->nirqs; irq += 4) gic_d_write_4(sc, GICD_IPRIORITYR(irq >> 2), 0); /* Set all the interrupts to be in Group 0 (secure) */ for (irq = 0; irq < sc->nirqs; irq += 32) { gic_d_write_4(sc, GICD_IGROUPR(irq >> 5), 0); } /* Enable CPU interface */ gic_c_write_4(sc, GICC_CTLR, 1); /* Set priority mask register. */ gic_c_write_4(sc, GICC_PMR, 0xff); /* Enable interrupt distribution */ gic_d_write_4(sc, GICD_CTLR, 0x01); /* Unmask attached SGI interrupts. */ for (irq = GIC_FIRST_SGI; irq <= GIC_LAST_SGI; irq++) { isrc = sc->gic_irqs[irq]; if (isrc != NULL && isrc->isrc_handlers != 0) { CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu); gic_irq_unmask(sc, irq); } } /* Unmask attached PPI interrupts. */ for (irq = GIC_FIRST_PPI; irq <= GIC_LAST_PPI; irq++) { isrc = sc->gic_irqs[irq]; if (isrc == NULL || isrc->isrc_handlers == 0) continue; - if (isrc->isrc_flags & ARM_ISRCF_BOUND) { + if (isrc->isrc_flags & INTR_ISRCF_BOUND) { if (CPU_ISSET(PCPU_GET(cpuid), &isrc->isrc_cpu)) gic_irq_unmask(sc, irq); } else { CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu); gic_irq_unmask(sc, irq); } } } #else static void arm_gic_init_secondary(device_t dev) { struct arm_gic_softc *sc = device_get_softc(dev); int i; for (i = 0; i < sc->nirqs; i += 4) gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0); /* Set all the interrupts to be in Group 0 (secure) */ for (i = 0; i < sc->nirqs; i += 32) { gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0); } /* Enable CPU interface */ gic_c_write_4(sc, GICC_CTLR, 1); /* Set priority mask register. */ gic_c_write_4(sc, GICC_PMR, 0xff); /* Enable interrupt distribution */ gic_d_write_4(sc, GICD_CTLR, 0x01); /* * Activate the timer interrupts: virtual, secure, and non-secure. */ gic_d_write_4(sc, GICD_ISENABLER(27 >> 5), (1UL << (27 & 0x1F))); gic_d_write_4(sc, GICD_ISENABLER(29 >> 5), (1UL << (29 & 0x1F))); gic_d_write_4(sc, GICD_ISENABLER(30 >> 5), (1UL << (30 & 0x1F))); } #endif /* ARM_INTRNG */ #endif /* SMP */ #ifndef ARM_INTRNG int gic_decode_fdt(phandle_t iparent, pcell_t *intr, int *interrupt, int *trig, int *pol) { static u_int num_intr_cells; static phandle_t self; struct ofw_compat_data *ocd; if (self == 0) { for (ocd = compat_data; ocd->ocd_str != NULL; ocd++) { if (fdt_is_compatible(iparent, ocd->ocd_str)) { self = iparent; break; } } } if (self != iparent) return (ENXIO); if (num_intr_cells == 0) { if (OF_searchencprop(OF_node_from_xref(iparent), "#interrupt-cells", &num_intr_cells, sizeof(num_intr_cells)) == -1) { num_intr_cells = 1; } } if (num_intr_cells == 1) { *interrupt = fdt32_to_cpu(intr[0]); *trig = INTR_TRIGGER_CONFORM; *pol = INTR_POLARITY_CONFORM; } else { if (fdt32_to_cpu(intr[0]) == 0) *interrupt = fdt32_to_cpu(intr[1]) + GIC_FIRST_SPI; else *interrupt = fdt32_to_cpu(intr[1]) + GIC_FIRST_PPI; /* * In intr[2], bits[3:0] are trigger type and level flags. * 1 = low-to-high edge triggered * 2 = high-to-low edge triggered * 4 = active high level-sensitive * 8 = active low level-sensitive * The hardware only supports active-high-level or rising-edge. */ if (fdt32_to_cpu(intr[2]) & 0x0a) { printf("unsupported trigger/polarity configuration " "0x%02x\n", fdt32_to_cpu(intr[2]) & 0x0f); } *pol = INTR_POLARITY_CONFORM; if (fdt32_to_cpu(intr[2]) & 0x03) *trig = INTR_TRIGGER_EDGE; else *trig = INTR_TRIGGER_LEVEL; } return (0); } #endif #ifdef ARM_INTRNG static inline intptr_t gic_xref(device_t dev) { #ifdef FDT return (OF_xref_from_node(ofw_bus_get_node(dev))); #else return (0); #endif } #endif static int arm_gic_attach(device_t dev) { struct arm_gic_softc *sc; int i; uint32_t icciidr; #ifdef ARM_INTRNG phandle_t pxref; intptr_t xref = gic_xref(dev); #endif if (gic_sc) return (ENXIO); sc = device_get_softc(dev); if (bus_alloc_resources(dev, arm_gic_spec, sc->gic_res)) { device_printf(dev, "could not allocate resources\n"); return (ENXIO); } sc->gic_dev = dev; gic_sc = sc; /* Initialize mutex */ mtx_init(&sc->mutex, "GIC lock", "", MTX_SPIN); /* Distributor Interface */ sc->gic_d_bst = rman_get_bustag(sc->gic_res[0]); sc->gic_d_bsh = rman_get_bushandle(sc->gic_res[0]); /* CPU Interface */ sc->gic_c_bst = rman_get_bustag(sc->gic_res[1]); sc->gic_c_bsh = rman_get_bushandle(sc->gic_res[1]); /* Disable interrupt forwarding to the CPU interface */ gic_d_write_4(sc, GICD_CTLR, 0x00); /* Get the number of interrupts */ sc->nirqs = gic_d_read_4(sc, GICD_TYPER); sc->nirqs = 32 * ((sc->nirqs & 0x1f) + 1); #ifdef ARM_INTRNG sc->gic_irqs = malloc(sc->nirqs * sizeof (*sc->gic_irqs), M_DEVBUF, M_WAITOK | M_ZERO); #else /* Set up function pointers */ arm_post_filter = gic_post_filter; arm_config_irq = gic_config_irq; #endif icciidr = gic_c_read_4(sc, GICC_IIDR); device_printf(dev,"pn 0x%x, arch 0x%x, rev 0x%x, implementer 0x%x irqs %u\n", icciidr>>20, (icciidr>>16) & 0xF, (icciidr>>12) & 0xf, (icciidr & 0xfff), sc->nirqs); /* Set all global interrupts to be level triggered, active low. */ for (i = 32; i < sc->nirqs; i += 16) { gic_d_write_4(sc, GICD_ICFGR(i >> 4), GIC_DEFAULT_ICFGR_INIT); } /* Disable all interrupts. */ for (i = 32; i < sc->nirqs; i += 32) { gic_d_write_4(sc, GICD_ICENABLER(i >> 5), 0xFFFFFFFF); } for (i = 0; i < sc->nirqs; i += 4) { gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0); gic_d_write_4(sc, GICD_ITARGETSR(i >> 2), 1 << 0 | 1 << 8 | 1 << 16 | 1 << 24); } /* Set all the interrupts to be in Group 0 (secure) */ for (i = 0; i < sc->nirqs; i += 32) { gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0); } /* Enable CPU interface */ gic_c_write_4(sc, GICC_CTLR, 1); /* Set priority mask register. */ gic_c_write_4(sc, GICC_PMR, 0xff); /* Enable interrupt distribution */ gic_d_write_4(sc, GICD_CTLR, 0x01); #ifndef ARM_INTRNG return (0); #else /* * Now, when everything is initialized, it's right time to * register interrupt controller to interrupt framefork. */ - if (arm_pic_register(dev, xref) != 0) { + if (intr_pic_register(dev, xref) != 0) { device_printf(dev, "could not register PIC\n"); goto cleanup; } /* * Controller is root if: * - doesn't have interrupt parent * - his interrupt parent is this controller */ pxref = ofw_bus_find_iparent(ofw_bus_get_node(dev)); if (pxref == 0 || xref == pxref) { - if (arm_pic_claim_root(dev, xref, arm_gic_intr, sc, + if (intr_pic_claim_root(dev, xref, arm_gic_intr, sc, GIC_LAST_SGI - GIC_FIRST_SGI + 1) != 0) { device_printf(dev, "could not set PIC as a root\n"); - arm_pic_unregister(dev, xref); + intr_pic_unregister(dev, xref); goto cleanup; } } else { if (sc->gic_res[2] == NULL) { device_printf(dev, "not root PIC must have defined interrupt\n"); - arm_pic_unregister(dev, xref); + intr_pic_unregister(dev, xref); goto cleanup; } if (bus_setup_intr(dev, sc->gic_res[2], INTR_TYPE_CLK, arm_gic_intr, NULL, sc, &sc->gic_intrhand)) { device_printf(dev, "could not setup irq handler\n"); - arm_pic_unregister(dev, xref); + intr_pic_unregister(dev, xref); goto cleanup; } } OF_device_register_xref(xref, dev); return (0); cleanup: /* * XXX - not implemented arm_gic_detach() should be called ! */ if (sc->gic_irqs != NULL) free(sc->gic_irqs, M_DEVBUF); bus_release_resources(dev, arm_gic_spec, sc->gic_res); return(ENXIO); #endif } #ifdef ARM_INTRNG static int arm_gic_intr(void *arg) { struct arm_gic_softc *sc = arg; - struct arm_irqsrc *isrc; + struct intr_irqsrc *isrc; uint32_t irq_active_reg, irq; struct trapframe *tf; irq_active_reg = gic_c_read_4(sc, GICC_IAR); irq = irq_active_reg & 0x3FF; /* * 1. We do EOI here because recent read value from active interrupt * register must be used for it. Another approach is to save this * value into associated interrupt source. * 2. EOI must be done on same CPU where interrupt has fired. Thus * we must ensure that interrupted thread does not migrate to * another CPU. * 3. EOI cannot be delayed by any preemption which could happen on * critical_exit() used in MI intr code, when interrupt thread is * scheduled. See next point. * 4. IPI_RENDEZVOUS assumes that no preemption is permitted during * an action and any use of critical_exit() could break this * assumption. See comments within smp_rendezvous_action(). * 5. We always return FILTER_HANDLED as this is an interrupt * controller dispatch function. Otherwise, in cascaded interrupt * case, the whole interrupt subtree would be masked. */ if (irq >= sc->nirqs) { #ifdef GIC_DEBUG_SPURIOUS device_printf(sc->gic_dev, "Spurious interrupt detected: last irq: %d on CPU%d\n", sc->last_irq[PCPU_GET(cpuid)], PCPU_GET(cpuid)); #endif return (FILTER_HANDLED); } tf = curthread->td_intr_frame; dispatch_irq: isrc = sc->gic_irqs[irq]; if (isrc == NULL) { device_printf(sc->gic_dev, "Stray interrupt %u detected\n", irq); gic_irq_mask(sc, irq); gic_c_write_4(sc, GICC_EOIR, irq_active_reg); goto next_irq; } /* * Note that GIC_FIRST_SGI is zero and is not used in 'if' statement * as compiler complains that comparing u_int >= 0 is always true. */ if (irq <= GIC_LAST_SGI) { #ifdef SMP /* Call EOI for all IPI before dispatch. */ gic_c_write_4(sc, GICC_EOIR, irq_active_reg); - arm_ipi_dispatch(isrc, tf); + intr_ipi_dispatch(isrc, tf); goto next_irq; #else device_printf(sc->gic_dev, "SGI %u on UP system detected\n", irq - GIC_FIRST_SGI); gic_c_write_4(sc, GICC_EOIR, irq_active_reg); goto next_irq; #endif } #ifdef GIC_DEBUG_SPURIOUS sc->last_irq[PCPU_GET(cpuid)] = irq; #endif if (isrc->isrc_trig == INTR_TRIGGER_EDGE) gic_c_write_4(sc, GICC_EOIR, irq_active_reg); - arm_irq_dispatch(isrc, tf); + intr_irq_dispatch(isrc, tf); next_irq: arm_irq_memory_barrier(irq); irq_active_reg = gic_c_read_4(sc, GICC_IAR); irq = irq_active_reg & 0x3FF; if (irq < sc->nirqs) goto dispatch_irq; return (FILTER_HANDLED); } static int -gic_attach_isrc(struct arm_gic_softc *sc, struct arm_irqsrc *isrc, u_int irq) +gic_attach_isrc(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int irq) { const char *name; /* * 1. The link between ISRC and controller must be set atomically. * 2. Just do things only once in rare case when consumers * of shared interrupt came here at the same moment. */ mtx_lock_spin(&sc->mutex); if (sc->gic_irqs[irq] != NULL) { mtx_unlock_spin(&sc->mutex); return (sc->gic_irqs[irq] == isrc ? 0 : EEXIST); } sc->gic_irqs[irq] = isrc; isrc->isrc_data = irq; mtx_unlock_spin(&sc->mutex); name = device_get_nameunit(sc->gic_dev); if (irq <= GIC_LAST_SGI) - arm_irq_set_name(isrc, "%s,i%u", name, irq - GIC_FIRST_SGI); + intr_irq_set_name(isrc, "%s,i%u", name, irq - GIC_FIRST_SGI); else if (irq <= GIC_LAST_PPI) - arm_irq_set_name(isrc, "%s,p%u", name, irq - GIC_FIRST_PPI); + intr_irq_set_name(isrc, "%s,p%u", name, irq - GIC_FIRST_PPI); else - arm_irq_set_name(isrc, "%s,s%u", name, irq - GIC_FIRST_SPI); + intr_irq_set_name(isrc, "%s,s%u", name, irq - GIC_FIRST_SPI); return (0); } static int -gic_detach_isrc(struct arm_gic_softc *sc, struct arm_irqsrc *isrc, u_int irq) +gic_detach_isrc(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int irq) { mtx_lock_spin(&sc->mutex); if (sc->gic_irqs[irq] != isrc) { mtx_unlock_spin(&sc->mutex); return (sc->gic_irqs[irq] == NULL ? 0 : EINVAL); } sc->gic_irqs[irq] = NULL; isrc->isrc_data = 0; mtx_unlock_spin(&sc->mutex); - arm_irq_set_name(isrc, ""); + intr_irq_set_name(isrc, ""); return (0); } static void gic_config(struct arm_gic_softc *sc, u_int irq, enum intr_trigger trig, enum intr_polarity pol) { uint32_t reg; uint32_t mask; if (irq < GIC_FIRST_SPI) return; mtx_lock_spin(&sc->mutex); reg = gic_d_read_4(sc, GICD_ICFGR(irq >> 4)); mask = (reg >> 2*(irq % 16)) & 0x3; if (pol == INTR_POLARITY_LOW) { mask &= ~GICD_ICFGR_POL_MASK; mask |= GICD_ICFGR_POL_LOW; } else if (pol == INTR_POLARITY_HIGH) { mask &= ~GICD_ICFGR_POL_MASK; mask |= GICD_ICFGR_POL_HIGH; } if (trig == INTR_TRIGGER_LEVEL) { mask &= ~GICD_ICFGR_TRIG_MASK; mask |= GICD_ICFGR_TRIG_LVL; } else if (trig == INTR_TRIGGER_EDGE) { mask &= ~GICD_ICFGR_TRIG_MASK; mask |= GICD_ICFGR_TRIG_EDGE; } /* Set mask */ reg = reg & ~(0x3 << 2*(irq % 16)); reg = reg | (mask << 2*(irq % 16)); gic_d_write_4(sc, GICD_ICFGR(irq >> 4), reg); mtx_unlock_spin(&sc->mutex); } static int gic_bind(struct arm_gic_softc *sc, u_int irq, cpuset_t *cpus) { uint32_t cpu, end, mask; end = min(mp_ncpus, 8); for (cpu = end; cpu < MAXCPU; cpu++) if (CPU_ISSET(cpu, cpus)) return (EINVAL); for (mask = 0, cpu = 0; cpu < end; cpu++) if (CPU_ISSET(cpu, cpus)) mask |= 1 << cpu; gic_d_write_1(sc, GICD_ITARGETSR(0) + irq, mask); return (0); } static int gic_irq_from_nspc(struct arm_gic_softc *sc, u_int type, u_int num, u_int *irqp) { switch (type) { - case ARM_IRQ_NSPC_PLAIN: + case INTR_IRQ_NSPC_PLAIN: *irqp = num; return (*irqp < sc->nirqs ? 0 : EINVAL); - case ARM_IRQ_NSPC_IRQ: + case INTR_IRQ_NSPC_IRQ: *irqp = num + GIC_FIRST_PPI; return (*irqp < sc->nirqs ? 0 : EINVAL); - case ARM_IRQ_NSPC_IPI: + case INTR_IRQ_NSPC_IPI: *irqp = num + GIC_FIRST_SGI; return (*irqp < GIC_LAST_SGI ? 0 : EINVAL); default: return (EINVAL); } } static int -gic_map_nspc(struct arm_gic_softc *sc, struct arm_irqsrc *isrc, u_int *irqp) +gic_map_nspc(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp) { int error; error = gic_irq_from_nspc(sc, isrc->isrc_nspc_type, isrc->isrc_nspc_num, irqp); if (error != 0) return (error); return (gic_attach_isrc(sc, isrc, *irqp)); } #ifdef FDT static int -gic_map_fdt(struct arm_gic_softc *sc, struct arm_irqsrc *isrc, u_int *irqp) +gic_map_fdt(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp) { u_int irq, tripol; enum intr_trigger trig; enum intr_polarity pol; int error; if (isrc->isrc_ncells == 1) { irq = isrc->isrc_cells[0]; pol = INTR_POLARITY_CONFORM; trig = INTR_TRIGGER_CONFORM; } else if (isrc->isrc_ncells == 3) { if (isrc->isrc_cells[0] == 0) irq = isrc->isrc_cells[1] + GIC_FIRST_SPI; else irq = isrc->isrc_cells[1] + GIC_FIRST_PPI; /* * In intr[2], bits[3:0] are trigger type and level flags. * 1 = low-to-high edge triggered * 2 = high-to-low edge triggered * 4 = active high level-sensitive * 8 = active low level-sensitive * The hardware only supports active-high-level or rising-edge. */ tripol = isrc->isrc_cells[2]; if (tripol & 0x0a) { device_printf(sc->gic_dev, "unsupported trigger/polarity configuration " "0x%02x\n", tripol & 0x0f); } pol = INTR_POLARITY_CONFORM; if (tripol & 0x03) trig = INTR_TRIGGER_EDGE; else trig = INTR_TRIGGER_LEVEL; } else return (EINVAL); if (irq >= sc->nirqs) return (EINVAL); error = gic_attach_isrc(sc, isrc, irq); if (error != 0) return (error); - isrc->isrc_nspc_type = ARM_IRQ_NSPC_PLAIN; + isrc->isrc_nspc_type = INTR_IRQ_NSPC_PLAIN; isrc->isrc_nspc_num = irq; isrc->isrc_trig = trig; isrc->isrc_pol = pol; *irqp = irq; return (0); } #endif static int -arm_gic_register(device_t dev, struct arm_irqsrc *isrc, boolean_t *is_percpu) +arm_gic_register(device_t dev, struct intr_irqsrc *isrc, boolean_t *is_percpu) { struct arm_gic_softc *sc = device_get_softc(dev); u_int irq; int error; - if (isrc->isrc_type == ARM_ISRCT_NAMESPACE) + if (isrc->isrc_type == INTR_ISRCT_NAMESPACE) error = gic_map_nspc(sc, isrc, &irq); #ifdef FDT - else if (isrc->isrc_type == ARM_ISRCT_FDT) + else if (isrc->isrc_type == INTR_ISRCT_FDT) error = gic_map_fdt(sc, isrc, &irq); #endif else return (EINVAL); if (error == 0) *is_percpu = irq < GIC_FIRST_SPI ? TRUE : FALSE; return (error); } static void -arm_gic_enable_intr(device_t dev, struct arm_irqsrc *isrc) +arm_gic_enable_intr(device_t dev, struct intr_irqsrc *isrc) { struct arm_gic_softc *sc = device_get_softc(dev); u_int irq = isrc->isrc_data; if (isrc->isrc_trig == INTR_TRIGGER_CONFORM) isrc->isrc_trig = INTR_TRIGGER_LEVEL; /* * XXX - In case that per CPU interrupt is going to be enabled in time * when SMP is already started, we need some IPI call which * enables it on others CPUs. Further, it's more complicated as * pic_enable_source() and pic_disable_source() should act on * per CPU basis only. Thus, it should be solved here somehow. */ - if (isrc->isrc_flags & ARM_ISRCF_PERCPU) + if (isrc->isrc_flags & INTR_ISRCF_PERCPU) CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu); gic_config(sc, irq, isrc->isrc_trig, isrc->isrc_pol); arm_gic_bind(dev, isrc); } static void -arm_gic_enable_source(device_t dev, struct arm_irqsrc *isrc) +arm_gic_enable_source(device_t dev, struct intr_irqsrc *isrc) { struct arm_gic_softc *sc = device_get_softc(dev); u_int irq = isrc->isrc_data; arm_irq_memory_barrier(irq); gic_irq_unmask(sc, irq); } static void -arm_gic_disable_source(device_t dev, struct arm_irqsrc *isrc) +arm_gic_disable_source(device_t dev, struct intr_irqsrc *isrc) { struct arm_gic_softc *sc = device_get_softc(dev); u_int irq = isrc->isrc_data; gic_irq_mask(sc, irq); } static int -arm_gic_unregister(device_t dev, struct arm_irqsrc *isrc) +arm_gic_unregister(device_t dev, struct intr_irqsrc *isrc) { struct arm_gic_softc *sc = device_get_softc(dev); u_int irq = isrc->isrc_data; return (gic_detach_isrc(sc, isrc, irq)); } static void -arm_gic_pre_ithread(device_t dev, struct arm_irqsrc *isrc) +arm_gic_pre_ithread(device_t dev, struct intr_irqsrc *isrc) { struct arm_gic_softc *sc = device_get_softc(dev); arm_gic_disable_source(dev, isrc); gic_c_write_4(sc, GICC_EOIR, isrc->isrc_data); } static void -arm_gic_post_ithread(device_t dev, struct arm_irqsrc *isrc) +arm_gic_post_ithread(device_t dev, struct intr_irqsrc *isrc) { arm_irq_memory_barrier(0); arm_gic_enable_source(dev, isrc); } static void -arm_gic_post_filter(device_t dev, struct arm_irqsrc *isrc) +arm_gic_post_filter(device_t dev, struct intr_irqsrc *isrc) { struct arm_gic_softc *sc = device_get_softc(dev); /* EOI for edge-triggered done earlier. */ if (isrc->isrc_trig == INTR_TRIGGER_EDGE) return; arm_irq_memory_barrier(0); gic_c_write_4(sc, GICC_EOIR, isrc->isrc_data); } static int -arm_gic_bind(device_t dev, struct arm_irqsrc *isrc) +arm_gic_bind(device_t dev, struct intr_irqsrc *isrc) { struct arm_gic_softc *sc = device_get_softc(dev); uint32_t irq = isrc->isrc_data; if (irq < GIC_FIRST_SPI) return (EINVAL); if (CPU_EMPTY(&isrc->isrc_cpu)) { - gic_irq_cpu = arm_irq_next_cpu(gic_irq_cpu, &all_cpus); + gic_irq_cpu = intr_irq_next_cpu(gic_irq_cpu, &all_cpus); CPU_SETOF(gic_irq_cpu, &isrc->isrc_cpu); } return (gic_bind(sc, irq, &isrc->isrc_cpu)); } #ifdef SMP static void -arm_gic_ipi_send(device_t dev, struct arm_irqsrc *isrc, cpuset_t cpus) +arm_gic_ipi_send(device_t dev, struct intr_irqsrc *isrc, cpuset_t cpus) { struct arm_gic_softc *sc = device_get_softc(dev); uint32_t irq, val = 0, i; irq = isrc->isrc_data; for (i = 0; i < MAXCPU; i++) if (CPU_ISSET(i, &cpus)) val |= 1 << (16 + i); gic_d_write_4(sc, GICD_SGIR(0), val | irq); } #endif #else static int arm_gic_next_irq(struct arm_gic_softc *sc, int last_irq) { uint32_t active_irq; active_irq = gic_c_read_4(sc, GICC_IAR); /* * Immediatly EOIR the SGIs, because doing so requires the other * bits (ie CPU number), not just the IRQ number, and we do not * have this information later. */ if ((active_irq & 0x3ff) <= GIC_LAST_SGI) gic_c_write_4(sc, GICC_EOIR, active_irq); active_irq &= 0x3FF; if (active_irq == 0x3FF) { if (last_irq == -1) device_printf(sc->gic_dev, "Spurious interrupt detected\n"); return -1; } return active_irq; } static int arm_gic_config(device_t dev, int irq, enum intr_trigger trig, enum intr_polarity pol) { struct arm_gic_softc *sc = device_get_softc(dev); uint32_t reg; uint32_t mask; /* Function is public-accessible, so validate input arguments */ if ((irq < 0) || (irq >= sc->nirqs)) goto invalid_args; if ((trig != INTR_TRIGGER_EDGE) && (trig != INTR_TRIGGER_LEVEL) && (trig != INTR_TRIGGER_CONFORM)) goto invalid_args; if ((pol != INTR_POLARITY_HIGH) && (pol != INTR_POLARITY_LOW) && (pol != INTR_POLARITY_CONFORM)) goto invalid_args; mtx_lock_spin(&sc->mutex); reg = gic_d_read_4(sc, GICD_ICFGR(irq >> 4)); mask = (reg >> 2*(irq % 16)) & 0x3; if (pol == INTR_POLARITY_LOW) { mask &= ~GICD_ICFGR_POL_MASK; mask |= GICD_ICFGR_POL_LOW; } else if (pol == INTR_POLARITY_HIGH) { mask &= ~GICD_ICFGR_POL_MASK; mask |= GICD_ICFGR_POL_HIGH; } if (trig == INTR_TRIGGER_LEVEL) { mask &= ~GICD_ICFGR_TRIG_MASK; mask |= GICD_ICFGR_TRIG_LVL; } else if (trig == INTR_TRIGGER_EDGE) { mask &= ~GICD_ICFGR_TRIG_MASK; mask |= GICD_ICFGR_TRIG_EDGE; } /* Set mask */ reg = reg & ~(0x3 << 2*(irq % 16)); reg = reg | (mask << 2*(irq % 16)); gic_d_write_4(sc, GICD_ICFGR(irq >> 4), reg); mtx_unlock_spin(&sc->mutex); return (0); invalid_args: device_printf(dev, "gic_config_irg, invalid parameters\n"); return (EINVAL); } static void arm_gic_mask(device_t dev, int irq) { struct arm_gic_softc *sc = device_get_softc(dev); gic_d_write_4(sc, GICD_ICENABLER(irq >> 5), (1UL << (irq & 0x1F))); gic_c_write_4(sc, GICC_EOIR, irq); /* XXX - not allowed */ } static void arm_gic_unmask(device_t dev, int irq) { struct arm_gic_softc *sc = device_get_softc(dev); if (irq > GIC_LAST_SGI) arm_irq_memory_barrier(irq); gic_d_write_4(sc, GICD_ISENABLER(irq >> 5), (1UL << (irq & 0x1F))); } #ifdef SMP static void arm_gic_ipi_send(device_t dev, cpuset_t cpus, u_int ipi) { struct arm_gic_softc *sc = device_get_softc(dev); uint32_t val = 0, i; for (i = 0; i < MAXCPU; i++) if (CPU_ISSET(i, &cpus)) val |= 1 << (16 + i); gic_d_write_4(sc, GICD_SGIR(0), val | ipi); } static int arm_gic_ipi_read(device_t dev, int i) { if (i != -1) { /* * The intr code will automagically give the frame pointer * if the interrupt argument is 0. */ if ((unsigned int)i > 16) return (0); return (i); } return (0x3ff); } static void arm_gic_ipi_clear(device_t dev, int ipi) { /* no-op */ } #endif static void gic_post_filter(void *arg) { struct arm_gic_softc *sc = gic_sc; uintptr_t irq = (uintptr_t) arg; if (irq > GIC_LAST_SGI) arm_irq_memory_barrier(irq); gic_c_write_4(sc, GICC_EOIR, irq); } static int gic_config_irq(int irq, enum intr_trigger trig, enum intr_polarity pol) { return (arm_gic_config(gic_sc->gic_dev, irq, trig, pol)); } void arm_mask_irq(uintptr_t nb) { arm_gic_mask(gic_sc->gic_dev, nb); } void arm_unmask_irq(uintptr_t nb) { arm_gic_unmask(gic_sc->gic_dev, nb); } int arm_get_next_irq(int last_irq) { return (arm_gic_next_irq(gic_sc, last_irq)); } #ifdef SMP void -arm_pic_init_secondary(void) +intr_pic_init_secondary(void) { arm_gic_init_secondary(gic_sc->gic_dev); } void pic_ipi_send(cpuset_t cpus, u_int ipi) { arm_gic_ipi_send(gic_sc->gic_dev, cpus, ipi); } int pic_ipi_read(int i) { return (arm_gic_ipi_read(gic_sc->gic_dev, i)); } void pic_ipi_clear(int ipi) { arm_gic_ipi_clear(gic_sc->gic_dev, ipi); } #endif #endif /* ARM_INTRNG */ static device_method_t arm_gic_methods[] = { /* Device interface */ DEVMETHOD(device_probe, arm_gic_probe), DEVMETHOD(device_attach, arm_gic_attach), #ifdef ARM_INTRNG /* Interrupt controller interface */ DEVMETHOD(pic_disable_source, arm_gic_disable_source), DEVMETHOD(pic_enable_intr, arm_gic_enable_intr), DEVMETHOD(pic_enable_source, arm_gic_enable_source), DEVMETHOD(pic_post_filter, arm_gic_post_filter), DEVMETHOD(pic_post_ithread, arm_gic_post_ithread), DEVMETHOD(pic_pre_ithread, arm_gic_pre_ithread), DEVMETHOD(pic_register, arm_gic_register), DEVMETHOD(pic_unregister, arm_gic_unregister), #ifdef SMP DEVMETHOD(pic_bind, arm_gic_bind), DEVMETHOD(pic_init_secondary, arm_gic_init_secondary), DEVMETHOD(pic_ipi_send, arm_gic_ipi_send), #endif #endif { 0, 0 } }; static driver_t arm_gic_driver = { "gic", arm_gic_methods, sizeof(struct arm_gic_softc), }; static devclass_t arm_gic_devclass; EARLY_DRIVER_MODULE(gic, simplebus, arm_gic_driver, arm_gic_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); EARLY_DRIVER_MODULE(gic, ofwbus, arm_gic_driver, arm_gic_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); Index: user/alc/PQ_LAUNDRY/sys/arm/arm/intr.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/arm/intr.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/arm/intr.c (revision 292449) @@ -1,265 +1,201 @@ /* $NetBSD: intr.c,v 1.12 2003/07/15 00:24:41 lukem Exp $ */ /*- * Copyright (c) 2004 Olivier Houchard. * Copyright (c) 1994-1998 Mark Brinicombe. * 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 Mark Brinicombe * for the NetBSD Project. * 4. The name of the company nor the name of the author may be used to * endorse or promote products derived from this software without specific * prior written permission. * * 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 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. * * Soft interrupt and other generic interrupt functions. */ #include "opt_platform.h" #include "opt_hwpmc_hooks.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef FDT #include #include #endif #define INTRNAME_LEN (MAXCOMLEN + 1) typedef void (*mask_fn)(void *); static struct intr_event *intr_events[NIRQ]; -void arm_irq_handler(struct trapframe *); +void intr_irq_handler(struct trapframe *); void (*arm_post_filter)(void *) = NULL; int (*arm_config_irq)(int irq, enum intr_trigger trig, enum intr_polarity pol) = NULL; /* Data for statistics reporting. */ u_long intrcnt[NIRQ]; char intrnames[(NIRQ * INTRNAME_LEN) + 1]; size_t sintrcnt = sizeof(intrcnt); size_t sintrnames = sizeof(intrnames); /* * Pre-format intrnames into an array of fixed-size strings containing spaces. * This allows us to avoid the need for an intermediate table of indices into * the names and counts arrays, while still meeting the requirements and * assumptions of vmstat(8) and the kdb "show intrcnt" command, the two * consumers of this data. */ static void intr_init(void *unused) { int i; for (i = 0; i < NIRQ; ++i) { snprintf(&intrnames[i * INTRNAME_LEN], INTRNAME_LEN, "%-*s", INTRNAME_LEN - 1, ""); } } SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL); #ifdef FDT int -arm_fdt_map_irq(phandle_t iparent, pcell_t *intr, int icells) +intr_fdt_map_irq(phandle_t iparent, pcell_t *intr, int icells) { fdt_pic_decode_t intr_decode; phandle_t intr_parent; int i, rv, interrupt, trig, pol; intr_parent = OF_node_from_xref(iparent); for (i = 0; i < icells; i++) intr[i] = cpu_to_fdt32(intr[i]); for (i = 0; fdt_pic_table[i] != NULL; i++) { intr_decode = fdt_pic_table[i]; rv = intr_decode(intr_parent, intr, &interrupt, &trig, &pol); if (rv == 0) { /* This was recognized as our PIC and decoded. */ interrupt = FDT_MAP_IRQ(intr_parent, interrupt); return (interrupt); } } /* Not in table, so guess */ interrupt = FDT_MAP_IRQ(intr_parent, fdt32_to_cpu(intr[0])); return (interrupt); } #endif void arm_setup_irqhandler(const char *name, driver_filter_t *filt, void (*hand)(void*), void *arg, int irq, int flags, void **cookiep) { struct intr_event *event; int error; if (irq < 0 || irq >= NIRQ) return; event = intr_events[irq]; if (event == NULL) { error = intr_event_create(&event, (void *)irq, 0, irq, (mask_fn)arm_mask_irq, (mask_fn)arm_unmask_irq, arm_post_filter, NULL, "intr%d:", irq); if (error) return; intr_events[irq] = event; snprintf(&intrnames[irq * INTRNAME_LEN], INTRNAME_LEN, "irq%d: %-*s", irq, INTRNAME_LEN - 1, name); } intr_event_add_handler(event, name, filt, hand, arg, intr_priority(flags), flags, cookiep); } int arm_remove_irqhandler(int irq, void *cookie) { struct intr_event *event; int error; event = intr_events[irq]; arm_mask_irq(irq); error = intr_event_remove_handler(cookie); if (!TAILQ_EMPTY(&event->ie_handlers)) arm_unmask_irq(irq); return (error); } void dosoftints(void); void dosoftints(void) { } void -arm_irq_handler(struct trapframe *frame) +intr_irq_handler(struct trapframe *frame) { struct intr_event *event; int i; PCPU_INC(cnt.v_intr); i = -1; while ((i = arm_get_next_irq(i)) != -1) { intrcnt[i]++; event = intr_events[i]; if (intr_event_handle(event, frame) != 0) { /* XXX: Log stray IRQs */ arm_mask_irq(i); } } #ifdef HWPMC_HOOKS if (pmc_hook && (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN)) pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, frame); #endif } - -/* - * arm_irq_memory_barrier() - * - * Ensure all writes to device memory have reached devices before proceeding. - * - * This is intended to be called from the post-filter and post-thread routines - * of an interrupt controller implementation. A peripheral device driver should - * use bus_space_barrier() if it needs to ensure a write has reached the - * hardware for some reason other than clearing interrupt conditions. - * - * The need for this function arises from the ARM weak memory ordering model. - * Writes to locations mapped with the Device attribute bypass any caches, but - * are buffered. Multiple writes to the same device will be observed by that - * device in the order issued by the cpu. Writes to different devices may - * appear at those devices in a different order than issued by the cpu. That - * is, if the cpu writes to device A then device B, the write to device B could - * complete before the write to device A. - * - * Consider a typical device interrupt handler which services the interrupt and - * writes to a device status-acknowledge register to clear the interrupt before - * returning. That write is posted to the L2 controller which "immediately" - * places it in a store buffer and automatically drains that buffer. This can - * be less immediate than you'd think... There may be no free slots in the store - * buffers, so an existing buffer has to be drained first to make room. The - * target bus may be busy with other traffic (such as DMA for various devices), - * delaying the drain of the store buffer for some indeterminate time. While - * all this delay is happening, execution proceeds on the CPU, unwinding its way - * out of the interrupt call stack to the point where the interrupt driver code - * is ready to EOI and unmask the interrupt. The interrupt controller may be - * accessed via a faster bus than the hardware whose handler just ran; the write - * to unmask and EOI the interrupt may complete quickly while the device write - * to ack and clear the interrupt source is still lingering in a store buffer - * waiting for access to a slower bus. With the interrupt unmasked at the - * interrupt controller but still active at the device, as soon as interrupts - * are enabled on the core the device re-interrupts immediately: now you've got - * a spurious interrupt on your hands. - * - * The right way to fix this problem is for every device driver to use the - * proper bus_space_barrier() calls in its interrupt handler. For ARM a single - * barrier call at the end of the handler would work. This would have to be - * done to every driver in the system, not just arm-specific drivers. - * - * Another potential fix is to map all device memory as Strongly-Ordered rather - * than Device memory, which takes the store buffers out of the picture. This - * has a pretty big impact on overall system performance, because each strongly - * ordered memory access causes all L2 store buffers to be drained. - * - * A compromise solution is to have the interrupt controller implementation call - * this function to establish a barrier between writes to the interrupt-source - * device and writes to the interrupt controller device. - * - * This takes the interrupt number as an argument, and currently doesn't use it. - * The plan is that maybe some day there is a way to flag certain interrupts as - * "memory barrier safe" and we can avoid this overhead with them. - */ -void -arm_irq_memory_barrier(uintptr_t irq) -{ - - dsb(); - cpu_l2cache_drain_writebuf(); -} - Index: user/alc/PQ_LAUNDRY/sys/arm/arm/machdep_intr.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/arm/machdep_intr.c (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/arm/arm/machdep_intr.c (revision 292449) @@ -0,0 +1,123 @@ +/* $NetBSD: intr.c,v 1.12 2003/07/15 00:24:41 lukem Exp $ */ + +/*- + * Copyright (c) 2004 Olivier Houchard. + * Copyright (c) 1994-1998 Mark Brinicombe. + * 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 Mark Brinicombe + * for the NetBSD Project. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * 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 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. + * + * Soft interrupt and other generic interrupt functions. + */ + +#include "opt_platform.h" + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * arm_irq_memory_barrier() + * + * Ensure all writes to device memory have reached devices before proceeding. + * + * This is intended to be called from the post-filter and post-thread routines + * of an interrupt controller implementation. A peripheral device driver should + * use bus_space_barrier() if it needs to ensure a write has reached the + * hardware for some reason other than clearing interrupt conditions. + * + * The need for this function arises from the ARM weak memory ordering model. + * Writes to locations mapped with the Device attribute bypass any caches, but + * are buffered. Multiple writes to the same device will be observed by that + * device in the order issued by the cpu. Writes to different devices may + * appear at those devices in a different order than issued by the cpu. That + * is, if the cpu writes to device A then device B, the write to device B could + * complete before the write to device A. + * + * Consider a typical device interrupt handler which services the interrupt and + * writes to a device status-acknowledge register to clear the interrupt before + * returning. That write is posted to the L2 controller which "immediately" + * places it in a store buffer and automatically drains that buffer. This can + * be less immediate than you'd think... There may be no free slots in the store + * buffers, so an existing buffer has to be drained first to make room. The + * target bus may be busy with other traffic (such as DMA for various devices), + * delaying the drain of the store buffer for some indeterminate time. While + * all this delay is happening, execution proceeds on the CPU, unwinding its way + * out of the interrupt call stack to the point where the interrupt driver code + * is ready to EOI and unmask the interrupt. The interrupt controller may be + * accessed via a faster bus than the hardware whose handler just ran; the write + * to unmask and EOI the interrupt may complete quickly while the device write + * to ack and clear the interrupt source is still lingering in a store buffer + * waiting for access to a slower bus. With the interrupt unmasked at the + * interrupt controller but still active at the device, as soon as interrupts + * are enabled on the core the device re-interrupts immediately: now you've got + * a spurious interrupt on your hands. + * + * The right way to fix this problem is for every device driver to use the + * proper bus_space_barrier() calls in its interrupt handler. For ARM a single + * barrier call at the end of the handler would work. This would have to be + * done to every driver in the system, not just arm-specific drivers. + * + * Another potential fix is to map all device memory as Strongly-Ordered rather + * than Device memory, which takes the store buffers out of the picture. This + * has a pretty big impact on overall system performance, because each strongly + * ordered memory access causes all L2 store buffers to be drained. + * + * A compromise solution is to have the interrupt controller implementation call + * this function to establish a barrier between writes to the interrupt-source + * device and writes to the interrupt controller device. + * + * This takes the interrupt number as an argument, and currently doesn't use it. + * The plan is that maybe some day there is a way to flag certain interrupts as + * "memory barrier safe" and we can avoid this overhead with them. + */ +void +arm_irq_memory_barrier(uintptr_t irq) +{ + + dsb(); + cpu_l2cache_drain_writebuf(); +} + Property changes on: user/alc/PQ_LAUNDRY/sys/arm/arm/machdep_intr.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/arm/arm/mp_machdep.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/arm/mp_machdep.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/arm/mp_machdep.c (revision 292449) @@ -1,549 +1,549 @@ /*- * Copyright (c) 2011 Semihalf. * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef VFP #include #endif #ifdef CPU_MV_PJ4B #include #include #endif #include "opt_smp.h" extern struct pcpu __pcpu[]; /* used to hold the AP's until we are ready to release them */ struct mtx ap_boot_mtx; struct pcb stoppcbs[MAXCPU]; /* # of Applications processors */ volatile int mp_naps; /* Set to 1 once we're ready to let the APs out of the pen. */ volatile int aps_ready = 0; #ifndef ARM_INTRNG static int ipi_handler(void *arg); #endif void set_stackptrs(int cpu); /* Temporary variables for init_secondary() */ void *dpcpu[MAXCPU - 1]; /* Determine if we running MP machine */ int cpu_mp_probe(void) { CPU_SETOF(0, &all_cpus); return (platform_mp_probe()); } /* Start Application Processor via platform specific function */ static int check_ap(void) { uint32_t ms; for (ms = 0; ms < 2000; ++ms) { if ((mp_naps + 1) == mp_ncpus) return (0); /* success */ else DELAY(1000); } return (-2); } extern unsigned char _end[]; /* Initialize and fire up non-boot processors */ void cpu_mp_start(void) { int error, i; mtx_init(&ap_boot_mtx, "ap boot", NULL, MTX_SPIN); /* Reserve memory for application processors */ for(i = 0; i < (mp_ncpus - 1); i++) dpcpu[i] = (void *)kmem_malloc(kernel_arena, DPCPU_SIZE, M_WAITOK | M_ZERO); cpu_idcache_wbinv_all(); cpu_l2cache_wbinv_all(); cpu_idcache_wbinv_all(); /* Initialize boot code and start up processors */ platform_mp_start_ap(); /* Check if ap's started properly */ error = check_ap(); if (error) printf("WARNING: Some AP's failed to start\n"); else for (i = 1; i < mp_ncpus; i++) CPU_SET(i, &all_cpus); } /* Introduce rest of cores to the world */ void cpu_mp_announce(void) { } extern vm_paddr_t pmap_pa; void init_secondary(int cpu) { struct pcpu *pc; uint32_t loop_counter; #ifndef ARM_INTRNG int start = 0, end = 0; #endif #ifdef ARM_NEW_PMAP uint32_t actlr_mask, actlr_set; pmap_set_tex(); cpuinfo_get_actlr_modifier(&actlr_mask, &actlr_set); reinit_mmu(pmap_kern_ttb, actlr_mask, actlr_set); cpu_setup(); /* Provide stack pointers for other processor modes. */ set_stackptrs(cpu); enable_interrupts(PSR_A); #else /* ARM_NEW_PMAP */ cpu_setup(); setttb(pmap_pa); cpu_tlb_flushID(); #endif /* ARM_NEW_PMAP */ pc = &__pcpu[cpu]; /* * pcpu_init() updates queue, so it should not be executed in parallel * on several cores */ while(mp_naps < (cpu - 1)) ; pcpu_init(pc, cpu, sizeof(struct pcpu)); dpcpu_init(dpcpu[cpu - 1], cpu); #ifndef ARM_NEW_PMAP /* Provide stack pointers for other processor modes. */ set_stackptrs(cpu); #endif /* Signal our startup to BSP */ atomic_add_rel_32(&mp_naps, 1); /* Spin until the BSP releases the APs */ while (!atomic_load_acq_int(&aps_ready)) { #if __ARM_ARCH >= 7 __asm __volatile("wfe"); #endif } /* Initialize curthread */ KASSERT(PCPU_GET(idlethread) != NULL, ("no idle thread")); pc->pc_curthread = pc->pc_idlethread; pc->pc_curpcb = pc->pc_idlethread->td_pcb; set_curthread(pc->pc_idlethread); #ifdef VFP vfp_init(); #endif mtx_lock_spin(&ap_boot_mtx); atomic_add_rel_32(&smp_cpus, 1); if (smp_cpus == mp_ncpus) { /* enable IPI's, tlb shootdown, freezes etc */ atomic_store_rel_int(&smp_started, 1); } mtx_unlock_spin(&ap_boot_mtx); #ifndef ARM_INTRNG /* Enable ipi */ #ifdef IPI_IRQ_START start = IPI_IRQ_START; #ifdef IPI_IRQ_END end = IPI_IRQ_END; #else end = IPI_IRQ_START; #endif #endif for (int i = start; i <= end; i++) arm_unmask_irq(i); #endif /* INTRNG */ enable_interrupts(PSR_I); loop_counter = 0; while (smp_started == 0) { DELAY(100); loop_counter++; if (loop_counter == 1000) CTR0(KTR_SMP, "AP still wait for smp_started"); } /* Start per-CPU event timers. */ cpu_initclocks_ap(); CTR0(KTR_SMP, "go into scheduler"); platform_mp_init_secondary(); /* Enter the scheduler */ sched_throw(NULL); panic("scheduler returned us to %s", __func__); /* NOTREACHED */ } #ifdef ARM_INTRNG static void ipi_rendezvous(void *dummy __unused) { CTR0(KTR_SMP, "IPI_RENDEZVOUS"); smp_rendezvous_action(); } static void ipi_ast(void *dummy __unused) { CTR0(KTR_SMP, "IPI_AST"); } static void ipi_stop(void *dummy __unused) { u_int cpu; /* * IPI_STOP_HARD is mapped to IPI_STOP. */ CTR0(KTR_SMP, "IPI_STOP or IPI_STOP_HARD"); cpu = PCPU_GET(cpuid); savectx(&stoppcbs[cpu]); /* * CPUs are stopped when entering the debugger and at * system shutdown, both events which can precede a * panic dump. For the dump to be correct, all caches * must be flushed and invalidated, but on ARM there's * no way to broadcast a wbinv_all to other cores. * Instead, we have each core do the local wbinv_all as * part of stopping the core. The core requesting the * stop will do the l2 cache flush after all other cores * have done their l1 flushes and stopped. */ cpu_idcache_wbinv_all(); /* Indicate we are stopped */ CPU_SET_ATOMIC(cpu, &stopped_cpus); /* Wait for restart */ while (!CPU_ISSET(cpu, &started_cpus)) cpu_spinwait(); CPU_CLR_ATOMIC(cpu, &started_cpus); CPU_CLR_ATOMIC(cpu, &stopped_cpus); CTR0(KTR_SMP, "IPI_STOP (restart)"); } static void ipi_preempt(void *arg) { struct trapframe *oldframe; struct thread *td; critical_enter(); td = curthread; td->td_intr_nesting_level++; oldframe = td->td_intr_frame; td->td_intr_frame = (struct trapframe *)arg; CTR1(KTR_SMP, "%s: IPI_PREEMPT", __func__); sched_preempt(td); td->td_intr_frame = oldframe; td->td_intr_nesting_level--; critical_exit(); } static void ipi_hardclock(void *arg) { struct trapframe *oldframe; struct thread *td; critical_enter(); td = curthread; td->td_intr_nesting_level++; oldframe = td->td_intr_frame; td->td_intr_frame = (struct trapframe *)arg; CTR1(KTR_SMP, "%s: IPI_HARDCLOCK", __func__); hardclockintr(); td->td_intr_frame = oldframe; td->td_intr_nesting_level--; critical_exit(); } static void ipi_tlb(void *dummy __unused) { CTR1(KTR_SMP, "%s: IPI_TLB", __func__); cpufuncs.cf_tlb_flushID(); } #else static int ipi_handler(void *arg) { u_int cpu, ipi; cpu = PCPU_GET(cpuid); ipi = pic_ipi_read((int)arg); while ((ipi != 0x3ff)) { switch (ipi) { case IPI_RENDEZVOUS: CTR0(KTR_SMP, "IPI_RENDEZVOUS"); smp_rendezvous_action(); break; case IPI_AST: CTR0(KTR_SMP, "IPI_AST"); break; case IPI_STOP: /* * IPI_STOP_HARD is mapped to IPI_STOP so it is not * necessary to add it in the switch. */ CTR0(KTR_SMP, "IPI_STOP or IPI_STOP_HARD"); savectx(&stoppcbs[cpu]); /* * CPUs are stopped when entering the debugger and at * system shutdown, both events which can precede a * panic dump. For the dump to be correct, all caches * must be flushed and invalidated, but on ARM there's * no way to broadcast a wbinv_all to other cores. * Instead, we have each core do the local wbinv_all as * part of stopping the core. The core requesting the * stop will do the l2 cache flush after all other cores * have done their l1 flushes and stopped. */ cpu_idcache_wbinv_all(); /* Indicate we are stopped */ CPU_SET_ATOMIC(cpu, &stopped_cpus); /* Wait for restart */ while (!CPU_ISSET(cpu, &started_cpus)) cpu_spinwait(); CPU_CLR_ATOMIC(cpu, &started_cpus); CPU_CLR_ATOMIC(cpu, &stopped_cpus); CTR0(KTR_SMP, "IPI_STOP (restart)"); break; case IPI_PREEMPT: CTR1(KTR_SMP, "%s: IPI_PREEMPT", __func__); sched_preempt(curthread); break; case IPI_HARDCLOCK: CTR1(KTR_SMP, "%s: IPI_HARDCLOCK", __func__); hardclockintr(); break; case IPI_TLB: CTR1(KTR_SMP, "%s: IPI_TLB", __func__); cpufuncs.cf_tlb_flushID(); break; default: panic("Unknown IPI 0x%0x on cpu %d", ipi, curcpu); } pic_ipi_clear(ipi); ipi = pic_ipi_read(-1); } return (FILTER_HANDLED); } #endif static void release_aps(void *dummy __unused) { uint32_t loop_counter; #ifndef ARM_INTRNG int start = 0, end = 0; #endif if (mp_ncpus == 1) return; #ifdef ARM_INTRNG - arm_ipi_set_handler(IPI_RENDEZVOUS, "rendezvous", ipi_rendezvous, NULL, 0); - arm_ipi_set_handler(IPI_AST, "ast", ipi_ast, NULL, 0); - arm_ipi_set_handler(IPI_STOP, "stop", ipi_stop, NULL, 0); - arm_ipi_set_handler(IPI_PREEMPT, "preempt", ipi_preempt, NULL, 0); - arm_ipi_set_handler(IPI_HARDCLOCK, "hardclock", ipi_hardclock, NULL, 0); - arm_ipi_set_handler(IPI_TLB, "tlb", ipi_tlb, NULL, 0); + intr_ipi_set_handler(IPI_RENDEZVOUS, "rendezvous", ipi_rendezvous, NULL, 0); + intr_ipi_set_handler(IPI_AST, "ast", ipi_ast, NULL, 0); + intr_ipi_set_handler(IPI_STOP, "stop", ipi_stop, NULL, 0); + intr_ipi_set_handler(IPI_PREEMPT, "preempt", ipi_preempt, NULL, 0); + intr_ipi_set_handler(IPI_HARDCLOCK, "hardclock", ipi_hardclock, NULL, 0); + intr_ipi_set_handler(IPI_TLB, "tlb", ipi_tlb, NULL, 0); #else #ifdef IPI_IRQ_START start = IPI_IRQ_START; #ifdef IPI_IRQ_END end = IPI_IRQ_END; #else end = IPI_IRQ_START; #endif #endif for (int i = start; i <= end; i++) { /* * IPI handler */ /* * Use 0xdeadbeef as the argument value for irq 0, * if we used 0, the intr code will give the trap frame * pointer instead. */ arm_setup_irqhandler("ipi", ipi_handler, NULL, (void *)i, i, INTR_TYPE_MISC | INTR_EXCL, NULL); /* Enable ipi */ arm_unmask_irq(i); } #endif atomic_store_rel_int(&aps_ready, 1); /* Wake the other threads up */ #if __ARM_ARCH >= 7 armv7_sev(); #endif printf("Release APs\n"); for (loop_counter = 0; loop_counter < 2000; loop_counter++) { if (smp_started) return; DELAY(1000); } printf("AP's not started\n"); } SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, release_aps, NULL); struct cpu_group * cpu_topo(void) { return (smp_topo_1level(CG_SHARE_L2, mp_ncpus, 0)); } void cpu_mp_setmaxid(void) { platform_mp_setmaxid(); } /* Sending IPI */ void ipi_all_but_self(u_int ipi) { cpuset_t other_cpus; other_cpus = all_cpus; CPU_CLR(PCPU_GET(cpuid), &other_cpus); CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi); platform_ipi_send(other_cpus, ipi); } void ipi_cpu(int cpu, u_int ipi) { cpuset_t cpus; CPU_ZERO(&cpus); CPU_SET(cpu, &cpus); CTR3(KTR_SMP, "%s: cpu: %d, ipi: %x", __func__, cpu, ipi); platform_ipi_send(cpus, ipi); } void ipi_selected(cpuset_t cpus, u_int ipi) { CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi); platform_ipi_send(cpus, ipi); } void tlb_broadcast(int ipi) { if (smp_started) ipi_all_but_self(ipi); } Index: user/alc/PQ_LAUNDRY/sys/arm/arm/nexus.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/arm/nexus.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/arm/nexus.c (revision 292449) @@ -1,401 +1,401 @@ /*- * Copyright 1998 Massachusetts Institute of Technology * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that both the above copyright notice and this * permission notice appear in all copies, that both the above * copyright notice and this permission notice appear in all * supporting documentation, and that the name of M.I.T. not be used * in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. M.I.T. makes * no representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied * warranty. * * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT * SHALL M.I.T. 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 code implements a `root nexus' for Arm Architecture * machines. The function of the root nexus is to serve as an * attachment point for both processors and buses, and to manage * resources which are common to all of them. In particular, * this code implements the core resource managers for interrupt * requests, DMA requests (which rightfully should be a part of the * ISA code but it's easier to do it here for now), I/O port addresses, * and I/O memory address space. */ #include "opt_platform.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef FDT #include #include "ofw_bus_if.h" #endif static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device"); struct nexus_device { struct resource_list nx_resources; }; #define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev)) static struct rman mem_rman; static int nexus_probe(device_t); static int nexus_attach(device_t); static int nexus_print_child(device_t, device_t); static device_t nexus_add_child(device_t, u_int, const char *, int); static struct resource *nexus_alloc_resource(device_t, device_t, int, int *, u_long, u_long, u_long, u_int); static int nexus_activate_resource(device_t, device_t, int, int, struct resource *); #ifdef ARM_INTRNG #ifdef SMP static int nexus_bind_intr(device_t, device_t, struct resource *, int); #endif #endif static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, enum intr_polarity pol); #ifdef ARM_INTRNG static int nexus_describe_intr(device_t dev, device_t child, struct resource *irq, void *cookie, const char *descr); #endif static int nexus_deactivate_resource(device_t, device_t, int, int, struct resource *); static int nexus_release_resource(device_t, device_t, int, int, struct resource *); static int nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep); static int nexus_teardown_intr(device_t, device_t, struct resource *, void *); #ifdef FDT static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, pcell_t *intr); #endif static device_method_t nexus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, nexus_probe), DEVMETHOD(device_attach, nexus_attach), /* Bus interface */ DEVMETHOD(bus_print_child, nexus_print_child), DEVMETHOD(bus_add_child, nexus_add_child), DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), DEVMETHOD(bus_activate_resource, nexus_activate_resource), DEVMETHOD(bus_config_intr, nexus_config_intr), DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), DEVMETHOD(bus_release_resource, nexus_release_resource), DEVMETHOD(bus_setup_intr, nexus_setup_intr), DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), #ifdef ARM_INTRNG DEVMETHOD(bus_describe_intr, nexus_describe_intr), #ifdef SMP DEVMETHOD(bus_bind_intr, nexus_bind_intr), #endif #endif #ifdef FDT DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr), #endif { 0, 0 } }; static devclass_t nexus_devclass; static driver_t nexus_driver = { "nexus", nexus_methods, 1 /* no softc */ }; EARLY_DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_EARLY); static int nexus_probe(device_t dev) { device_quiet(dev); /* suppress attach message for neatness */ return (BUS_PROBE_DEFAULT); } static int nexus_attach(device_t dev) { mem_rman.rm_start = 0; mem_rman.rm_end = ~0ul; mem_rman.rm_type = RMAN_ARRAY; mem_rman.rm_descr = "I/O memory addresses"; if (rman_init(&mem_rman) || rman_manage_region(&mem_rman, 0, ~0)) panic("nexus_probe mem_rman"); /* * First, deal with the children we know about already */ bus_generic_probe(dev); bus_generic_attach(dev); return (0); } static int nexus_print_child(device_t bus, device_t child) { int retval = 0; retval += bus_print_child_header(bus, child); retval += printf("\n"); return (retval); } static device_t nexus_add_child(device_t bus, u_int order, const char *name, int unit) { device_t child; struct nexus_device *ndev; ndev = malloc(sizeof(struct nexus_device), M_NEXUSDEV, M_NOWAIT|M_ZERO); if (!ndev) return (0); resource_list_init(&ndev->nx_resources); child = device_add_child_ordered(bus, order, name, unit); /* should we free this in nexus_child_detached? */ device_set_ivars(child, ndev); return (child); } /* * Allocate a resource on behalf of child. NB: child is usually going to be a * child of one of our descendants, not a direct child of nexus0. * (Exceptions include footbridge.) */ static struct resource * nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct resource *rv; struct rman *rm; int needactivate = flags & RF_ACTIVE; flags &= ~RF_ACTIVE; switch (type) { case SYS_RES_MEMORY: case SYS_RES_IOPORT: rm = &mem_rman; break; default: return (NULL); } rv = rman_reserve_resource(rm, start, end, count, flags, child); if (rv == 0) return (NULL); rman_set_rid(rv, *rid); if (needactivate) { if (bus_activate_resource(child, type, *rid, rv)) { rman_release_resource(rv); return (0); } } return (rv); } static int nexus_release_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { int error; if (rman_get_flags(res) & RF_ACTIVE) { error = bus_deactivate_resource(child, type, rid, res); if (error) return (error); } return (rman_release_resource(res)); } static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, enum intr_polarity pol) { int ret = ENODEV; #ifdef ARM_INTRNG - ret = arm_irq_config(irq, trig, pol); + ret = intr_irq_config(irq, trig, pol); #else if (arm_config_irq) ret = (*arm_config_irq)(irq, trig, pol); #endif return (ret); } static int nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { int irq; if ((rman_get_flags(res) & RF_SHAREABLE) == 0) flags |= INTR_EXCL; for (irq = rman_get_start(res); irq <= rman_get_end(res); irq++) { #ifdef ARM_INTRNG - arm_irq_add_handler(child, filt, intr, arg, irq, flags, + intr_irq_add_handler(child, filt, intr, arg, irq, flags, cookiep); #else arm_setup_irqhandler(device_get_nameunit(child), filt, intr, arg, irq, flags, cookiep); arm_unmask_irq(irq); #endif } return (0); } static int nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) { #ifdef ARM_INTRNG - return (arm_irq_remove_handler(child, rman_get_start(r), ih)); + return (intr_irq_remove_handler(child, rman_get_start(r), ih)); #else return (arm_remove_irqhandler(rman_get_start(r), ih)); #endif } #ifdef ARM_INTRNG static int nexus_describe_intr(device_t dev, device_t child, struct resource *irq, void *cookie, const char *descr) { - return (arm_irq_describe(rman_get_start(irq), cookie, descr)); + return (intr_irq_describe(rman_get_start(irq), cookie, descr)); } #ifdef SMP static int nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu) { - return (arm_irq_bind(rman_get_start(irq), cpu)); + return (intr_irq_bind(rman_get_start(irq), cpu)); } #endif #endif static int nexus_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { int err; bus_addr_t paddr; bus_size_t psize; bus_space_handle_t vaddr; if ((err = rman_activate_resource(r)) != 0) return (err); /* * If this is a memory resource, map it into the kernel. */ if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { paddr = (bus_addr_t)rman_get_start(r); psize = (bus_size_t)rman_get_size(r); #ifdef FDT err = bus_space_map(fdtbus_bs_tag, paddr, psize, 0, &vaddr); if (err != 0) { rman_deactivate_resource(r); return (err); } rman_set_bustag(r, fdtbus_bs_tag); #else vaddr = (bus_space_handle_t)pmap_mapdev((vm_offset_t)paddr, (vm_size_t)psize); if (vaddr == 0) { rman_deactivate_resource(r); return (ENOMEM); } rman_set_bustag(r, (void *)1); #endif rman_set_virtual(r, (void *)vaddr); rman_set_bushandle(r, vaddr); } return (0); } static int nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { bus_size_t psize; bus_space_handle_t vaddr; psize = (bus_size_t)rman_get_size(r); vaddr = rman_get_bushandle(r); if (vaddr != 0) { #ifdef FDT bus_space_unmap(fdtbus_bs_tag, vaddr, psize); #else pmap_unmapdev((vm_offset_t)vaddr, (vm_size_t)psize); #endif rman_set_virtual(r, NULL); rman_set_bushandle(r, 0); } return (rman_deactivate_resource(r)); } #ifdef FDT static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, pcell_t *intr) { - return (arm_fdt_map_irq(iparent, intr, icells)); + return (intr_fdt_map_irq(iparent, intr, icells)); } #endif Index: user/alc/PQ_LAUNDRY/sys/arm/freescale/imx/imx6_mp.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/freescale/imx/imx6_mp.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/freescale/imx/imx6_mp.c (revision 292449) @@ -1,181 +1,181 @@ /*- * Copyright (c) 2014 Juergen Weiss * Copyright (c) 2014 Ian Lepore * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #define SCU_PHYSBASE 0x00a00000 #define SCU_SIZE 0x00001000 #define SCU_CONTROL_REG 0x00 #define SCU_CONTROL_ENABLE (1 << 0) #define SCU_CONFIG_REG 0x04 #define SCU_CONFIG_REG_NCPU_MASK 0x03 #define SCU_CPUPOWER_REG 0x08 #define SCU_INV_TAGS_REG 0x0c #define SCU_DIAG_CONTROL 0x30 #define SCU_DIAG_DISABLE_MIGBIT (1 << 0) #define SCU_FILTER_START_REG 0x40 #define SCU_FILTER_END_REG 0x44 #define SCU_SECURE_ACCESS_REG 0x50 #define SCU_NONSECURE_ACCESS_REG 0x54 #define SRC_PHYSBASE 0x020d8000 #define SRC_SIZE 0x4000 #define SRC_CONTROL_REG 0x00 #define SRC_CONTROL_C1ENA_SHIFT 22 /* Bit for Core 1 enable */ #define SRC_CONTROL_C1RST_SHIFT 14 /* Bit for Core 1 reset */ #define SRC_GPR0_C1FUNC 0x20 /* Register for Core 1 entry func */ #define SRC_GPR1_C1ARG 0x24 /* Register for Core 1 entry arg */ void platform_mp_init_secondary(void) { - arm_pic_init_secondary(); + intr_pic_init_secondary(); } void platform_mp_setmaxid(void) { bus_space_handle_t scu; int hwcpu, ncpu; uint32_t val; /* If we've already set the global vars don't bother to do it again. */ if (mp_ncpus != 0) return; if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0) panic("Couldn't map the SCU\n"); val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONFIG_REG); hwcpu = (val & SCU_CONFIG_REG_NCPU_MASK) + 1; bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE); ncpu = hwcpu; TUNABLE_INT_FETCH("hw.ncpu", &ncpu); if (ncpu < 1 || ncpu > hwcpu) ncpu = hwcpu; mp_ncpus = ncpu; mp_maxid = ncpu - 1; } int platform_mp_probe(void) { /* I think platform_mp_setmaxid must get called first, but be safe. */ if (mp_ncpus == 0) platform_mp_setmaxid(); return (mp_ncpus > 1); } void platform_mp_start_ap(void) { bus_space_handle_t scu; bus_space_handle_t src; uint32_t val; int i; if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0) panic("Couldn't map the SCU\n"); if (bus_space_map(fdtbus_bs_tag, SRC_PHYSBASE, SRC_SIZE, 0, &src) != 0) panic("Couldn't map the system reset controller (SRC)\n"); /* * Invalidate SCU cache tags. The 0x0000ffff constant invalidates all * ways on all cores 0-3. Per the ARM docs, it's harmless to write to * the bits for cores that are not present. */ bus_space_write_4(fdtbus_bs_tag, scu, SCU_INV_TAGS_REG, 0x0000ffff); /* * Erratum ARM/MP: 764369 (problems with cache maintenance). * Setting the "disable-migratory bit" in the undocumented SCU * Diagnostic Control Register helps work around the problem. */ val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_DIAG_CONTROL); bus_space_write_4(fdtbus_bs_tag, scu, SCU_DIAG_CONTROL, val | SCU_DIAG_DISABLE_MIGBIT); /* * Enable the SCU, then clean the cache on this core. After these two * operations the cache tag ram in the SCU is coherent with the contents * of the cache on this core. The other cores aren't running yet so * their caches can't contain valid data yet, but we've initialized * their SCU tag ram above, so they will be coherent from startup. */ val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG); bus_space_write_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG, val | SCU_CONTROL_ENABLE); cpu_idcache_wbinv_all(); /* * For each AP core, set the entry point address and argument registers, * and set the core-enable and core-reset bits in the control register. */ val = bus_space_read_4(fdtbus_bs_tag, src, SRC_CONTROL_REG); for (i=1; i < mp_ncpus; i++) { bus_space_write_4(fdtbus_bs_tag, src, SRC_GPR0_C1FUNC + 8*i, pmap_kextract((vm_offset_t)mpentry)); bus_space_write_4(fdtbus_bs_tag, src, SRC_GPR1_C1ARG + 8*i, 0); val |= ((1 << (SRC_CONTROL_C1ENA_SHIFT - 1 + i )) | ( 1 << (SRC_CONTROL_C1RST_SHIFT - 1 + i))); } bus_space_write_4(fdtbus_bs_tag, src, SRC_CONTROL_REG, val); armv7_sev(); bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE); bus_space_unmap(fdtbus_bs_tag, src, SRC_SIZE); } void platform_ipi_send(cpuset_t cpus, u_int ipi) { pic_ipi_send(cpus, ipi); } Index: user/alc/PQ_LAUNDRY/sys/arm/freescale/imx/imx_gpio.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/freescale/imx/imx_gpio.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/freescale/imx/imx_gpio.c (revision 292449) @@ -1,729 +1,729 @@ /*- * Copyright (c) 2012, 2013 The FreeBSD Foundation * All rights reserved. * * This software was developed by Oleksandr Rybalko under sponsorship * from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Freescale i.MX515 GPIO driver. */ #include __FBSDID("$FreeBSD$"); #include "opt_platform.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gpio_if.h" #ifdef ARM_INTRNG #include "pic_if.h" #endif #define WRITE4(_sc, _r, _v) \ bus_space_write_4((_sc)->sc_iot, (_sc)->sc_ioh, (_r), (_v)) #define READ4(_sc, _r) \ bus_space_read_4((_sc)->sc_iot, (_sc)->sc_ioh, (_r)) #define SET4(_sc, _r, _m) \ WRITE4((_sc), (_r), READ4((_sc), (_r)) | (_m)) #define CLEAR4(_sc, _r, _m) \ WRITE4((_sc), (_r), READ4((_sc), (_r)) & ~(_m)) /* Registers definition for Freescale i.MX515 GPIO controller */ #define IMX_GPIO_DR_REG 0x000 /* Pin Data */ #define IMX_GPIO_OE_REG 0x004 /* Set Pin Output */ #define IMX_GPIO_PSR_REG 0x008 /* Pad Status */ #define IMX_GPIO_ICR1_REG 0x00C /* Interrupt Configuration */ #define IMX_GPIO_ICR2_REG 0x010 /* Interrupt Configuration */ #define GPIO_ICR_COND_LOW 0 #define GPIO_ICR_COND_HIGH 1 #define GPIO_ICR_COND_RISE 2 #define GPIO_ICR_COND_FALL 3 #define IMX_GPIO_IMR_REG 0x014 /* Interrupt Mask Register */ #define IMX_GPIO_ISR_REG 0x018 /* Interrupt Status Register */ #define IMX_GPIO_EDGE_REG 0x01C /* Edge Detect Register */ #define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT) #define NGPIO 32 struct imx51_gpio_softc { device_t dev; device_t sc_busdev; struct mtx sc_mtx; struct resource *sc_res[3]; /* 1 x mem, 2 x IRQ */ void *gpio_ih[2]; bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; int gpio_npins; struct gpio_pin gpio_pins[NGPIO]; - struct arm_irqsrc *gpio_pic_irqsrc[NGPIO]; + struct intr_irqsrc *gpio_pic_irqsrc[NGPIO]; }; static struct ofw_compat_data compat_data[] = { {"fsl,imx6q-gpio", 1}, {"fsl,imx53-gpio", 1}, {"fsl,imx51-gpio", 1}, {NULL, 0} }; static struct resource_spec imx_gpio_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, { SYS_RES_IRQ, 0, RF_ACTIVE }, { SYS_RES_IRQ, 1, RF_ACTIVE }, { -1, 0 } }; /* * Helpers */ static void imx51_gpio_pin_configure(struct imx51_gpio_softc *, struct gpio_pin *, uint32_t); /* * Driver stuff */ static int imx51_gpio_probe(device_t); static int imx51_gpio_attach(device_t); static int imx51_gpio_detach(device_t); /* * GPIO interface */ static device_t imx51_gpio_get_bus(device_t); static int imx51_gpio_pin_max(device_t, int *); static int imx51_gpio_pin_getcaps(device_t, uint32_t, uint32_t *); static int imx51_gpio_pin_getflags(device_t, uint32_t, uint32_t *); static int imx51_gpio_pin_getname(device_t, uint32_t, char *); static int imx51_gpio_pin_setflags(device_t, uint32_t, uint32_t); static int imx51_gpio_pin_set(device_t, uint32_t, unsigned int); static int imx51_gpio_pin_get(device_t, uint32_t, unsigned int *); static int imx51_gpio_pin_toggle(device_t, uint32_t pin); #ifdef ARM_INTRNG /* * this is teardown_intr */ static void -gpio_pic_disable_intr(device_t dev, struct arm_irqsrc *isrc) +gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc) { struct imx51_gpio_softc *sc; u_int irq; sc = device_get_softc(dev); irq = isrc->isrc_data; // XXX Not sure this is necessary mtx_lock_spin(&sc->sc_mtx); CLEAR4(sc, IMX_GPIO_IMR_REG, (1U << irq)); WRITE4(sc, IMX_GPIO_ISR_REG, (1U << irq)); mtx_unlock_spin(&sc->sc_mtx); } /* * this is mask_intr */ static void -gpio_pic_disable_source(device_t dev, struct arm_irqsrc *isrc) +gpio_pic_disable_source(device_t dev, struct intr_irqsrc *isrc) { struct imx51_gpio_softc *sc; sc = device_get_softc(dev); mtx_lock_spin(&sc->sc_mtx); CLEAR4(sc, IMX_GPIO_IMR_REG, (1U << isrc->isrc_data)); mtx_unlock_spin(&sc->sc_mtx); } /* * this is setup_intr */ static void -gpio_pic_enable_intr(device_t dev, struct arm_irqsrc *isrc) +gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc) { struct imx51_gpio_softc *sc; int icfg; u_int irq, reg, shift, wrk; sc = device_get_softc(dev); if (isrc->isrc_trig == INTR_TRIGGER_LEVEL) { if (isrc->isrc_pol == INTR_POLARITY_LOW) icfg = GPIO_ICR_COND_LOW; else icfg = GPIO_ICR_COND_HIGH; } else { if (isrc->isrc_pol == INTR_POLARITY_HIGH) icfg = GPIO_ICR_COND_FALL; else icfg = GPIO_ICR_COND_RISE; } irq = isrc->isrc_data; if (irq < 16) { reg = IMX_GPIO_ICR1_REG; shift = 2 * irq; } else { reg = IMX_GPIO_ICR2_REG; shift = 2 * (irq - 16); } mtx_lock_spin(&sc->sc_mtx); CLEAR4(sc, IMX_GPIO_IMR_REG, (1U << irq)); WRITE4(sc, IMX_GPIO_ISR_REG, (1U << irq)); wrk = READ4(sc, reg); wrk &= ~(0x03 << shift); wrk |= icfg << shift; WRITE4(sc, reg, wrk); mtx_unlock_spin(&sc->sc_mtx); } /* * this is unmask_intr */ static void -gpio_pic_enable_source(device_t dev, struct arm_irqsrc *isrc) +gpio_pic_enable_source(device_t dev, struct intr_irqsrc *isrc) { struct imx51_gpio_softc *sc; sc = device_get_softc(dev); mtx_lock_spin(&sc->sc_mtx); SET4(sc, IMX_GPIO_IMR_REG, (1U << isrc->isrc_data)); mtx_unlock_spin(&sc->sc_mtx); } static void -gpio_pic_post_filter(device_t dev, struct arm_irqsrc *isrc) +gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc) { struct imx51_gpio_softc *sc; sc = device_get_softc(dev); arm_irq_memory_barrier(0); /* EOI. W1C reg so no r-m-w, no locking needed. */ WRITE4(sc, IMX_GPIO_ISR_REG, (1U << isrc->isrc_data)); } static void -gpio_pic_post_ithread(device_t dev, struct arm_irqsrc *isrc) +gpio_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc) { arm_irq_memory_barrier(0); gpio_pic_enable_source(dev, isrc); } static void -gpio_pic_pre_ithread(device_t dev, struct arm_irqsrc *isrc) +gpio_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc) { gpio_pic_disable_source(dev, isrc); } /* * intrng calls this to make a new isrc known to us. */ static int -gpio_pic_register(device_t dev, struct arm_irqsrc *isrc, boolean_t *is_percpu) +gpio_pic_register(device_t dev, struct intr_irqsrc *isrc, boolean_t *is_percpu) { struct imx51_gpio_softc *sc; u_int irq, tripol; sc = device_get_softc(dev); /* * From devicetree/bindings/gpio/fsl-imx-gpio.txt: * #interrupt-cells: 2. The first cell is the GPIO number. The second * cell bits[3:0] is used to specify trigger type and level flags: * 1 = low-to-high edge triggered. * 2 = high-to-low edge triggered. * 4 = active high level-sensitive. * 8 = active low level-sensitive. * We can do any single one of these modes, but nothing in combo. */ if (isrc->isrc_ncells != 2) { device_printf(sc->dev, "Invalid #interrupt-cells"); return (EINVAL); } irq = isrc->isrc_cells[0]; tripol = isrc->isrc_cells[1]; if (irq >= sc->gpio_npins) { device_printf(sc->dev, "Invalid interrupt number %d", irq); return (EINVAL); } switch (tripol) { case 1: isrc->isrc_trig = INTR_TRIGGER_EDGE; isrc->isrc_pol = INTR_POLARITY_HIGH; break; case 2: isrc->isrc_trig = INTR_TRIGGER_EDGE; isrc->isrc_pol = INTR_POLARITY_LOW; break; case 4: isrc->isrc_trig = INTR_TRIGGER_LEVEL; isrc->isrc_pol = INTR_POLARITY_HIGH; break; case 8: isrc->isrc_trig = INTR_TRIGGER_LEVEL; isrc->isrc_pol = INTR_POLARITY_LOW; break; default: device_printf(sc->dev, "unsupported trigger/polarity 0x%2x\n", tripol); return (ENOTSUP); } - isrc->isrc_nspc_type = ARM_IRQ_NSPC_PLAIN; + isrc->isrc_nspc_type = INTR_IRQ_NSPC_PLAIN; isrc->isrc_nspc_num = irq; /* * 1. The link between ISRC and controller must be set atomically. * 2. Just do things only once in rare case when consumers * of shared interrupt came here at the same moment. */ mtx_lock_spin(&sc->sc_mtx); if (sc->gpio_pic_irqsrc[irq] != NULL) { mtx_unlock_spin(&sc->sc_mtx); return (sc->gpio_pic_irqsrc[irq] == isrc ? 0 : EEXIST); } sc->gpio_pic_irqsrc[irq] = isrc; isrc->isrc_data = irq; mtx_unlock_spin(&sc->sc_mtx); - arm_irq_set_name(isrc, "%s,%u", device_get_nameunit(sc->dev), irq); + intr_irq_set_name(isrc, "%s,%u", device_get_nameunit(sc->dev), irq); return (0); } static int -gpio_pic_unregister(device_t dev, struct arm_irqsrc *isrc) +gpio_pic_unregister(device_t dev, struct intr_irqsrc *isrc) { struct imx51_gpio_softc *sc; u_int irq; sc = device_get_softc(dev); mtx_lock_spin(&sc->sc_mtx); irq = isrc->isrc_data; if (sc->gpio_pic_irqsrc[irq] != isrc) { mtx_unlock_spin(&sc->sc_mtx); return (sc->gpio_pic_irqsrc[irq] == NULL ? 0 : EINVAL); } sc->gpio_pic_irqsrc[irq] = NULL; isrc->isrc_data = 0; mtx_unlock_spin(&sc->sc_mtx); - arm_irq_set_name(isrc, ""); + intr_irq_set_name(isrc, ""); return (0); } static int gpio_pic_filter(void *arg) { struct imx51_gpio_softc *sc; uint32_t i, interrupts; sc = arg; mtx_lock_spin(&sc->sc_mtx); interrupts = READ4(sc, IMX_GPIO_ISR_REG) & READ4(sc, IMX_GPIO_IMR_REG); mtx_unlock_spin(&sc->sc_mtx); for (i = 0; interrupts != 0; i++, interrupts >>= 1) { if ((interrupts & 0x1) == 0) continue; if (sc->gpio_pic_irqsrc[i]) - arm_irq_dispatch(sc->gpio_pic_irqsrc[i], curthread->td_intr_frame); + intr_irq_dispatch(sc->gpio_pic_irqsrc[i], curthread->td_intr_frame); else device_printf(sc->dev, "spurious interrupt %d\n", i); } return (FILTER_HANDLED); } #endif /* * */ static void imx51_gpio_pin_configure(struct imx51_gpio_softc *sc, struct gpio_pin *pin, unsigned int flags) { mtx_lock_spin(&sc->sc_mtx); /* * Manage input/output */ if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) { pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT); if (flags & GPIO_PIN_OUTPUT) { pin->gp_flags |= GPIO_PIN_OUTPUT; SET4(sc, IMX_GPIO_OE_REG, (1U << pin->gp_pin)); } else { pin->gp_flags |= GPIO_PIN_INPUT; CLEAR4(sc, IMX_GPIO_OE_REG, (1U << pin->gp_pin)); } } mtx_unlock_spin(&sc->sc_mtx); } static device_t imx51_gpio_get_bus(device_t dev) { struct imx51_gpio_softc *sc; sc = device_get_softc(dev); return (sc->sc_busdev); } static int imx51_gpio_pin_max(device_t dev, int *maxpin) { struct imx51_gpio_softc *sc; sc = device_get_softc(dev); *maxpin = sc->gpio_npins - 1; return (0); } static int imx51_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) { struct imx51_gpio_softc *sc; int i; sc = device_get_softc(dev); for (i = 0; i < sc->gpio_npins; i++) { if (sc->gpio_pins[i].gp_pin == pin) break; } if (i >= sc->gpio_npins) return (EINVAL); mtx_lock_spin(&sc->sc_mtx); *caps = sc->gpio_pins[i].gp_caps; mtx_unlock_spin(&sc->sc_mtx); return (0); } static int imx51_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) { struct imx51_gpio_softc *sc; int i; sc = device_get_softc(dev); for (i = 0; i < sc->gpio_npins; i++) { if (sc->gpio_pins[i].gp_pin == pin) break; } if (i >= sc->gpio_npins) return (EINVAL); mtx_lock_spin(&sc->sc_mtx); *flags = sc->gpio_pins[i].gp_flags; mtx_unlock_spin(&sc->sc_mtx); return (0); } static int imx51_gpio_pin_getname(device_t dev, uint32_t pin, char *name) { struct imx51_gpio_softc *sc; int i; sc = device_get_softc(dev); for (i = 0; i < sc->gpio_npins; i++) { if (sc->gpio_pins[i].gp_pin == pin) break; } if (i >= sc->gpio_npins) return (EINVAL); mtx_lock_spin(&sc->sc_mtx); memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME); mtx_unlock_spin(&sc->sc_mtx); return (0); } static int imx51_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) { struct imx51_gpio_softc *sc; int i; sc = device_get_softc(dev); for (i = 0; i < sc->gpio_npins; i++) { if (sc->gpio_pins[i].gp_pin == pin) break; } if (i >= sc->gpio_npins) return (EINVAL); imx51_gpio_pin_configure(sc, &sc->gpio_pins[i], flags); return (0); } static int imx51_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) { struct imx51_gpio_softc *sc; int i; sc = device_get_softc(dev); for (i = 0; i < sc->gpio_npins; i++) { if (sc->gpio_pins[i].gp_pin == pin) break; } if (i >= sc->gpio_npins) return (EINVAL); mtx_lock_spin(&sc->sc_mtx); if (value) SET4(sc, IMX_GPIO_DR_REG, (1U << i)); else CLEAR4(sc, IMX_GPIO_DR_REG, (1U << i)); mtx_unlock_spin(&sc->sc_mtx); return (0); } static int imx51_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) { struct imx51_gpio_softc *sc; int i; sc = device_get_softc(dev); for (i = 0; i < sc->gpio_npins; i++) { if (sc->gpio_pins[i].gp_pin == pin) break; } if (i >= sc->gpio_npins) return (EINVAL); mtx_lock_spin(&sc->sc_mtx); *val = (READ4(sc, IMX_GPIO_DR_REG) >> i) & 1; mtx_unlock_spin(&sc->sc_mtx); return (0); } static int imx51_gpio_pin_toggle(device_t dev, uint32_t pin) { struct imx51_gpio_softc *sc; int i; sc = device_get_softc(dev); for (i = 0; i < sc->gpio_npins; i++) { if (sc->gpio_pins[i].gp_pin == pin) break; } if (i >= sc->gpio_npins) return (EINVAL); mtx_lock_spin(&sc->sc_mtx); WRITE4(sc, IMX_GPIO_DR_REG, (READ4(sc, IMX_GPIO_DR_REG) ^ (1U << i))); mtx_unlock_spin(&sc->sc_mtx); return (0); } static int imx51_gpio_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) { device_set_desc(dev, "Freescale i.MX GPIO Controller"); return (BUS_PROBE_DEFAULT); } return (ENXIO); } static int imx51_gpio_attach(device_t dev) { struct imx51_gpio_softc *sc; int i, irq, unit; sc = device_get_softc(dev); sc->dev = dev; sc->gpio_npins = NGPIO; mtx_init(&sc->sc_mtx, device_get_nameunit(sc->dev), NULL, MTX_SPIN); if (bus_alloc_resources(dev, imx_gpio_spec, sc->sc_res)) { device_printf(dev, "could not allocate resources\n"); bus_release_resources(dev, imx_gpio_spec, sc->sc_res); mtx_destroy(&sc->sc_mtx); return (ENXIO); } sc->sc_iot = rman_get_bustag(sc->sc_res[0]); sc->sc_ioh = rman_get_bushandle(sc->sc_res[0]); /* * Mask off all interrupts in hardware, then set up interrupt handling. */ WRITE4(sc, IMX_GPIO_IMR_REG, 0); for (irq = 0; irq < 2; irq++) { #ifdef ARM_INTRNG if ((bus_setup_intr(dev, sc->sc_res[1 + irq], INTR_TYPE_CLK, gpio_pic_filter, NULL, sc, &sc->gpio_ih[irq]))) { device_printf(dev, "WARNING: unable to register interrupt handler\n"); imx51_gpio_detach(dev); return (ENXIO); } #endif } unit = device_get_unit(dev); for (i = 0; i < sc->gpio_npins; i++) { sc->gpio_pins[i].gp_pin = i; sc->gpio_pins[i].gp_caps = DEFAULT_CAPS; sc->gpio_pins[i].gp_flags = (READ4(sc, IMX_GPIO_OE_REG) & (1U << i)) ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT; snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME, "imx_gpio%d.%d", unit, i); } #ifdef ARM_INTRNG - arm_pic_register(dev, OF_xref_from_node(ofw_bus_get_node(dev))); + intr_pic_register(dev, OF_xref_from_node(ofw_bus_get_node(dev))); #endif sc->sc_busdev = gpiobus_attach_bus(dev); if (sc->sc_busdev == NULL) { imx51_gpio_detach(dev); return (ENXIO); } return (0); } static int imx51_gpio_detach(device_t dev) { int irq; struct imx51_gpio_softc *sc; sc = device_get_softc(dev); gpiobus_detach_bus(dev); for (irq = 1; irq <= 2; irq++) { if (sc->gpio_ih[irq]) bus_teardown_intr(dev, sc->sc_res[irq], sc->gpio_ih[irq]); } bus_release_resources(dev, imx_gpio_spec, sc->sc_res); mtx_destroy(&sc->sc_mtx); return(0); } static device_method_t imx51_gpio_methods[] = { DEVMETHOD(device_probe, imx51_gpio_probe), DEVMETHOD(device_attach, imx51_gpio_attach), DEVMETHOD(device_detach, imx51_gpio_detach), #ifdef ARM_INTRNG /* Interrupt controller interface */ DEVMETHOD(pic_disable_intr, gpio_pic_disable_intr), DEVMETHOD(pic_disable_source, gpio_pic_disable_source), DEVMETHOD(pic_enable_intr, gpio_pic_enable_intr), DEVMETHOD(pic_enable_source, gpio_pic_enable_source), DEVMETHOD(pic_post_filter, gpio_pic_post_filter), DEVMETHOD(pic_post_ithread, gpio_pic_post_ithread), DEVMETHOD(pic_pre_ithread, gpio_pic_pre_ithread), DEVMETHOD(pic_register, gpio_pic_register), DEVMETHOD(pic_unregister, gpio_pic_unregister), #endif /* GPIO protocol */ DEVMETHOD(gpio_get_bus, imx51_gpio_get_bus), DEVMETHOD(gpio_pin_max, imx51_gpio_pin_max), DEVMETHOD(gpio_pin_getname, imx51_gpio_pin_getname), DEVMETHOD(gpio_pin_getflags, imx51_gpio_pin_getflags), DEVMETHOD(gpio_pin_getcaps, imx51_gpio_pin_getcaps), DEVMETHOD(gpio_pin_setflags, imx51_gpio_pin_setflags), DEVMETHOD(gpio_pin_get, imx51_gpio_pin_get), DEVMETHOD(gpio_pin_set, imx51_gpio_pin_set), DEVMETHOD(gpio_pin_toggle, imx51_gpio_pin_toggle), {0, 0}, }; static driver_t imx51_gpio_driver = { "gpio", imx51_gpio_methods, sizeof(struct imx51_gpio_softc), }; static devclass_t imx51_gpio_devclass; DRIVER_MODULE(imx51_gpio, simplebus, imx51_gpio_driver, imx51_gpio_devclass, 0, 0); Index: user/alc/PQ_LAUNDRY/sys/arm/freescale/imx/imx_sdhci.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/freescale/imx/imx_sdhci.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/freescale/imx/imx_sdhci.c (revision 292449) @@ -1,830 +1,837 @@ /*- * Copyright (c) 2013 Ian Lepore * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); /* * SDHCI driver glue for Freescale i.MX SoC family. * * This supports both eSDHC (earlier SoCs) and uSDHC (more recent SoCs). */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sdhci_if.h" struct imx_sdhci_softc { device_t dev; struct resource * mem_res; struct resource * irq_res; void * intr_cookie; struct sdhci_slot slot; struct callout r1bfix_callout; sbintime_t r1bfix_timeout_at; uint32_t baseclk_hz; uint32_t sdclockreg_freq_bits; uint32_t cmd_and_mode; uint32_t r1bfix_intmask; uint8_t r1bfix_type; uint8_t hwtype; boolean_t force_card_present; }; #define R1BFIX_NONE 0 /* No fix needed at next interrupt. */ #define R1BFIX_NODATA 1 /* Synthesize DATA_END for R1B w/o data. */ #define R1BFIX_AC12 2 /* Wait for busy after auto command 12. */ #define HWTYPE_NONE 0 /* Hardware not recognized/supported. */ #define HWTYPE_ESDHC 1 /* imx5x and earlier. */ #define HWTYPE_USDHC 2 /* imx6. */ #define SDHC_WTMK_LVL 0x44 /* Watermark Level register. */ #define USDHC_MIX_CONTROL 0x48 /* Mix(ed) Control register. */ #define SDHC_VEND_SPEC 0xC0 /* Vendor-specific register. */ #define SDHC_VEND_FRC_SDCLK_ON (1 << 8) #define SDHC_VEND_IPGEN (1 << 11) #define SDHC_VEND_HCKEN (1 << 12) #define SDHC_VEND_PEREN (1 << 13) #define SDHC_PRES_STATE 0x24 #define SDHC_PRES_CIHB (1 << 0) #define SDHC_PRES_CDIHB (1 << 1) #define SDHC_PRES_DLA (1 << 2) #define SDHC_PRES_SDSTB (1 << 3) #define SDHC_PRES_IPGOFF (1 << 4) #define SDHC_PRES_HCKOFF (1 << 5) #define SDHC_PRES_PEROFF (1 << 6) #define SDHC_PRES_SDOFF (1 << 7) #define SDHC_PRES_WTA (1 << 8) #define SDHC_PRES_RTA (1 << 9) #define SDHC_PRES_BWEN (1 << 10) #define SDHC_PRES_BREN (1 << 11) #define SDHC_PRES_RTR (1 << 12) #define SDHC_PRES_CINST (1 << 16) #define SDHC_PRES_CDPL (1 << 18) #define SDHC_PRES_WPSPL (1 << 19) #define SDHC_PRES_CLSL (1 << 23) #define SDHC_PRES_DLSL_SHIFT 24 #define SDHC_PRES_DLSL_MASK (0xffU << SDHC_PRES_DLSL_SHIFT) #define SDHC_PROT_CTRL 0x28 #define SDHC_PROT_LED (1 << 0) #define SDHC_PROT_WIDTH_1BIT (0 << 1) #define SDHC_PROT_WIDTH_4BIT (1 << 1) #define SDHC_PROT_WIDTH_8BIT (2 << 1) #define SDHC_PROT_WIDTH_MASK (3 << 1) #define SDHC_PROT_D3CD (1 << 3) #define SDHC_PROT_EMODE_BIG (0 << 4) #define SDHC_PROT_EMODE_HALF (1 << 4) #define SDHC_PROT_EMODE_LITTLE (2 << 4) #define SDHC_PROT_EMODE_MASK (3 << 4) #define SDHC_PROT_SDMA (0 << 8) #define SDHC_PROT_ADMA1 (1 << 8) #define SDHC_PROT_ADMA2 (2 << 8) #define SDHC_PROT_ADMA264 (3 << 8) #define SDHC_PROT_DMA_MASK (3 << 8) #define SDHC_PROT_CDTL (1 << 6) #define SDHC_PROT_CDSS (1 << 7) #define SDHC_INT_STATUS 0x30 #define SDHC_CLK_IPGEN (1 << 0) #define SDHC_CLK_HCKEN (1 << 1) #define SDHC_CLK_PEREN (1 << 2) #define SDHC_CLK_DIVISOR_MASK 0x000000f0 #define SDHC_CLK_DIVISOR_SHIFT 4 #define SDHC_CLK_PRESCALE_MASK 0x0000ff00 #define SDHC_CLK_PRESCALE_SHIFT 8 static struct ofw_compat_data compat_data[] = { {"fsl,imx6q-usdhc", HWTYPE_USDHC}, {"fsl,imx6sl-usdhc", HWTYPE_USDHC}, {"fsl,imx53-esdhc", HWTYPE_ESDHC}, {"fsl,imx51-esdhc", HWTYPE_ESDHC}, {NULL, HWTYPE_NONE}, }; static void imx_sdhc_set_clock(struct imx_sdhci_softc *sc, int enable); static void imx_sdhci_r1bfix_func(void *arg); static inline uint32_t RD4(struct imx_sdhci_softc *sc, bus_size_t off) { return (bus_read_4(sc->mem_res, off)); } static inline void WR4(struct imx_sdhci_softc *sc, bus_size_t off, uint32_t val) { bus_write_4(sc->mem_res, off, val); } static uint8_t imx_sdhci_read_1(device_t dev, struct sdhci_slot *slot, bus_size_t off) { struct imx_sdhci_softc *sc = device_get_softc(dev); uint32_t val32, wrk32; /* * Most of the things in the standard host control register are in the * hardware's wider protocol control register, but some of the bits are * moved around. */ if (off == SDHCI_HOST_CONTROL) { wrk32 = RD4(sc, SDHC_PROT_CTRL); val32 = wrk32 & (SDHCI_CTRL_LED | SDHCI_CTRL_CARD_DET | SDHCI_CTRL_FORCE_CARD); switch (wrk32 & SDHC_PROT_WIDTH_MASK) { case SDHC_PROT_WIDTH_1BIT: /* Value is already 0. */ break; case SDHC_PROT_WIDTH_4BIT: val32 |= SDHCI_CTRL_4BITBUS; break; case SDHC_PROT_WIDTH_8BIT: val32 |= SDHCI_CTRL_8BITBUS; break; } switch (wrk32 & SDHC_PROT_DMA_MASK) { case SDHC_PROT_SDMA: /* Value is already 0. */ break; case SDHC_PROT_ADMA1: /* This value is deprecated, should never appear. */ break; case SDHC_PROT_ADMA2: val32 |= SDHCI_CTRL_ADMA2; break; case SDHC_PROT_ADMA264: val32 |= SDHCI_CTRL_ADMA264; break; } return val32; } /* * XXX can't find the bus power on/off knob. For now we have to say the * power is always on and always set to the same voltage. */ if (off == SDHCI_POWER_CONTROL) { return (SDHCI_POWER_ON | SDHCI_POWER_300); } return ((RD4(sc, off & ~3) >> (off & 3) * 8) & 0xff); } static uint16_t imx_sdhci_read_2(device_t dev, struct sdhci_slot *slot, bus_size_t off) { struct imx_sdhci_softc *sc = device_get_softc(dev); uint32_t val32, wrk32; if (sc->hwtype == HWTYPE_USDHC) { /* * The USDHC hardware has nothing in the version register, but * it's v3 compatible with all our translation code. */ if (off == SDHCI_HOST_VERSION) { return (SDHCI_SPEC_300 << SDHCI_SPEC_VER_SHIFT); } /* * The USDHC hardware moved the transfer mode bits to the mixed * control register, fetch them from there. */ if (off == SDHCI_TRANSFER_MODE) return (RD4(sc, USDHC_MIX_CONTROL) & 0x37); } else if (sc->hwtype == HWTYPE_ESDHC) { /* * The ESDHC hardware has the typical 32-bit combined "command * and mode" register that we have to cache so that command * isn't written until after mode. On a read, just retrieve the * cached values last written. */ if (off == SDHCI_TRANSFER_MODE) { return (sc->cmd_and_mode >> 16); } else if (off == SDHCI_COMMAND_FLAGS) { return (sc->cmd_and_mode & 0x0000ffff); } } /* * This hardware only manages one slot. Synthesize a slot interrupt * status register... if there are any enabled interrupts active they * must be coming from our one and only slot. */ if (off == SDHCI_SLOT_INT_STATUS) { val32 = RD4(sc, SDHCI_INT_STATUS); val32 &= RD4(sc, SDHCI_SIGNAL_ENABLE); return (val32 ? 1 : 0); } /* * The clock enable bit is in the vendor register and the clock-stable * bit is in the present state register. Transcribe them as if they * were in the clock control register where they should be. * XXX Is it important that we distinguish between "internal" and "card" * clocks? Probably not; transcribe the card clock status to both bits. */ if (off == SDHCI_CLOCK_CONTROL) { val32 = 0; wrk32 = RD4(sc, SDHC_VEND_SPEC); if (wrk32 & SDHC_VEND_FRC_SDCLK_ON) val32 |= SDHCI_CLOCK_INT_EN | SDHCI_CLOCK_CARD_EN; wrk32 = RD4(sc, SDHC_PRES_STATE); if (wrk32 & SDHC_PRES_SDSTB) val32 |= SDHCI_CLOCK_INT_STABLE; val32 |= sc->sdclockreg_freq_bits; return (val32); } return ((RD4(sc, off & ~3) >> (off & 3) * 8) & 0xffff); } static uint32_t imx_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off) { struct imx_sdhci_softc *sc = device_get_softc(dev); uint32_t val32, wrk32; val32 = RD4(sc, off); /* * The hardware leaves the base clock frequency out of the capabilities * register; fill it in. The timeout clock is the same as the active * output sdclock; we indicate that with a quirk setting so don't * populate the timeout frequency bits. * * XXX Turn off (for now) features the hardware can do but this driver * doesn't yet handle (1.8v, suspend/resume, etc). */ if (off == SDHCI_CAPABILITIES) { val32 &= ~SDHCI_CAN_VDD_180; val32 &= ~SDHCI_CAN_DO_SUSPEND; val32 |= SDHCI_CAN_DO_8BITBUS; val32 |= (sc->baseclk_hz / 1000000) << SDHCI_CLOCK_BASE_SHIFT; return (val32); } /* * The hardware moves bits around in the present state register to make * room for all 8 data line state bits. To translate, mask out all the * bits which are not in the same position in both registers (this also * masks out some freescale-specific bits in locations defined as * reserved by sdhci), then shift the data line and retune request bits * down to their standard locations. */ if (off == SDHCI_PRESENT_STATE) { wrk32 = val32; val32 &= 0x000F0F07; val32 |= (wrk32 >> 4) & SDHCI_STATE_DAT_MASK; val32 |= (wrk32 >> 9) & SDHCI_RETUNE_REQUEST; if (sc->force_card_present) val32 |= SDHCI_CARD_PRESENT; return (val32); } /* * imx_sdhci_intr() can synthesize a DATA_END interrupt following a * command with an R1B response, mix it into the hardware status. */ if (off == SDHCI_INT_STATUS) { return (val32 | sc->r1bfix_intmask); } return val32; } static void imx_sdhci_read_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint32_t *data, bus_size_t count) { struct imx_sdhci_softc *sc = device_get_softc(dev); bus_read_multi_4(sc->mem_res, off, data, count); } static void imx_sdhci_write_1(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint8_t val) { struct imx_sdhci_softc *sc = device_get_softc(dev); uint32_t val32; /* * Most of the things in the standard host control register are in the * hardware's wider protocol control register, but some of the bits are * moved around. */ if (off == SDHCI_HOST_CONTROL) { val32 = RD4(sc, SDHC_PROT_CTRL); val32 &= ~(SDHC_PROT_LED | SDHC_PROT_DMA_MASK | SDHC_PROT_WIDTH_MASK | SDHC_PROT_CDTL | SDHC_PROT_CDSS); val32 |= (val & SDHCI_CTRL_LED); if (val & SDHCI_CTRL_8BITBUS) val32 |= SDHC_PROT_WIDTH_8BIT; else val32 |= (val & SDHCI_CTRL_4BITBUS); val32 |= (val & (SDHCI_CTRL_SDMA | SDHCI_CTRL_ADMA2)) << 4; val32 |= (val & (SDHCI_CTRL_CARD_DET | SDHCI_CTRL_FORCE_CARD)); WR4(sc, SDHC_PROT_CTRL, val32); return; } /* XXX I can't find the bus power on/off knob; do nothing. */ if (off == SDHCI_POWER_CONTROL) { return; } val32 = RD4(sc, off & ~3); val32 &= ~(0xff << (off & 3) * 8); val32 |= (val << (off & 3) * 8); WR4(sc, off & ~3, val32); } static void imx_sdhci_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint16_t val) { struct imx_sdhci_softc *sc = device_get_softc(dev); uint32_t val32; /* The USDHC hardware moved the transfer mode bits to mixed control. */ if (sc->hwtype == HWTYPE_USDHC) { if (off == SDHCI_TRANSFER_MODE) { val32 = RD4(sc, USDHC_MIX_CONTROL); val32 &= ~0x3f; val32 |= val & 0x37; // XXX acmd23 not supported here (or by sdhci driver) WR4(sc, USDHC_MIX_CONTROL, val32); return; } } /* * The clock control stuff is complex enough to have its own routine * that can both change speeds and en/disable the clock output. Also, * save the register bits in SDHCI format so that we can play them back * in the read2 routine without complex decoding. */ if (off == SDHCI_CLOCK_CONTROL) { sc->sdclockreg_freq_bits = val & 0xffc0; if (val & SDHCI_CLOCK_CARD_EN) { imx_sdhc_set_clock(sc, true); } else { imx_sdhc_set_clock(sc, false); } } /* * Figure out whether we need to check the DAT0 line for busy status at * interrupt time. The controller should be doing this, but for some * reason it doesn't. There are two cases: * - R1B response with no data transfer should generate a DATA_END (aka * TRANSFER_COMPLETE) interrupt after waiting for busy, but if * there's no data transfer there's no DATA_END interrupt. This is * documented; they seem to think it's a feature. * - R1B response after Auto-CMD12 appears to not work, even though * there's a control bit for it (bit 3) in the vendor register. * When we're starting a command that needs a manual DAT0 line check at * interrupt time, we leave ourselves a note in r1bfix_type so that we * can do the extra work in imx_sdhci_intr(). */ if (off == SDHCI_COMMAND_FLAGS) { if (val & SDHCI_CMD_DATA) { const uint32_t MBAUTOCMD = SDHCI_TRNS_ACMD12 | SDHCI_TRNS_MULTI; val32 = RD4(sc, USDHC_MIX_CONTROL); if ((val32 & MBAUTOCMD) == MBAUTOCMD) sc->r1bfix_type = R1BFIX_AC12; } else { if ((val & SDHCI_CMD_RESP_MASK) == SDHCI_CMD_RESP_SHORT_BUSY) { WR4(sc, SDHCI_INT_ENABLE, slot->intmask | SDHCI_INT_RESPONSE); WR4(sc, SDHCI_SIGNAL_ENABLE, slot->intmask | SDHCI_INT_RESPONSE); sc->r1bfix_type = R1BFIX_NODATA; } } } val32 = RD4(sc, off & ~3); val32 &= ~(0xffff << (off & 3) * 8); val32 |= ((val & 0xffff) << (off & 3) * 8); WR4(sc, off & ~3, val32); } static void imx_sdhci_write_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint32_t val) { struct imx_sdhci_softc *sc = device_get_softc(dev); /* Clear synthesized interrupts, then pass the value to the hardware. */ if (off == SDHCI_INT_STATUS) { sc->r1bfix_intmask &= ~val; } WR4(sc, off, val); } static void imx_sdhci_write_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint32_t *data, bus_size_t count) { struct imx_sdhci_softc *sc = device_get_softc(dev); bus_write_multi_4(sc->mem_res, off, data, count); } static void imx_sdhc_set_clock(struct imx_sdhci_softc *sc, int enable) { uint32_t divisor, enable_bits, enable_reg, freq, prescale, val32; if (sc->hwtype == HWTYPE_ESDHC) { divisor = (sc->sdclockreg_freq_bits >> SDHCI_DIVIDER_SHIFT) & SDHCI_DIVIDER_MASK; enable_reg = SDHCI_CLOCK_CONTROL; enable_bits = SDHC_CLK_IPGEN | SDHC_CLK_HCKEN | SDHC_CLK_PEREN; } else { divisor = (sc->sdclockreg_freq_bits >> SDHCI_DIVIDER_SHIFT) & SDHCI_DIVIDER_MASK; divisor |= ((sc->sdclockreg_freq_bits >> SDHCI_DIVIDER_HI_SHIFT) & SDHCI_DIVIDER_HI_MASK) << SDHCI_DIVIDER_MASK_LEN; enable_reg = SDHCI_CLOCK_CONTROL; enable_bits = SDHC_VEND_IPGEN | SDHC_VEND_HCKEN | SDHC_VEND_PEREN; } WR4(sc, SDHC_VEND_SPEC, RD4(sc, SDHC_VEND_SPEC) & ~SDHC_VEND_FRC_SDCLK_ON); WR4(sc, enable_reg, RD4(sc, enable_reg) & ~enable_bits); if (!enable) return; if (divisor == 0) freq = sc->baseclk_hz; else freq = sc->baseclk_hz / (2 * divisor); - for (prescale = 2; prescale < freq / prescale / 16;) + for (prescale = 2; freq < sc->baseclk_hz / (prescale * 16);) prescale <<= 1; - for (divisor = 1; freq < freq / prescale / divisor;) + for (divisor = 1; freq < sc->baseclk_hz / (prescale * divisor);) ++divisor; + +#ifdef DEBUG + device_printf(sc->dev, + "desired SD freq: %d, actual: %d; base %d prescale %d divisor %d\n", + freq, sc->baseclk_hz / (prescale * divisor), sc->baseclk_hz, + prescale, divisor); +#endif prescale >>= 1; divisor -= 1; val32 = RD4(sc, SDHCI_CLOCK_CONTROL); val32 &= ~SDHC_CLK_DIVISOR_MASK; val32 |= divisor << SDHC_CLK_DIVISOR_SHIFT; val32 &= ~SDHC_CLK_PRESCALE_MASK; val32 |= prescale << SDHC_CLK_PRESCALE_SHIFT; WR4(sc, SDHCI_CLOCK_CONTROL, val32); WR4(sc, enable_reg, RD4(sc, enable_reg) | enable_bits); WR4(sc, SDHC_VEND_SPEC, RD4(sc, SDHC_VEND_SPEC) | SDHC_VEND_FRC_SDCLK_ON); } static boolean_t imx_sdhci_r1bfix_is_wait_done(struct imx_sdhci_softc *sc) { uint32_t inhibit; mtx_assert(&sc->slot.mtx, MA_OWNED); /* * Check the DAT0 line status using both the DLA (data line active) and * CDIHB (data inhibit) bits in the present state register. In theory * just DLA should do the trick, but in practice it takes both. If the * DAT0 line is still being held and we're not yet beyond the timeout * point, just schedule another callout to check again later. */ inhibit = RD4(sc, SDHC_PRES_STATE) & (SDHC_PRES_DLA | SDHC_PRES_CDIHB); if (inhibit && getsbinuptime() < sc->r1bfix_timeout_at) { callout_reset_sbt(&sc->r1bfix_callout, SBT_1MS, 0, imx_sdhci_r1bfix_func, sc, 0); return (false); } /* * If we reach this point with the inhibit bits still set, we've got a * timeout, synthesize a DATA_TIMEOUT interrupt. Otherwise the DAT0 * line has been released, and we synthesize a DATA_END, and if the type * of fix needed was on a command-without-data we also now add in the * original INT_RESPONSE that we suppressed earlier. */ if (inhibit) sc->r1bfix_intmask |= SDHCI_INT_DATA_TIMEOUT; else { sc->r1bfix_intmask |= SDHCI_INT_DATA_END; if (sc->r1bfix_type == R1BFIX_NODATA) sc->r1bfix_intmask |= SDHCI_INT_RESPONSE; } sc->r1bfix_type = R1BFIX_NONE; return (true); } static void imx_sdhci_r1bfix_func(void * arg) { struct imx_sdhci_softc *sc = arg; boolean_t r1bwait_done; mtx_lock(&sc->slot.mtx); r1bwait_done = imx_sdhci_r1bfix_is_wait_done(sc); mtx_unlock(&sc->slot.mtx); if (r1bwait_done) sdhci_generic_intr(&sc->slot); } static void imx_sdhci_intr(void *arg) { struct imx_sdhci_softc *sc = arg; uint32_t intmask; mtx_lock(&sc->slot.mtx); /* * Manually check the DAT0 line for R1B response types that the * controller fails to handle properly. The controller asserts the done * interrupt while the card is still asserting busy with the DAT0 line. * * We check DAT0 immediately because most of the time, especially on a * read, the card will actually be done by time we get here. If it's * not, then the wait_done routine will schedule a callout to re-check * periodically until it is done. In that case we clear the interrupt * out of the hardware now so that we can present it later when the DAT0 * line is released. * * If we need to wait for the the DAT0 line to be released, we set up a * timeout point 250ms in the future. This number comes from the SD * spec, which allows a command to take that long. In the real world, * cards tend to take 10-20ms for a long-running command such as a write * or erase that spans two pages. */ switch (sc->r1bfix_type) { case R1BFIX_NODATA: intmask = RD4(sc, SDHC_INT_STATUS) & SDHCI_INT_RESPONSE; break; case R1BFIX_AC12: intmask = RD4(sc, SDHC_INT_STATUS) & SDHCI_INT_DATA_END; break; default: intmask = 0; break; } if (intmask) { sc->r1bfix_timeout_at = getsbinuptime() + 250 * SBT_1MS; if (!imx_sdhci_r1bfix_is_wait_done(sc)) { WR4(sc, SDHC_INT_STATUS, intmask); bus_barrier(sc->mem_res, SDHC_INT_STATUS, 4, BUS_SPACE_BARRIER_WRITE); } } mtx_unlock(&sc->slot.mtx); sdhci_generic_intr(&sc->slot); } static int imx_sdhci_get_ro(device_t bus, device_t child) { return (false); } static int imx_sdhci_detach(device_t dev) { return (EBUSY); } static int imx_sdhci_attach(device_t dev) { struct imx_sdhci_softc *sc = device_get_softc(dev); int rid, err; phandle_t node; sc->dev = dev; sc->hwtype = ofw_bus_search_compatible(dev, compat_data)->ocd_data; if (sc->hwtype == HWTYPE_NONE) panic("Impossible: not compatible in imx_sdhci_attach()"); rid = 0; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!sc->mem_res) { device_printf(dev, "cannot allocate memory window\n"); err = ENXIO; goto fail; } rid = 0; sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (!sc->irq_res) { device_printf(dev, "cannot allocate interrupt\n"); err = ENXIO; goto fail; } if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_BIO | INTR_MPSAFE, NULL, imx_sdhci_intr, sc, &sc->intr_cookie)) { device_printf(dev, "cannot setup interrupt handler\n"); err = ENXIO; goto fail; } sc->slot.quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK; /* * DMA is not really broken, I just haven't implemented it yet. */ sc->slot.quirks |= SDHCI_QUIRK_BROKEN_DMA; /* * Set the buffer watermark level to 128 words (512 bytes) for both read * and write. The hardware has a restriction that when the read or * write ready status is asserted, that means you can read exactly the * number of words set in the watermark register before you have to * re-check the status and potentially wait for more data. The main * sdhci driver provides no hook for doing status checking on less than * a full block boundary, so we set the watermark level to be a full * block. Reads and writes where the block size is less than the * watermark size will work correctly too, no need to change the * watermark for different size blocks. However, 128 is the maximum * allowed for the watermark, so PIO is limitted to 512 byte blocks * (which works fine for SD cards, may be a problem for SDIO some day). * * XXX need named constants for this stuff. */ WR4(sc, SDHC_WTMK_LVL, 0x08800880); sc->baseclk_hz = imx_ccm_sdhci_hz(); /* * If the slot is flagged with the non-removable property, set our flag * to always force the SDHCI_CARD_PRESENT bit on. * * XXX Workaround for gpio-based card detect... * * We don't have gpio support yet. If there's a cd-gpios property just * force the SDHCI_CARD_PRESENT bit on for now. If there isn't really a * card there it will fail to probe at the mmc layer and nothing bad * happens except instantiating an mmcN device for an empty slot. */ node = ofw_bus_get_node(dev); if (OF_hasprop(node, "non-removable")) sc->force_card_present = true; else if (OF_hasprop(node, "cd-gpios")) { /* XXX put real gpio hookup here. */ sc->force_card_present = true; } callout_init(&sc->r1bfix_callout, 1); sdhci_init_slot(dev, &sc->slot, 0); bus_generic_probe(dev); bus_generic_attach(dev); sdhci_start_slot(&sc->slot); return (0); fail: if (sc->intr_cookie) bus_teardown_intr(dev, sc->irq_res, sc->intr_cookie); if (sc->irq_res) bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); if (sc->mem_res) bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res); return (err); } static int imx_sdhci_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data) { case HWTYPE_ESDHC: device_set_desc(dev, "Freescale eSDHC controller"); return (BUS_PROBE_DEFAULT); case HWTYPE_USDHC: device_set_desc(dev, "Freescale uSDHC controller"); return (BUS_PROBE_DEFAULT); default: break; } return (ENXIO); } static device_method_t imx_sdhci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, imx_sdhci_probe), DEVMETHOD(device_attach, imx_sdhci_attach), DEVMETHOD(device_detach, imx_sdhci_detach), /* Bus interface */ DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar), DEVMETHOD(bus_write_ivar, sdhci_generic_write_ivar), DEVMETHOD(bus_print_child, bus_generic_print_child), /* MMC bridge interface */ DEVMETHOD(mmcbr_update_ios, sdhci_generic_update_ios), DEVMETHOD(mmcbr_request, sdhci_generic_request), DEVMETHOD(mmcbr_get_ro, imx_sdhci_get_ro), DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host), DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host), /* SDHCI registers accessors */ DEVMETHOD(sdhci_read_1, imx_sdhci_read_1), DEVMETHOD(sdhci_read_2, imx_sdhci_read_2), DEVMETHOD(sdhci_read_4, imx_sdhci_read_4), DEVMETHOD(sdhci_read_multi_4, imx_sdhci_read_multi_4), DEVMETHOD(sdhci_write_1, imx_sdhci_write_1), DEVMETHOD(sdhci_write_2, imx_sdhci_write_2), DEVMETHOD(sdhci_write_4, imx_sdhci_write_4), DEVMETHOD(sdhci_write_multi_4, imx_sdhci_write_multi_4), { 0, 0 } }; static devclass_t imx_sdhci_devclass; static driver_t imx_sdhci_driver = { "sdhci_imx", imx_sdhci_methods, sizeof(struct imx_sdhci_softc), }; DRIVER_MODULE(sdhci_imx, simplebus, imx_sdhci_driver, imx_sdhci_devclass, 0, 0); MODULE_DEPEND(sdhci_imx, sdhci, 1, 1, 1); DRIVER_MODULE(mmc, sdhci_imx, mmc_driver, mmc_devclass, NULL, NULL); Index: user/alc/PQ_LAUNDRY/sys/arm/include/intr.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/include/intr.h (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/include/intr.h (revision 292449) @@ -1,192 +1,192 @@ /* $NetBSD: intr.h,v 1.7 2003/06/16 20:01:00 thorpej Exp $ */ /*- * Copyright (c) 1997 Mark Brinicombe. * 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 Mark Brinicombe * for the NetBSD Project. * 4. The name of the company nor the name of the author may be used to * endorse or promote products derived from this software without specific * prior written permission. * * 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 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ * */ #ifndef _MACHINE_INTR_H_ #define _MACHINE_INTR_H_ #ifdef FDT #include #endif #ifdef ARM_INTRNG #ifndef NIRQ #define NIRQ 1024 /* XXX - It should be an option. */ #endif #ifdef notyet #define INTR_SOLO INTR_MD1 -typedef int arm_irq_filter_t(void *arg, struct trapframe *tf); +typedef int intr_irq_filter_t(void *arg, struct trapframe *tf); #else -typedef int arm_irq_filter_t(void *arg); +typedef int intr_irq_filter_t(void *arg); #endif -#define ARM_ISRC_NAMELEN (MAXCOMLEN + 1) +#define INTR_ISRC_NAMELEN (MAXCOMLEN + 1) -typedef void arm_ipi_filter_t(void *arg); +typedef void intr_ipi_filter_t(void *arg); -enum arm_isrc_type { - ARM_ISRCT_NAMESPACE, - ARM_ISRCT_FDT +enum intr_isrc_type { + INTR_ISRCT_NAMESPACE, + INTR_ISRCT_FDT }; -#define ARM_ISRCF_REGISTERED 0x01 /* registered in a controller */ -#define ARM_ISRCF_PERCPU 0x02 /* per CPU interrupt */ -#define ARM_ISRCF_BOUND 0x04 /* bound to a CPU */ +#define INTR_ISRCF_REGISTERED 0x01 /* registered in a controller */ +#define INTR_ISRCF_PERCPU 0x02 /* per CPU interrupt */ +#define INTR_ISRCF_BOUND 0x04 /* bound to a CPU */ /* Interrupt source definition. */ -struct arm_irqsrc { +struct intr_irqsrc { device_t isrc_dev; /* where isrc is mapped */ intptr_t isrc_xref; /* device reference key */ uintptr_t isrc_data; /* device data for isrc */ u_int isrc_irq; /* unique identificator */ - enum arm_isrc_type isrc_type; /* how is isrc decribed */ + enum intr_isrc_type isrc_type; /* how is isrc decribed */ u_int isrc_flags; - char isrc_name[ARM_ISRC_NAMELEN]; + char isrc_name[INTR_ISRC_NAMELEN]; uint16_t isrc_nspc_type; uint16_t isrc_nspc_num; enum intr_trigger isrc_trig; enum intr_polarity isrc_pol; cpuset_t isrc_cpu; /* on which CPUs is enabled */ u_int isrc_index; u_long * isrc_count; u_int isrc_handlers; struct intr_event * isrc_event; - arm_irq_filter_t * isrc_filter; - arm_ipi_filter_t * isrc_ipifilter; + intr_irq_filter_t * isrc_filter; + intr_ipi_filter_t * isrc_ipifilter; void * isrc_arg; #ifdef FDT u_int isrc_ncells; pcell_t isrc_cells[]; /* leave it last */ #endif }; -void arm_irq_set_name(struct arm_irqsrc *isrc, const char *fmt, ...) +void intr_irq_set_name(struct intr_irqsrc *isrc, const char *fmt, ...) __printflike(2, 3); -void arm_irq_dispatch(struct arm_irqsrc *isrc, struct trapframe *tf); +void intr_irq_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf); -#define ARM_IRQ_NSPC_NONE 0 -#define ARM_IRQ_NSPC_PLAIN 1 -#define ARM_IRQ_NSPC_IRQ 2 -#define ARM_IRQ_NSPC_IPI 3 +#define INTR_IRQ_NSPC_NONE 0 +#define INTR_IRQ_NSPC_PLAIN 1 +#define INTR_IRQ_NSPC_IRQ 2 +#define INTR_IRQ_NSPC_IPI 3 -u_int arm_namespace_map_irq(device_t dev, uint16_t type, uint16_t num); +u_int intr_namespace_map_irq(device_t dev, uint16_t type, uint16_t num); #ifdef FDT -u_int arm_fdt_map_irq(phandle_t, pcell_t *, u_int); +u_int intr_fdt_map_irq(phandle_t, pcell_t *, u_int); #endif -int arm_pic_register(device_t dev, intptr_t xref); -int arm_pic_unregister(device_t dev, intptr_t xref); -int arm_pic_claim_root(device_t dev, intptr_t xref, arm_irq_filter_t *filter, +int intr_pic_register(device_t dev, intptr_t xref); +int intr_pic_unregister(device_t dev, intptr_t xref); +int intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter, void *arg, u_int ipicount); -int arm_irq_add_handler(device_t dev, driver_filter_t, driver_intr_t, void *, +int intr_irq_add_handler(device_t dev, driver_filter_t, driver_intr_t, void *, u_int, int, void **); -int arm_irq_remove_handler(device_t dev, u_int, void *); -int arm_irq_config(u_int, enum intr_trigger, enum intr_polarity); -int arm_irq_describe(u_int, void *, const char *); +int intr_irq_remove_handler(device_t dev, u_int, void *); +int intr_irq_config(u_int, enum intr_trigger, enum intr_polarity); +int intr_irq_describe(u_int, void *, const char *); -u_int arm_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask); +u_int intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask); #ifdef SMP -int arm_irq_bind(u_int, int); +int intr_irq_bind(u_int, int); -void arm_ipi_dispatch(struct arm_irqsrc *isrc, struct trapframe *tf); +void intr_ipi_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf); #define AISHF_NOALLOC 0x0001 -int arm_ipi_set_handler(u_int ipi, const char *name, arm_ipi_filter_t *filter, +int intr_ipi_set_handler(u_int ipi, const char *name, intr_ipi_filter_t *filter, void *arg, u_int flags); -void arm_pic_init_secondary(void); +void intr_pic_init_secondary(void); #endif #else /* ARM_INTRNG */ /* XXX move to std.* files? */ #ifdef CPU_XSCALE_81342 #define NIRQ 128 #elif defined(CPU_XSCALE_PXA2X0) #include #define NIRQ IRQ_GPIO_MAX #elif defined(SOC_MV_DISCOVERY) #define NIRQ 96 #elif defined(CPU_ARM9) || defined(SOC_MV_KIRKWOOD) || \ defined(CPU_XSCALE_IXP435) #define NIRQ 64 #elif defined(CPU_CORTEXA) #define NIRQ 1020 #elif defined(CPU_KRAIT) #define NIRQ 288 #elif defined(CPU_ARM1176) #define NIRQ 128 #elif defined(SOC_MV_ARMADAXP) #define MAIN_IRQ_NUM 116 #define ERR_IRQ_NUM 32 #define ERR_IRQ (MAIN_IRQ_NUM) #define MSI_IRQ_NUM 32 #define MSI_IRQ (ERR_IRQ + ERR_IRQ_NUM) #define NIRQ (MAIN_IRQ_NUM + ERR_IRQ_NUM + MSI_IRQ_NUM) #else #define NIRQ 32 #endif int arm_get_next_irq(int); void arm_mask_irq(uintptr_t); void arm_unmask_irq(uintptr_t); void arm_intrnames_init(void); void arm_setup_irqhandler(const char *, int (*)(void*), void (*)(void*), void *, int, int, void **); int arm_remove_irqhandler(int, void *); extern void (*arm_post_filter)(void *); extern int (*arm_config_irq)(int irq, enum intr_trigger trig, enum intr_polarity pol); -void arm_pic_init_secondary(void); +void intr_pic_init_secondary(void); #ifdef FDT int gic_decode_fdt(phandle_t, pcell_t *, int *, int *, int *); -int arm_fdt_map_irq(phandle_t, pcell_t *, int); +int intr_fdt_map_irq(phandle_t, pcell_t *, int); #endif #endif /* ARM_INTRNG */ void arm_irq_memory_barrier(uintptr_t); #endif /* _MACHINE_INTR_H */ Index: user/alc/PQ_LAUNDRY/sys/arm/include/smp.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/include/smp.h (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/include/smp.h (revision 292449) @@ -1,57 +1,57 @@ /* $FreeBSD$ */ #ifndef _MACHINE_SMP_H_ #define _MACHINE_SMP_H_ #include #include #ifdef ARM_INTRNG enum { IPI_AST, IPI_PREEMPT, IPI_RENDEZVOUS, IPI_STOP, IPI_STOP_HARD = IPI_STOP, /* These are synonyms on arm. */ IPI_HARDCLOCK, IPI_TLB, IPI_CACHE, - ARM_IPI_COUNT + INTR_IPI_COUNT }; #else #define IPI_AST 0 #define IPI_PREEMPT 2 #define IPI_RENDEZVOUS 3 #define IPI_STOP 4 #define IPI_STOP_HARD 4 #define IPI_HARDCLOCK 6 #define IPI_TLB 7 #define IPI_CACHE 8 #endif /* INTRNG */ void init_secondary(int cpu); void mpentry(void); void ipi_all_but_self(u_int ipi); void ipi_cpu(int cpu, u_int ipi); void ipi_selected(cpuset_t cpus, u_int ipi); /* PIC interface */ void pic_ipi_send(cpuset_t cpus, u_int ipi); #ifndef ARM_INTRNG void pic_ipi_clear(int ipi); int pic_ipi_read(int arg); #endif /* Platform interface */ void platform_mp_setmaxid(void); int platform_mp_probe(void); void platform_mp_start_ap(void); void platform_mp_init_secondary(void); void platform_ipi_send(cpuset_t cpus, u_int ipi); /* global data in mp_machdep.c */ extern struct pcb stoppcbs[]; #endif /* !_MACHINE_SMP_H_ */ Index: user/alc/PQ_LAUNDRY/sys/arm/qemu/virt_mp.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/qemu/virt_mp.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/qemu/virt_mp.c (revision 292449) @@ -1,113 +1,113 @@ /*- * Copyright (c) 2015 Andrew Turner * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include static int running_cpus; int platform_mp_probe(void) { return (mp_ncpus > 1); } static boolean_t virt_maxid(u_int id, phandle_t node, u_int addr_cells, pcell_t *reg) { if (mp_maxid < id) mp_maxid = id; return (true); } void platform_mp_setmaxid(void) { mp_maxid = PCPU_GET(cpuid); mp_ncpus = ofw_cpu_early_foreach(virt_maxid, true); if (mp_ncpus < 1) mp_ncpus = 1; mp_ncpus = MIN(mp_ncpus, MAXCPU); } static boolean_t virt_start_ap(u_int id, phandle_t node, u_int addr_cells, pcell_t *reg) { int err; if (running_cpus >= mp_ncpus) return (false); running_cpus++; err = psci_cpu_on(*reg, pmap_kextract((vm_offset_t)mpentry), id); if (err != PSCI_RETVAL_SUCCESS) return (false); return (true); } void platform_mp_start_ap(void) { ofw_cpu_early_foreach(virt_start_ap, true); } void platform_mp_init_secondary(void) { - arm_pic_init_secondary(); + intr_pic_init_secondary(); } void platform_ipi_send(cpuset_t cpus, u_int ipi) { pic_ipi_send(cpus, ipi); } Index: user/alc/PQ_LAUNDRY/sys/arm/rockchip/rk30xx_mp.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/rockchip/rk30xx_mp.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/rockchip/rk30xx_mp.c (revision 292449) @@ -1,195 +1,195 @@ /*- * Copyright (c) 2014 Ganbold Tsagaankhuu * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #define SCU_PHYSBASE 0x1013c000 #define SCU_SIZE 0x100 #define SCU_CONTROL_REG 0x00 #define SCU_CONTROL_ENABLE (1 << 0) #define SCU_STANDBY_EN (1 << 5) #define SCU_CONFIG_REG 0x04 #define SCU_CONFIG_REG_NCPU_MASK 0x03 #define SCU_CPUPOWER_REG 0x08 #define SCU_INV_TAGS_REG 0x0c #define SCU_FILTER_START_REG 0x10 #define SCU_FILTER_END_REG 0x14 #define SCU_SECURE_ACCESS_REG 0x18 #define SCU_NONSECURE_ACCESS_REG 0x1c #define IMEM_PHYSBASE 0x10080000 #define IMEM_SIZE 0x20 #define PMU_PHYSBASE 0x20004000 #define PMU_SIZE 0x100 #define PMU_PWRDN_CON 0x08 #define PMU_PWRDN_SCU (1 << 4) extern char *mpentry_addr; static void rk30xx_boot2(void); static void rk30xx_boot2(void) { __asm __volatile( "ldr pc, 1f\n" ".globl mpentry_addr\n" "mpentry_addr:\n" "1: .space 4\n"); } void platform_mp_init_secondary(void) { - arm_pic_init_secondary(); + intr_pic_init_secondary(); } void platform_mp_setmaxid(void) { bus_space_handle_t scu; int ncpu; uint32_t val; if (mp_ncpus != 0) return; if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0) panic("Could not map the SCU"); val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONFIG_REG); ncpu = (val & SCU_CONFIG_REG_NCPU_MASK) + 1; bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE); mp_ncpus = ncpu; mp_maxid = ncpu - 1; } int platform_mp_probe(void) { if (mp_ncpus == 0) platform_mp_setmaxid(); return (mp_ncpus > 1); } void platform_mp_start_ap(void) { bus_space_handle_t scu; bus_space_handle_t imem; bus_space_handle_t pmu; uint32_t val; int i; if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0) panic("Could not map the SCU"); if (bus_space_map(fdtbus_bs_tag, IMEM_PHYSBASE, IMEM_SIZE, 0, &imem) != 0) panic("Could not map the IMEM"); if (bus_space_map(fdtbus_bs_tag, PMU_PHYSBASE, PMU_SIZE, 0, &pmu) != 0) panic("Could not map the PMU"); /* * Invalidate SCU cache tags. The 0x0000ffff constant invalidates all * ways on all cores 0-3. Per the ARM docs, it's harmless to write to * the bits for cores that are not present. */ bus_space_write_4(fdtbus_bs_tag, scu, SCU_INV_TAGS_REG, 0x0000ffff); /* Make sure all cores except the first are off */ val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON); for (i = 1; i < mp_ncpus; i++) val |= 1 << i; bus_space_write_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON, val); /* Enable SCU power domain */ val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON); val &= ~PMU_PWRDN_SCU; bus_space_write_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON, val); /* Enable SCU */ val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG); bus_space_write_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG, val | SCU_CONTROL_ENABLE); /* * Cores will execute the code which resides at the start of * the on-chip bootram/sram after power-on. This sram region * should be reserved and the trampoline code that directs * the core to the real startup code in ram should be copied * into this sram region. * * First set boot function for the sram code. */ mpentry_addr = (char *)pmap_kextract((vm_offset_t)mpentry); /* Copy trampoline to sram, that runs during startup of the core */ bus_space_write_region_4(fdtbus_bs_tag, imem, 0, (uint32_t *)&rk30xx_boot2, 8); cpu_idcache_wbinv_all(); cpu_l2cache_wbinv_all(); /* Start all cores */ val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON); for (i = 1; i < mp_ncpus; i++) val &= ~(1 << i); bus_space_write_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON, val); armv7_sev(); bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE); bus_space_unmap(fdtbus_bs_tag, imem, IMEM_SIZE); bus_space_unmap(fdtbus_bs_tag, pmu, PMU_SIZE); } void platform_ipi_send(cpuset_t cpus, u_int ipi) { pic_ipi_send(cpus, ipi); } Index: user/alc/PQ_LAUNDRY/sys/arm/samsung/exynos/exynos5_mp.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/samsung/exynos/exynos5_mp.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/samsung/exynos/exynos5_mp.c (revision 292449) @@ -1,151 +1,151 @@ /*- * Copyright (c) 2013-2014 Ruslan Bukin * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #define EXYNOS_CHIPID 0x10000000 #define EXYNOS5250_SOC_ID 0x43520000 #define EXYNOS5420_SOC_ID 0xE5420000 #define EXYNOS5_SOC_ID_MASK 0xFFFFF000 #define EXYNOS_SYSRAM 0x02020000 #define EXYNOS5420_SYSRAM_NS (EXYNOS_SYSRAM + 0x53000 + 0x1c) #define EXYNOS_PMU_BASE 0x10040000 #define CORE_CONFIG(n) (0x2000 + (0x80 * (n))) #define CORE_STATUS(n) (CORE_CONFIG(n) + 0x4) #define CORE_PWR_EN 0x3 static int exynos_get_soc_id(void) { bus_addr_t chipid; int reg; if (bus_space_map(fdtbus_bs_tag, EXYNOS_CHIPID, 0x1000, 0, &chipid) != 0) panic("Couldn't map chipid\n"); reg = bus_space_read_4(fdtbus_bs_tag, chipid, 0x0); bus_space_unmap(fdtbus_bs_tag, chipid, 0x1000); return (reg & EXYNOS5_SOC_ID_MASK); } void platform_mp_init_secondary(void) { - arm_pic_init_secondary(); + intr_pic_init_secondary(); } void platform_mp_setmaxid(void) { if (exynos_get_soc_id() == EXYNOS5420_SOC_ID) mp_ncpus = 4; else mp_ncpus = 2; mp_maxid = mp_ncpus - 1; } int platform_mp_probe(void) { return (mp_ncpus > 1); } void platform_mp_start_ap(void) { bus_addr_t sysram, pmu; int err, i, j; int status; int reg; err = bus_space_map(fdtbus_bs_tag, EXYNOS_PMU_BASE, 0x20000, 0, &pmu); if (err != 0) panic("Couldn't map pmu\n"); if (exynos_get_soc_id() == EXYNOS5420_SOC_ID) reg = EXYNOS5420_SYSRAM_NS; else reg = EXYNOS_SYSRAM; err = bus_space_map(fdtbus_bs_tag, reg, 0x100, 0, &sysram); if (err != 0) panic("Couldn't map sysram\n"); /* Give power to CPUs */ for (i = 1; i < mp_ncpus; i++) { bus_space_write_4(fdtbus_bs_tag, pmu, CORE_CONFIG(i), CORE_PWR_EN); for (j = 10; j >= 0; j--) { status = bus_space_read_4(fdtbus_bs_tag, pmu, CORE_STATUS(i)); if ((status & CORE_PWR_EN) == CORE_PWR_EN) break; DELAY(10); if (j == 0) printf("Can't power on CPU%d\n", i); } } bus_space_write_4(fdtbus_bs_tag, sysram, 0x0, pmap_kextract((vm_offset_t)mpentry)); cpu_idcache_wbinv_all(); cpu_l2cache_wbinv_all(); armv7_sev(); bus_space_unmap(fdtbus_bs_tag, sysram, 0x100); bus_space_unmap(fdtbus_bs_tag, pmu, 0x20000); } void platform_ipi_send(cpuset_t cpus, u_int ipi) { pic_ipi_send(cpus, ipi); } Index: user/alc/PQ_LAUNDRY/sys/arm/ti/aintc.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/ti/aintc.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/ti/aintc.c (revision 292449) @@ -1,201 +1,202 @@ /*- * Copyright (c) 2012 Damjan Marion * All rights reserved. * * Based on OMAP3 INTC code by Ben Gray * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #define INTC_REVISION 0x00 #define INTC_SYSCONFIG 0x10 #define INTC_SYSSTATUS 0x14 #define INTC_SIR_IRQ 0x40 #define INTC_CONTROL 0x48 #define INTC_THRESHOLD 0x68 #define INTC_MIR_CLEAR(x) (0x88 + ((x) * 0x20)) #define INTC_MIR_SET(x) (0x8C + ((x) * 0x20)) #define INTC_ISR_SET(x) (0x90 + ((x) * 0x20)) #define INTC_ISR_CLEAR(x) (0x94 + ((x) * 0x20)) struct ti_aintc_softc { device_t sc_dev; struct resource * aintc_res[3]; bus_space_tag_t aintc_bst; bus_space_handle_t aintc_bsh; uint8_t ver; }; static struct resource_spec ti_aintc_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, { -1, 0 } }; static struct ti_aintc_softc *ti_aintc_sc = NULL; #define aintc_read_4(_sc, reg) \ bus_space_read_4((_sc)->aintc_bst, (_sc)->aintc_bsh, (reg)) #define aintc_write_4(_sc, reg, val) \ bus_space_write_4((_sc)->aintc_bst, (_sc)->aintc_bsh, (reg), (val)) /* List of compatible strings for FDT tree */ static struct ofw_compat_data compat_data[] = { {"ti,am33xx-intc", 1}, {"ti,omap2-intc", 1}, {NULL, 0}, }; static void aintc_post_filter(void *arg) { arm_irq_memory_barrier(0); aintc_write_4(ti_aintc_sc, INTC_CONTROL, 1); /* EOI */ } static int ti_aintc_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) return (ENXIO); device_set_desc(dev, "TI AINTC Interrupt Controller"); return (BUS_PROBE_DEFAULT); } static int ti_aintc_attach(device_t dev) { struct ti_aintc_softc *sc = device_get_softc(dev); uint32_t x; sc->sc_dev = dev; if (ti_aintc_sc) return (ENXIO); if (bus_alloc_resources(dev, ti_aintc_spec, sc->aintc_res)) { device_printf(dev, "could not allocate resources\n"); return (ENXIO); } sc->aintc_bst = rman_get_bustag(sc->aintc_res[0]); sc->aintc_bsh = rman_get_bushandle(sc->aintc_res[0]); ti_aintc_sc = sc; x = aintc_read_4(sc, INTC_REVISION); device_printf(dev, "Revision %u.%u\n",(x >> 4) & 0xF, x & 0xF); /* SoftReset */ aintc_write_4(sc, INTC_SYSCONFIG, 2); /* Wait for reset to complete */ while(!(aintc_read_4(sc, INTC_SYSSTATUS) & 1)); /*Set Priority Threshold */ aintc_write_4(sc, INTC_THRESHOLD, 0xFF); arm_post_filter = aintc_post_filter; return (0); } static device_method_t ti_aintc_methods[] = { DEVMETHOD(device_probe, ti_aintc_probe), DEVMETHOD(device_attach, ti_aintc_attach), { 0, 0 } }; static driver_t ti_aintc_driver = { "aintc", ti_aintc_methods, sizeof(struct ti_aintc_softc), }; static devclass_t ti_aintc_devclass; EARLY_DRIVER_MODULE(aintc, simplebus, ti_aintc_driver, ti_aintc_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); +SIMPLEBUS_PNP_INFO(compat_data); int arm_get_next_irq(int last_irq) { struct ti_aintc_softc *sc = ti_aintc_sc; uint32_t active_irq; /* Get the next active interrupt */ active_irq = aintc_read_4(sc, INTC_SIR_IRQ); /* Check for spurious interrupt */ if ((active_irq & 0xffffff80)) { device_printf(sc->sc_dev, "Spurious interrupt detected (0x%08x)\n", active_irq); aintc_write_4(sc, INTC_SIR_IRQ, 0); return -1; } if (active_irq != last_irq) return active_irq; else return -1; } void arm_mask_irq(uintptr_t nb) { struct ti_aintc_softc *sc = ti_aintc_sc; aintc_write_4(sc, INTC_MIR_SET(nb >> 5), (1UL << (nb & 0x1F))); aintc_write_4(sc, INTC_CONTROL, 1); /* EOI */ } void arm_unmask_irq(uintptr_t nb) { struct ti_aintc_softc *sc = ti_aintc_sc; arm_irq_memory_barrier(nb); aintc_write_4(sc, INTC_MIR_CLEAR(nb >> 5), (1UL << (nb & 0x1F))); } Index: user/alc/PQ_LAUNDRY/sys/arm/ti/omap4/omap4_mp.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/ti/omap4/omap4_mp.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/ti/omap4/omap4_mp.c (revision 292449) @@ -1,87 +1,87 @@ /*- * Copyright (c) 2012 Olivier Houchard. 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include void platform_mp_init_secondary(void) { - arm_pic_init_secondary(); + intr_pic_init_secondary(); } void platform_mp_setmaxid(void) { mp_maxid = 1; mp_ncpus = 2; } int platform_mp_probe(void) { return (1); } void platform_mp_start_ap(void) { bus_addr_t scu_addr; if (bus_space_map(fdtbus_bs_tag, 0x48240000, 0x1000, 0, &scu_addr) != 0) panic("Couldn't map the SCU\n"); /* Enable the SCU */ *(volatile unsigned int *)scu_addr |= 1; //*(volatile unsigned int *)(scu_addr + 0x30) |= 1; cpu_idcache_wbinv_all(); cpu_l2cache_wbinv_all(); ti_smc0(0x200, 0xfffffdff, MODIFY_AUX_CORE_0); ti_smc0(pmap_kextract((vm_offset_t)mpentry), 0, WRITE_AUX_CORE_1); armv7_sev(); bus_space_unmap(fdtbus_bs_tag, scu_addr, 0x1000); } void platform_ipi_send(cpuset_t cpus, u_int ipi) { pic_ipi_send(cpus, ipi); } Index: user/alc/PQ_LAUNDRY/sys/arm/xilinx/zy7_mp.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm/xilinx/zy7_mp.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm/xilinx/zy7_mp.c (revision 292449) @@ -1,119 +1,119 @@ /*- * Copyright (c) 2013 Thomas Skibo. 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #define ZYNQ7_CPU1_ENTRY 0xfffffff0 #define SCU_CONTROL_REG 0xf8f00000 #define SCU_CONTROL_ENABLE (1 << 0) void platform_mp_init_secondary(void) { - arm_pic_init_secondary(); + intr_pic_init_secondary(); } void platform_mp_setmaxid(void) { mp_maxid = 1; mp_ncpus = 2; } int platform_mp_probe(void) { return (1); } void platform_mp_start_ap(void) { bus_space_handle_t scu_handle; bus_space_handle_t ocm_handle; uint32_t scu_ctrl; /* Map in SCU control register. */ if (bus_space_map(fdtbus_bs_tag, SCU_CONTROL_REG, 4, 0, &scu_handle) != 0) panic("platform_mp_start_ap: Couldn't map SCU config reg\n"); /* Set SCU enable bit. */ scu_ctrl = bus_space_read_4(fdtbus_bs_tag, scu_handle, 0); scu_ctrl |= SCU_CONTROL_ENABLE; bus_space_write_4(fdtbus_bs_tag, scu_handle, 0, scu_ctrl); bus_space_unmap(fdtbus_bs_tag, scu_handle, 4); /* Map in magic location to give entry address to CPU1. */ if (bus_space_map(fdtbus_bs_tag, ZYNQ7_CPU1_ENTRY, 4, 0, &ocm_handle) != 0) panic("platform_mp_start_ap: Couldn't map OCM\n"); /* Write start address for CPU1. */ bus_space_write_4(fdtbus_bs_tag, ocm_handle, 0, pmap_kextract((vm_offset_t)mpentry)); bus_space_unmap(fdtbus_bs_tag, ocm_handle, 4); /* * The SCU is enabled above but I think the second CPU doesn't * turn on filtering until after the wake-up below. I think that's why * things don't work if I don't put these cache ops here. Also, the * magic location, 0xfffffff0, isn't in the SCU's filtering range so it * needs a write-back too. */ cpu_idcache_wbinv_all(); cpu_l2cache_wbinv_all(); /* Wake up CPU1. */ armv7_sev(); } void platform_ipi_send(cpuset_t cpus, u_int ipi) { pic_ipi_send(cpus, ipi); } Index: user/alc/PQ_LAUNDRY/sys/arm64/include/ofw_machdep.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/arm64/include/ofw_machdep.h (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/arm64/include/ofw_machdep.h (revision 292449) @@ -1,44 +1,47 @@ /*- * Copyright (c) 2009 The FreeBSD Foundation * All rights reserved. * * This software was developed by Semihalf under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _MACHINE_OFW_MACHDEP_H_ #define _MACHINE_OFW_MACHDEP_H_ #include typedef uint32_t cell_t; struct mem_region { vm_offset_t mr_start; vm_size_t mr_size; }; +/* FDT follows ePAPR */ +#define OFW_EPAPR + #endif /* _MACHINE_OFW_MACHDEP_H_ */ Index: user/alc/PQ_LAUNDRY/sys/boot/efi/loader/bootinfo.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/boot/efi/loader/bootinfo.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/boot/efi/loader/bootinfo.c (revision 292449) @@ -1,470 +1,471 @@ /*- * Copyright (c) 1998 Michael Smith * Copyright (c) 2004, 2006 Marcel Moolenaar * Copyright (c) 2014 The FreeBSD Foundation * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include "bootstrap.h" #include "loader_efi.h" #if defined(__amd64__) #include #include "framebuffer.h" #endif #if defined(LOADER_FDT_SUPPORT) #include #endif static const char howto_switches[] = "aCdrgDmphsv"; static int howto_masks[] = { RB_ASKNAME, RB_CDROM, RB_KDB, RB_DFLTROOT, RB_GDB, RB_MULTIPLE, RB_MUTE, RB_PAUSE, RB_SERIAL, RB_SINGLE, RB_VERBOSE }; static int bi_getboothowto(char *kargs) { const char *sw; char *opts; char *console; int howto, i; howto = 0; /* Get the boot options from the environment first. */ for (i = 0; howto_names[i].ev != NULL; i++) { if (getenv(howto_names[i].ev) != NULL) howto |= howto_names[i].mask; } console = getenv("console"); if (console != NULL) { if (strcmp(console, "comconsole") == 0) howto |= RB_SERIAL; if (strcmp(console, "nullconsole") == 0) howto |= RB_MUTE; } /* Parse kargs */ if (kargs == NULL) return (howto); opts = strchr(kargs, '-'); while (opts != NULL) { while (*(++opts) != '\0') { sw = strchr(howto_switches, *opts); if (sw == NULL) break; howto |= howto_masks[sw - howto_switches]; } opts = strchr(opts, '-'); } return (howto); } /* * Copy the environment into the load area starting at (addr). * Each variable is formatted as =, with a single nul * separating each variable, and a double nul terminating the environment. */ static vm_offset_t bi_copyenv(vm_offset_t start) { struct env_var *ep; vm_offset_t addr, last; size_t len; addr = last = start; /* Traverse the environment. */ for (ep = environ; ep != NULL; ep = ep->ev_next) { len = strlen(ep->ev_name); if (archsw.arch_copyin(ep->ev_name, addr, len) != len) break; addr += len; if (archsw.arch_copyin("=", addr, 1) != 1) break; addr++; if (ep->ev_value != NULL) { len = strlen(ep->ev_value); if (archsw.arch_copyin(ep->ev_value, addr, len) != len) break; addr += len; } if (archsw.arch_copyin("", addr, 1) != 1) break; last = ++addr; } if (archsw.arch_copyin("", last++, 1) != 1) last = start; return(last); } /* * Copy module-related data into the load area, where it can be * used as a directory for loaded modules. * * Module data is presented in a self-describing format. Each datum * is preceded by a 32-bit identifier and a 32-bit size field. * * Currently, the following data are saved: * * MOD_NAME (variable) module name (string) * MOD_TYPE (variable) module type (string) * MOD_ARGS (variable) module parameters (string) * MOD_ADDR sizeof(vm_offset_t) module load address * MOD_SIZE sizeof(size_t) module size * MOD_METADATA (variable) type-specific metadata */ #define COPY32(v, a, c) { \ uint32_t x = (v); \ if (c) \ archsw.arch_copyin(&x, a, sizeof(x)); \ a += sizeof(x); \ } #define MOD_STR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(strlen(s) + 1, a, c); \ if (c) \ archsw.arch_copyin(s, a, strlen(s) + 1); \ a += roundup(strlen(s) + 1, sizeof(u_long)); \ } #define MOD_NAME(a, s, c) MOD_STR(MODINFO_NAME, a, s, c) #define MOD_TYPE(a, s, c) MOD_STR(MODINFO_TYPE, a, s, c) #define MOD_ARGS(a, s, c) MOD_STR(MODINFO_ARGS, a, s, c) #define MOD_VAR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(sizeof(s), a, c); \ if (c) \ archsw.arch_copyin(&s, a, sizeof(s)); \ a += roundup(sizeof(s), sizeof(u_long)); \ } #define MOD_ADDR(a, s, c) MOD_VAR(MODINFO_ADDR, a, s, c) #define MOD_SIZE(a, s, c) MOD_VAR(MODINFO_SIZE, a, s, c) #define MOD_METADATA(a, mm, c) { \ COPY32(MODINFO_METADATA | mm->md_type, a, c); \ COPY32(mm->md_size, a, c); \ if (c) \ archsw.arch_copyin(mm->md_data, a, mm->md_size); \ a += roundup(mm->md_size, sizeof(u_long)); \ } #define MOD_END(a, c) { \ COPY32(MODINFO_END, a, c); \ COPY32(0, a, c); \ } static vm_offset_t bi_copymodules(vm_offset_t addr) { struct preloaded_file *fp; struct file_metadata *md; int c; uint64_t v; c = addr != 0; /* Start with the first module on the list, should be the kernel. */ for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) { MOD_NAME(addr, fp->f_name, c); /* This must come first. */ MOD_TYPE(addr, fp->f_type, c); if (fp->f_args) MOD_ARGS(addr, fp->f_args, c); v = fp->f_addr; #if defined(__arm__) v -= __elfN(relocation_offset); #endif MOD_ADDR(addr, v, c); v = fp->f_size; MOD_SIZE(addr, v, c); for (md = fp->f_metadata; md != NULL; md = md->md_next) if (!(md->md_type & MODINFOMD_NOCOPY)) MOD_METADATA(addr, md, c); } MOD_END(addr, c); return(addr); } static int bi_add_efi_data_and_exit(struct preloaded_file *kfp, struct efi_map_header *efihdr, size_t efisz, EFI_MEMORY_DESCRIPTOR *mm, UINTN sz) { UINTN efi_mapkey; UINTN mmsz; UINT32 mmver; EFI_STATUS status; UINTN retry; /* * It is possible that the first call to ExitBootServices may change * the map key. Fetch a new map key and retry ExitBootServices in that * case. */ for (retry = 2; retry > 0; retry--) { status = BS->GetMemoryMap(&sz, mm, &efi_mapkey, &mmsz, &mmver); if (EFI_ERROR(status)) { - printf("%s: GetMemoryMap() returned 0x%lx\n", __func__, - (long)status); + printf("%s: GetMemoryMap error %lu\n", __func__, + (unsigned long)(status & ~EFI_ERROR_MASK)); return (EINVAL); } status = BS->ExitBootServices(IH, efi_mapkey); if (EFI_ERROR(status) == 0) { efihdr->memory_size = sz; efihdr->descriptor_size = mmsz; efihdr->descriptor_version = mmver; file_addmetadata(kfp, MODINFOMD_EFI_MAP, efisz + sz, efihdr); return (0); } } - printf("ExitBootServices() returned 0x%lx\n", (long)status); + printf("ExitBootServices error %lu\n", + (unsigned long)(status & ~EFI_ERROR_MASK)); return (EINVAL); } static int bi_load_efi_data(struct preloaded_file *kfp) { EFI_MEMORY_DESCRIPTOR *mm; EFI_PHYSICAL_ADDRESS addr; EFI_STATUS status; size_t efisz; UINTN efi_mapkey; UINTN mmsz, pages, sz; UINT32 mmver; struct efi_map_header *efihdr; #if defined(__amd64__) struct efi_fb efifb; if (efi_find_framebuffer(&efifb) == 0) { printf("EFI framebuffer information:\n"); printf("addr, size 0x%lx, 0x%lx\n", efifb.fb_addr, efifb.fb_size); printf("dimensions %d x %d\n", efifb.fb_width, efifb.fb_height); printf("stride %d\n", efifb.fb_stride); printf("masks 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", efifb.fb_mask_red, efifb.fb_mask_green, efifb.fb_mask_blue, efifb.fb_mask_reserved); file_addmetadata(kfp, MODINFOMD_EFI_FB, sizeof(efifb), &efifb); } #endif efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf; /* * Allocate enough pages to hold the bootinfo block and the memory * map EFI will return to us. The memory map has an unknown size, * so we have to determine that first. Note that the AllocatePages * call can itself modify the memory map, so we have to take that * into account as well. The changes to the memory map are caused * by splitting a range of free memory into two (AFAICT), so that * one is marked as being loader data. */ sz = 0; BS->GetMemoryMap(&sz, NULL, &efi_mapkey, &mmsz, &mmver); sz += mmsz; sz = (sz + 0xf) & ~0xf; pages = EFI_SIZE_TO_PAGES(sz + efisz); status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, pages, &addr); if (EFI_ERROR(status)) { - printf("%s: AllocatePages() returned 0x%lx\n", __func__, - (long)status); + printf("%s: AllocatePages error %lu\n", __func__, + (unsigned long)(status & ~EFI_ERROR_MASK)); return (ENOMEM); } /* * Read the memory map and stash it after bootinfo. Align the * memory map on a 16-byte boundary (the bootinfo block is page * aligned). */ efihdr = (struct efi_map_header *)addr; mm = (void *)((uint8_t *)efihdr + efisz); sz = (EFI_PAGE_SIZE * pages) - efisz; return (bi_add_efi_data_and_exit(kfp, efihdr, efisz, mm, sz)); } /* * Load the information expected by an amd64 kernel. * * - The 'boothowto' argument is constructed. * - The 'bootdev' argument is constructed. * - The 'bootinfo' struct is constructed, and copied into the kernel space. * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp) { struct preloaded_file *xp, *kfp; struct devdesc *rootdev; struct file_metadata *md; vm_offset_t addr; uint64_t kernend; uint64_t envp; vm_offset_t size; char *rootdevname; int howto; #if defined(LOADER_FDT_SUPPORT) vm_offset_t dtbp; int dtb_size; #endif #if defined(__arm__) vm_offset_t vaddr; int i; /* * These metadata addreses must be converted for kernel after * relocation. */ uint32_t mdt[] = { MODINFOMD_SSYM, MODINFOMD_ESYM, MODINFOMD_KERNEND, MODINFOMD_ENVP, #if defined(LOADER_FDT_SUPPORT) MODINFOMD_DTBP #endif }; #endif howto = bi_getboothowto(args); /* * Allow the environment variable 'rootdev' to override the supplied * device. This should perhaps go to MI code and/or have $rootdev * tested/set by MI code before launching the kernel. */ rootdevname = getenv("rootdev"); archsw.arch_getdev((void**)(&rootdev), rootdevname, NULL); if (rootdev == NULL) { printf("Can't determine root device.\n"); return(EINVAL); } /* Try reading the /etc/fstab file to select the root device */ getrootmount(efi_fmtdev((void *)rootdev)); addr = 0; for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { if (addr < (xp->f_addr + xp->f_size)) addr = xp->f_addr + xp->f_size; } /* Pad to a page boundary. */ addr = roundup(addr, PAGE_SIZE); /* Copy our environment. */ envp = addr; addr = bi_copyenv(addr); /* Pad to a page boundary. */ addr = roundup(addr, PAGE_SIZE); #if defined(LOADER_FDT_SUPPORT) /* Handle device tree blob */ dtbp = addr; dtb_size = fdt_copy(addr); /* Pad to a page boundary */ if (dtb_size) addr += roundup(dtb_size, PAGE_SIZE); #endif kfp = file_findfile(NULL, "elf kernel"); if (kfp == NULL) kfp = file_findfile(NULL, "elf64 kernel"); if (kfp == NULL) panic("can't find kernel file"); kernend = 0; /* fill it in later */ file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); #if defined(LOADER_FDT_SUPPORT) if (dtb_size) file_addmetadata(kfp, MODINFOMD_DTBP, sizeof dtbp, &dtbp); else pager_output("WARNING! Trying to fire up the kernel, but no " "device tree blob found!\n"); #endif file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); bi_load_efi_data(kfp); /* Figure out the size and location of the metadata. */ *modulep = addr; size = bi_copymodules(0); kernend = roundup(addr + size, PAGE_SIZE); *kernendp = kernend; /* patch MODINFOMD_KERNEND */ md = file_findmetadata(kfp, MODINFOMD_KERNEND); bcopy(&kernend, md->md_data, sizeof kernend); #if defined(__arm__) *modulep -= __elfN(relocation_offset); /* Do relocation fixup on metadata of each module. */ for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { for (i = 0; i < sizeof mdt / sizeof mdt[0]; i++) { md = file_findmetadata(xp, mdt[i]); if (md) { bcopy(md->md_data, &vaddr, sizeof vaddr); vaddr -= __elfN(relocation_offset); bcopy(&vaddr, md->md_data, sizeof vaddr); } } } #endif /* Copy module list and metadata. */ (void)bi_copymodules(addr); return (0); } Index: user/alc/PQ_LAUNDRY/sys/boot =================================================================== --- user/alc/PQ_LAUNDRY/sys/boot (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/boot (revision 292449) Property changes on: user/alc/PQ_LAUNDRY/sys/boot ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/sys/boot:r292390-292448 Index: user/alc/PQ_LAUNDRY/sys/conf/files.arm =================================================================== --- user/alc/PQ_LAUNDRY/sys/conf/files.arm (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/conf/files.arm (revision 292449) @@ -1,136 +1,137 @@ # $FreeBSD$ arm/arm/autoconf.c standard arm/arm/bcopy_page.S standard arm/arm/bcopyinout.S standard arm/arm/blockio.S standard arm/arm/bus_space_asm_generic.S standard arm/arm/bus_space_base.c optional fdt arm/arm/bus_space_generic.c standard arm/arm/busdma_machdep.c optional !armv6 arm/arm/busdma_machdep-v6.c optional armv6 arm/arm/copystr.S standard arm/arm/cpufunc.c standard arm/arm/cpufunc_asm.S standard arm/arm/cpufunc_asm_arm9.S optional cpu_arm9 arm/arm/cpufunc_asm_arm10.S optional cpu_arm9e arm/arm/cpufunc_asm_arm11.S optional cpu_arm1176 arm/arm/cpufunc_asm_arm11x6.S optional cpu_arm1176 arm/arm/cpufunc_asm_armv4.S optional cpu_arm9 | cpu_arm9e | cpu_fa526 | cpu_xscale_80321 | cpu_xscale_pxa2x0 | cpu_xscale_ixp425 | cpu_xscale_80219 | cpu_xscale_81342 arm/arm/cpufunc_asm_armv5_ec.S optional cpu_arm9e arm/arm/cpufunc_asm_armv6.S optional cpu_arm1176 arm/arm/cpufunc_asm_armv7.S optional cpu_cortexa | cpu_krait | cpu_mv_pj4b arm/arm/cpufunc_asm_fa526.S optional cpu_fa526 arm/arm/cpufunc_asm_pj4b.S optional cpu_mv_pj4b arm/arm/cpufunc_asm_sheeva.S optional cpu_arm9e arm/arm/cpufunc_asm_xscale.S optional cpu_xscale_80321 | cpu_xscale_pxa2x0 | cpu_xscale_ixp425 | cpu_xscale_80219 | cpu_xscale_81342 arm/arm/cpufunc_asm_xscale_c3.S optional cpu_xscale_81342 arm/arm/cpuinfo.c standard arm/arm/cpu_asm-v6.S optional armv6 arm/arm/db_disasm.c optional ddb arm/arm/db_interface.c optional ddb arm/arm/db_trace.c optional ddb arm/arm/devmap.c standard arm/arm/disassem.c optional ddb arm/arm/dump_machdep.c standard arm/arm/elf_machdep.c standard arm/arm/elf_note.S standard arm/arm/exception.S standard arm/arm/fiq.c standard arm/arm/fiq_subr.S standard arm/arm/fusu.S standard arm/arm/gdb_machdep.c optional gdb arm/arm/generic_timer.c optional generic_timer arm/arm/gic.c optional gic arm/arm/hdmi_if.m optional hdmi arm/arm/identcpu.c standard arm/arm/in_cksum.c optional inet | inet6 arm/arm/in_cksum_arm.S optional inet | inet6 arm/arm/intr.c optional !arm_intrng -arm/arm/intrng.c optional arm_intrng +kern/subr_intr.c optional arm_intrng arm/arm/locore.S standard no-obj arm/arm/machdep.c standard +arm/arm/machdep_intr.c standard arm/arm/mem.c optional mem arm/arm/minidump_machdep.c optional mem arm/arm/mp_machdep.c optional smp arm/arm/mpcore_timer.c optional mpcore_timer arm/arm/nexus.c standard arm/arm/physmem.c standard -arm/arm/pic_if.m optional arm_intrng +kern/pic_if.m optional arm_intrng arm/arm/pl190.c optional pl190 arm/arm/pl310.c optional pl310 arm/arm/platform.c optional platform arm/arm/platform_if.m optional platform arm/arm/pmap.c optional !armv6 arm/arm/pmap-v6.c optional armv6 !arm_new_pmap arm/arm/pmap-v6-new.c optional armv6 arm_new_pmap arm/arm/pmu.c optional pmu | fdt hwpmc arm/arm/sc_machdep.c optional sc arm/arm/setcpsr.S standard arm/arm/setstack.s standard arm/arm/stack_machdep.c optional ddb | stack arm/arm/stdatomic.c standard \ compile-with "${NORMAL_C:N-Wmissing-prototypes}" arm/arm/support.S standard arm/arm/swtch.S standard arm/arm/sys_machdep.c standard arm/arm/syscall.c standard arm/arm/trap.c optional !armv6 arm/arm/trap-v6.c optional armv6 arm/arm/uio_machdep.c standard arm/arm/undefined.c standard arm/arm/unwind.c optional ddb | kdtrace_hooks arm/arm/vm_machdep.c standard arm/arm/vfp.c standard board_id.h standard \ dependency "$S/arm/conf/genboardid.awk $S/arm/conf/mach-types" \ compile-with "${AWK} -f $S/arm/conf/genboardid.awk $S/arm/conf/mach-types > board_id.h" \ no-obj no-implicit-rule before-depend \ clean "board_id.h" cddl/compat/opensolaris/kern/opensolaris_atomic.c optional zfs | dtrace compile-with "${CDDL_C}" cddl/dev/dtrace/arm/dtrace_asm.S optional dtrace compile-with "${DTRACE_S}" cddl/dev/dtrace/arm/dtrace_subr.c optional dtrace compile-with "${DTRACE_C}" cddl/dev/fbt/arm/fbt_isa.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}" crypto/blowfish/bf_enc.c optional crypto | ipsec crypto/des/des_enc.c optional crypto | ipsec | netsmb dev/dwc/if_dwc.c optional dwc dev/dwc/if_dwc_if.m optional dwc dev/fb/fb.c optional sc dev/fdt/fdt_arm_platform.c optional platform fdt dev/hwpmc/hwpmc_arm.c optional hwpmc dev/hwpmc/hwpmc_armv7.c optional hwpmc armv6 dev/psci/psci.c optional psci dev/psci/psci_arm.S optional psci dev/syscons/scgfbrndr.c optional sc dev/syscons/scterm-teken.c optional sc dev/syscons/scvtb.c optional sc dev/uart/uart_cpu_fdt.c optional uart fdt font.h optional sc \ compile-with "uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x16.fnt && file2c 'u_char dflt_font_16[16*256] = {' '};' < ${SC_DFLT_FONT}-8x16 > font.h && uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x14.fnt && file2c 'u_char dflt_font_14[14*256] = {' '};' < ${SC_DFLT_FONT}-8x14 >> font.h && uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x8.fnt && file2c 'u_char dflt_font_8[8*256] = {' '};' < ${SC_DFLT_FONT}-8x8 >> font.h" \ no-obj no-implicit-rule before-depend \ clean "font.h ${SC_DFLT_FONT}-8x14 ${SC_DFLT_FONT}-8x16 ${SC_DFLT_FONT}-8x8" kern/subr_busdma_bufalloc.c standard kern/subr_sfbuf.c standard libkern/arm/aeabi_unwind.c standard libkern/arm/divsi3.S standard libkern/arm/ffs.S standard libkern/arm/ldivmod.S standard libkern/arm/ldivmod_helper.c standard libkern/arm/memclr.S standard libkern/arm/memcpy.S standard libkern/arm/memset.S standard libkern/arm/muldi3.c standard libkern/ashldi3.c standard libkern/ashrdi3.c standard libkern/divdi3.c standard libkern/ffsl.c standard libkern/ffsll.c standard libkern/fls.c standard libkern/flsl.c standard libkern/flsll.c standard libkern/lshrdi3.c standard libkern/moddi3.c standard libkern/qdivrem.c standard libkern/ucmpdi2.c standard libkern/udivdi3.c standard libkern/umoddi3.c standard Index: user/alc/PQ_LAUNDRY/sys/conf =================================================================== --- user/alc/PQ_LAUNDRY/sys/conf (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/conf (revision 292449) Property changes on: user/alc/PQ_LAUNDRY/sys/conf ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/sys/conf:r292390-292448 Index: user/alc/PQ_LAUNDRY/sys/dev/drm2/i915/intel_iic.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/dev/drm2/i915/intel_iic.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/dev/drm2/i915/intel_iic.c (revision 292449) @@ -1,768 +1,768 @@ /* * Copyright (c) 2006 Dave Airlie * Copyright © 2006-2008,2010 Intel Corporation * Jesse Barnes * * 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 (including the next * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Eric Anholt * Chris Wilson * * Copyright (c) 2011 The FreeBSD Foundation * All rights reserved. * * This software was developed by Konstantin Belousov under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include "iicbus_if.h" #include "iicbb_if.h" static void intel_teardown_gmbus_m(struct drm_device *dev, int m); struct gmbus_port { const char *name; int reg; }; static const struct gmbus_port gmbus_ports[] = { { "ssc", GPIOB }, { "vga", GPIOA }, { "panel", GPIOC }, { "dpc", GPIOD }, { "dpb", GPIOE }, { "dpd", GPIOF }, }; /* Intel GPIO access functions */ #define I2C_RISEFALL_TIME 10 struct intel_iic_softc { struct drm_device *drm_dev; device_t iic_dev; bool force_bit_dev; char name[32]; uint32_t reg; uint32_t reg0; }; void intel_iic_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; I915_WRITE(dev_priv->gpio_mmio_base + GMBUS0, 0); } static int intel_iicbus_reset(device_t idev, u_char speed, u_char addr, u_char *oldaddr) { struct intel_iic_softc *sc; struct drm_device *dev; sc = device_get_softc(idev); dev = sc->drm_dev; intel_iic_reset(dev); return (0); } static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable) { u32 val; /* When using bit bashing for I2C, this bit needs to be set to 1 */ if (!IS_PINEVIEW(dev_priv->dev)) return; val = I915_READ(DSPCLK_GATE_D); if (enable) val |= DPCUNIT_CLOCK_GATE_DISABLE; else val &= ~DPCUNIT_CLOCK_GATE_DISABLE; I915_WRITE(DSPCLK_GATE_D, val); } static u32 get_reserved(device_t idev) { struct intel_iic_softc *sc = device_get_softc(idev); struct drm_device *dev = sc->drm_dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 reserved = 0; if (!IS_I830(dev) && !IS_845G(dev)) reserved = I915_READ_NOTRACE(sc->reg) & (GPIO_DATA_PULLUP_DISABLE | GPIO_CLOCK_PULLUP_DISABLE); return reserved; } static int get_clock(device_t adapter) { struct intel_iic_softc *sc = device_get_softc(adapter); struct drm_i915_private *dev_priv = sc->drm_dev->dev_private; u32 reserved = get_reserved(adapter); I915_WRITE_NOTRACE(sc->reg, reserved | GPIO_CLOCK_DIR_MASK); I915_WRITE_NOTRACE(sc->reg, reserved); return ((I915_READ_NOTRACE(sc->reg) & GPIO_CLOCK_VAL_IN) != 0); } static int get_data(device_t adapter) { struct intel_iic_softc *sc = device_get_softc(adapter); struct drm_i915_private *dev_priv = sc->drm_dev->dev_private; u32 reserved = get_reserved(adapter); I915_WRITE_NOTRACE(sc->reg, reserved | GPIO_DATA_DIR_MASK); I915_WRITE_NOTRACE(sc->reg, reserved); return ((I915_READ_NOTRACE(sc->reg) & GPIO_DATA_VAL_IN) != 0); } static void set_clock(device_t adapter, int state_high) { struct intel_iic_softc *sc = device_get_softc(adapter); struct drm_i915_private *dev_priv = sc->drm_dev->dev_private; u32 reserved = get_reserved(adapter); u32 clock_bits; if (state_high) clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK; else clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_VAL_MASK; I915_WRITE_NOTRACE(sc->reg, reserved | clock_bits); POSTING_READ(sc->reg); } static void set_data(device_t adapter, int state_high) { struct intel_iic_softc *sc = device_get_softc(adapter); struct drm_i915_private *dev_priv = sc->drm_dev->dev_private; u32 reserved = get_reserved(adapter); u32 data_bits; if (state_high) data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK; else data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | GPIO_DATA_VAL_MASK; I915_WRITE_NOTRACE(sc->reg, reserved | data_bits); POSTING_READ(sc->reg); } static int intel_gpio_pre_xfer(device_t adapter) { struct intel_iic_softc *sc = device_get_softc(adapter); struct drm_i915_private *dev_priv = sc->drm_dev->dev_private; intel_iic_reset(sc->drm_dev); intel_i2c_quirk_set(dev_priv, true); IICBB_SETSDA(adapter, 1); IICBB_SETSCL(adapter, 1); DELAY(I2C_RISEFALL_TIME); return 0; } static void intel_gpio_post_xfer(device_t adapter) { struct intel_iic_softc *sc = device_get_softc(adapter); struct drm_i915_private *dev_priv = sc->drm_dev->dev_private; IICBB_SETSDA(adapter, 1); IICBB_SETSCL(adapter, 1); intel_i2c_quirk_set(dev_priv, false); } static int gmbus_xfer_read(struct drm_i915_private *dev_priv, struct iic_msg *msg, u32 gmbus1_index) { int reg_offset = dev_priv->gpio_mmio_base; u16 len = msg->len; u8 *buf = msg->buf; I915_WRITE(GMBUS1 + reg_offset, gmbus1_index | GMBUS_CYCLE_WAIT | (len << GMBUS_BYTE_COUNT_SHIFT) | (msg->slave << (GMBUS_SLAVE_ADDR_SHIFT - 1)) | GMBUS_SLAVE_READ | GMBUS_SW_RDY); while (len) { int ret; u32 val, loop = 0; u32 gmbus2; ret = _intel_wait_for(sc->drm_dev, ((gmbus2 = I915_READ(GMBUS2 + reg_offset)) & (GMBUS_SATOER | GMBUS_HW_RDY)), 50, 1, "915gbr"); if (ret) return -ETIMEDOUT; if (gmbus2 & GMBUS_SATOER) return -ENXIO; val = I915_READ(GMBUS3 + reg_offset); do { *buf++ = val & 0xff; val >>= 8; } while (--len && ++loop < 4); } return 0; } static int gmbus_xfer_write(struct drm_i915_private *dev_priv, struct iic_msg *msg) { int reg_offset = dev_priv->gpio_mmio_base; u16 len = msg->len; u8 *buf = msg->buf; u32 val, loop; val = loop = 0; while (len && loop < 4) { val |= *buf++ << (8 * loop++); len -= 1; } I915_WRITE(GMBUS3 + reg_offset, val); I915_WRITE(GMBUS1 + reg_offset, GMBUS_CYCLE_WAIT | (msg->len << GMBUS_BYTE_COUNT_SHIFT) | (msg->slave << (GMBUS_SLAVE_ADDR_SHIFT - 1)) | GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); while (len) { int ret; u32 gmbus2; val = loop = 0; do { val |= *buf++ << (8 * loop); } while (--len && ++loop < 4); I915_WRITE(GMBUS3 + reg_offset, val); ret = _intel_wait_for(sc->drm_dev, ((gmbus2 = I915_READ(GMBUS2 + reg_offset)) & (GMBUS_SATOER | GMBUS_HW_RDY)), 50, 1, "915gbw"); if (ret) return -ETIMEDOUT; if (gmbus2 & GMBUS_SATOER) return -ENXIO; } return 0; } /* * The gmbus controller can combine a 1 or 2 byte write with a read that * immediately follows it by using an "INDEX" cycle. */ static bool gmbus_is_index_read(struct iic_msg *msgs, int i, int num) { return (i + 1 < num && !(msgs[i].flags & IIC_M_RD) && msgs[i].len <= 2 && (msgs[i + 1].flags & IIC_M_RD)); } static int gmbus_xfer_index_read(struct drm_i915_private *dev_priv, struct iic_msg *msgs) { int reg_offset = dev_priv->gpio_mmio_base; u32 gmbus1_index = 0; u32 gmbus5 = 0; int ret; if (msgs[0].len == 2) gmbus5 = GMBUS_2BYTE_INDEX_EN | msgs[0].buf[1] | (msgs[0].buf[0] << 8); if (msgs[0].len == 1) gmbus1_index = GMBUS_CYCLE_INDEX | (msgs[0].buf[0] << GMBUS_SLAVE_INDEX_SHIFT); /* GMBUS5 holds 16-bit index */ if (gmbus5) I915_WRITE(GMBUS5 + reg_offset, gmbus5); ret = gmbus_xfer_read(dev_priv, &msgs[1], gmbus1_index); /* Clear GMBUS5 after each index transfer */ if (gmbus5) I915_WRITE(GMBUS5 + reg_offset, 0); return ret; } static int gmbus_xfer(device_t adapter, struct iic_msg *msgs, uint32_t num) { struct intel_iic_softc *sc = device_get_softc(adapter); struct drm_i915_private *dev_priv = sc->drm_dev->dev_private; int error, i, ret, reg_offset, unit; error = 0; unit = device_get_unit(adapter); sx_xlock(&dev_priv->gmbus_sx); if (sc->force_bit_dev) { error = -IICBUS_TRANSFER(dev_priv->bbbus[unit], msgs, num); goto out; } reg_offset = dev_priv->gpio_mmio_base; I915_WRITE(GMBUS0 + reg_offset, sc->reg0); for (i = 0; i < num; i++) { u32 gmbus2; if (gmbus_is_index_read(msgs, i, num)) { error = gmbus_xfer_index_read(dev_priv, &msgs[i]); i += 1; /* set i to the index of the read xfer */ } else if (msgs[i].flags & IIC_M_RD) { error = gmbus_xfer_read(dev_priv, &msgs[i], 0); } else { error = gmbus_xfer_write(dev_priv, &msgs[i]); } if (error == -ETIMEDOUT) goto timeout; if (error == -ENXIO) goto clear_err; ret = _intel_wait_for(sc->drm_dev, ((gmbus2 = I915_READ(GMBUS2 + reg_offset)) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE)), 50, 1, "915gbh"); if (ret) goto timeout; if (gmbus2 & GMBUS_SATOER) goto clear_err; } /* Generate a STOP condition on the bus. Note that gmbus can't generata * a STOP on the very first cycle. To simplify the code we * unconditionally generate the STOP condition with an additional gmbus * cycle. */ I915_WRITE(GMBUS1 + reg_offset, GMBUS_CYCLE_STOP | GMBUS_SW_RDY); /* Mark the GMBUS interface as disabled after waiting for idle. * We will re-enable it at the start of the next xfer, * till then let it sleep. */ if (_intel_wait_for(dev, (I915_READ(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0, 10, 1, "915gbu")) { DRM_DEBUG_KMS("GMBUS [%s] timed out waiting for idle\n", sc->name); error = -ETIMEDOUT; } I915_WRITE(GMBUS0 + reg_offset, 0); goto out; clear_err: /* * Wait for bus to IDLE before clearing NAK. * If we clear the NAK while bus is still active, then it will stay * active and the next transaction may fail. */ if (_intel_wait_for(dev, (I915_READ(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0, 10, 1, "915gbu")) DRM_DEBUG_KMS("GMBUS [%s] timed out after NAK\n", sc->name); /* Toggle the Software Clear Interrupt bit. This has the effect * of resetting the GMBUS controller and so clearing the * BUS_ERROR raised by the slave's NAK. */ I915_WRITE(GMBUS1 + reg_offset, GMBUS_SW_CLR_INT); I915_WRITE(GMBUS1 + reg_offset, 0); I915_WRITE(GMBUS0 + reg_offset, 0); DRM_DEBUG_KMS("GMBUS [%s] NAK for addr: %04x %c(%d)\n", sc->name, msgs[i].slave, (msgs[i].flags & IIC_M_RD) ? 'r' : 'w', msgs[i].len); /* * If no ACK is received during the address phase of a transaction, * the adapter must report -ENXIO. * It is not clear what to return if no ACK is received at other times. * So, we always return -ENXIO in all NAK cases, to ensure we send * it at least during the one case that is specified. */ error = -ENXIO; goto out; timeout: DRM_INFO("GMBUS [%s] timed out, falling back to bit banging on pin %d\n", sc->name, sc->reg0 & 0xff); I915_WRITE(GMBUS0 + reg_offset, 0); /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */ sc->force_bit_dev = true; - error = -IICBUS_TRANSFER(adapter, msgs, num); + error = -IICBUS_TRANSFER(dev_priv->bbbus[unit], msgs, num); out: sx_xunlock(&dev_priv->gmbus_sx); return -error; } static int intel_gmbus_probe(device_t dev) { return (BUS_PROBE_SPECIFIC); } static int intel_gmbus_attach(device_t idev) { struct drm_i915_private *dev_priv; struct intel_iic_softc *sc; int pin, port; sc = device_get_softc(idev); sc->drm_dev = device_get_softc(device_get_parent(idev)); dev_priv = sc->drm_dev->dev_private; pin = device_get_unit(idev); port = pin + 1; snprintf(sc->name, sizeof(sc->name), "gmbus %s", intel_gmbus_is_port_valid(port) ? gmbus_ports[pin].name : "reserved"); device_set_desc(idev, sc->name); /* By default use a conservative clock rate */ sc->reg0 = port | GMBUS_RATE_100KHZ; /* gmbus seems to be broken on i830 */ if (IS_I830(sc->drm_dev)) sc->force_bit_dev = true; #if 0 if (IS_GEN2(sc->drm_dev)) { sc->force_bit_dev = true; } #endif /* add bus interface device */ sc->iic_dev = device_add_child(idev, "iicbus", -1); if (sc->iic_dev == NULL) return (ENXIO); device_quiet(sc->iic_dev); bus_generic_attach(idev); return (0); } static int intel_gmbus_detach(device_t idev) { struct intel_iic_softc *sc; struct drm_i915_private *dev_priv; device_t child; int u; sc = device_get_softc(idev); u = device_get_unit(idev); dev_priv = sc->drm_dev->dev_private; child = sc->iic_dev; bus_generic_detach(idev); if (child != NULL) device_delete_child(idev, child); return (0); } static int intel_iicbb_probe(device_t dev) { return (BUS_PROBE_DEFAULT); } static int intel_iicbb_attach(device_t idev) { struct intel_iic_softc *sc; struct drm_i915_private *dev_priv; int pin, port; sc = device_get_softc(idev); sc->drm_dev = device_get_softc(device_get_parent(idev)); dev_priv = sc->drm_dev->dev_private; pin = device_get_unit(idev); port = pin + 1; snprintf(sc->name, sizeof(sc->name), "i915 iicbb %s", intel_gmbus_is_port_valid(port) ? gmbus_ports[pin].name : "reserved"); device_set_desc(idev, sc->name); if (!intel_gmbus_is_port_valid(port)) pin = 1 ; /* GPIOA, VGA */ sc->reg0 = pin | GMBUS_RATE_100KHZ; sc->reg = dev_priv->gpio_mmio_base + gmbus_ports[pin].reg; /* add generic bit-banging code */ sc->iic_dev = device_add_child(idev, "iicbb", -1); if (sc->iic_dev == NULL) return (ENXIO); device_quiet(sc->iic_dev); bus_generic_attach(idev); iicbus_set_nostop(idev, true); return (0); } static int intel_iicbb_detach(device_t idev) { struct intel_iic_softc *sc; device_t child; sc = device_get_softc(idev); child = sc->iic_dev; bus_generic_detach(idev); if (child) device_delete_child(idev, child); return (0); } static device_method_t intel_gmbus_methods[] = { DEVMETHOD(device_probe, intel_gmbus_probe), DEVMETHOD(device_attach, intel_gmbus_attach), DEVMETHOD(device_detach, intel_gmbus_detach), DEVMETHOD(iicbus_reset, intel_iicbus_reset), DEVMETHOD(iicbus_transfer, gmbus_xfer), DEVMETHOD_END }; static driver_t intel_gmbus_driver = { "intel_gmbus", intel_gmbus_methods, sizeof(struct intel_iic_softc) }; static devclass_t intel_gmbus_devclass; DRIVER_MODULE_ORDERED(intel_gmbus, drmn, intel_gmbus_driver, intel_gmbus_devclass, 0, 0, SI_ORDER_FIRST); DRIVER_MODULE(iicbus, intel_gmbus, iicbus_driver, iicbus_devclass, 0, 0); static device_method_t intel_iicbb_methods[] = { DEVMETHOD(device_probe, intel_iicbb_probe), DEVMETHOD(device_attach, intel_iicbb_attach), DEVMETHOD(device_detach, intel_iicbb_detach), DEVMETHOD(bus_add_child, bus_generic_add_child), DEVMETHOD(bus_print_child, bus_generic_print_child), DEVMETHOD(iicbb_callback, iicbus_null_callback), DEVMETHOD(iicbb_reset, intel_iicbus_reset), DEVMETHOD(iicbb_setsda, set_data), DEVMETHOD(iicbb_setscl, set_clock), DEVMETHOD(iicbb_getsda, get_data), DEVMETHOD(iicbb_getscl, get_clock), DEVMETHOD(iicbb_pre_xfer, intel_gpio_pre_xfer), DEVMETHOD(iicbb_post_xfer, intel_gpio_post_xfer), DEVMETHOD_END }; static driver_t intel_iicbb_driver = { "intel_iicbb", intel_iicbb_methods, sizeof(struct intel_iic_softc) }; static devclass_t intel_iicbb_devclass; DRIVER_MODULE_ORDERED(intel_iicbb, drmn, intel_iicbb_driver, intel_iicbb_devclass, 0, 0, SI_ORDER_FIRST); DRIVER_MODULE(iicbb, intel_iicbb, iicbb_driver, iicbb_devclass, 0, 0); int intel_setup_gmbus(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; device_t iic_dev; int ret, i; if (HAS_PCH_SPLIT(dev)) dev_priv->gpio_mmio_base = PCH_GPIOA - GPIOA; else dev_priv->gpio_mmio_base = 0; sx_init(&dev_priv->gmbus_sx, "gmbus"); /* * The Giant there is recursed, most likely. Normally, the * intel_setup_gmbus() is called from the attach method of the * driver. */ mtx_lock(&Giant); for (i = 0; i <= GMBUS_NUM_PORTS; i++) { /* * Initialized bbbus_bridge before gmbus_bridge, since * gmbus may decide to force quirk transfer in the * attachment code. */ dev_priv->bbbus_bridge[i] = device_add_child(dev->dev, "intel_iicbb", i); if (dev_priv->bbbus_bridge[i] == NULL) { DRM_ERROR("bbbus bridge %d creation failed\n", i); ret = -ENXIO; goto err; } device_quiet(dev_priv->bbbus_bridge[i]); ret = -device_probe_and_attach(dev_priv->bbbus_bridge[i]); if (ret != 0) { DRM_ERROR("bbbus bridge %d attach failed, %d\n", i, ret); goto err; } iic_dev = device_find_child(dev_priv->bbbus_bridge[i], "iicbb", -1); if (iic_dev == NULL) { DRM_ERROR("bbbus bridge doesn't have iicbb child\n"); goto err; } iic_dev = device_find_child(iic_dev, "iicbus", -1); if (iic_dev == NULL) { DRM_ERROR( "bbbus bridge doesn't have iicbus grandchild\n"); goto err; } dev_priv->bbbus[i] = iic_dev; dev_priv->gmbus_bridge[i] = device_add_child(dev->dev, "intel_gmbus", i); if (dev_priv->gmbus_bridge[i] == NULL) { DRM_ERROR("gmbus bridge %d creation failed\n", i); ret = -ENXIO; goto err; } device_quiet(dev_priv->gmbus_bridge[i]); ret = -device_probe_and_attach(dev_priv->gmbus_bridge[i]); if (ret != 0) { DRM_ERROR("gmbus bridge %d attach failed, %d\n", i, ret); ret = -ENXIO; goto err; } iic_dev = device_find_child(dev_priv->gmbus_bridge[i], "iicbus", -1); if (iic_dev == NULL) { DRM_ERROR("gmbus bridge doesn't have iicbus child\n"); goto err; } dev_priv->gmbus[i] = iic_dev; intel_iic_reset(dev); } mtx_unlock(&Giant); return 0; err: intel_teardown_gmbus_m(dev, i); mtx_unlock(&Giant); return ret; } device_t intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned port) { if (!intel_gmbus_is_port_valid(port)) DRM_ERROR("GMBUS get adapter %d: invalid port\n", port); return (intel_gmbus_is_port_valid(port) ? dev_priv->gmbus[port - 1] : NULL); } void intel_gmbus_set_speed(device_t adapter, int speed) { struct intel_iic_softc *sc; sc = device_get_softc(device_get_parent(adapter)); sc->reg0 = (sc->reg0 & ~(0x3 << 8)) | speed; } void intel_gmbus_force_bit(device_t adapter, bool force_bit) { struct intel_iic_softc *sc; sc = device_get_softc(device_get_parent(adapter)); sc->force_bit_dev = force_bit; } static void intel_teardown_gmbus_m(struct drm_device *dev, int m) { struct drm_i915_private *dev_priv; dev_priv = dev->dev_private; sx_destroy(&dev_priv->gmbus_sx); } void intel_teardown_gmbus(struct drm_device *dev) { mtx_lock(&Giant); intel_teardown_gmbus_m(dev, GMBUS_NUM_PORTS); mtx_unlock(&Giant); } Index: user/alc/PQ_LAUNDRY/sys/dev/if_ndis/if_ndis_pci.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/dev/if_ndis/if_ndis_pci.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/dev/if_ndis/if_ndis_pci.c (revision 292449) @@ -1,353 +1,352 @@ /*- * Copyright (c) 2003 * Bill Paul . 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 Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include MODULE_DEPEND(ndis, pci, 1, 1, 1); static int ndis_probe_pci (device_t); static int ndis_attach_pci (device_t); static struct resource_list *ndis_get_resource_list (device_t, device_t); static int ndis_devcompare (interface_type, struct ndis_pci_type *, device_t); extern int ndisdrv_modevent (module_t, int, void *); extern int ndis_attach (device_t); extern int ndis_shutdown (device_t); extern int ndis_detach (device_t); extern int ndis_suspend (device_t); extern int ndis_resume (device_t); static device_method_t ndis_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ndis_probe_pci), DEVMETHOD(device_attach, ndis_attach_pci), DEVMETHOD(device_detach, ndis_detach), DEVMETHOD(device_shutdown, ndis_shutdown), DEVMETHOD(device_suspend, ndis_suspend), DEVMETHOD(device_resume, ndis_resume), /* Bus interface */ DEVMETHOD(bus_get_resource_list, ndis_get_resource_list), { 0, 0 } }; static driver_t ndis_driver = { "ndis", ndis_methods, sizeof(struct ndis_softc) }; static devclass_t ndis_devclass; DRIVER_MODULE(ndis, pci, ndis_driver, ndis_devclass, ndisdrv_modevent, 0); static int ndis_devcompare(bustype, t, dev) interface_type bustype; struct ndis_pci_type *t; device_t dev; { uint16_t vid, did; uint32_t subsys; if (bustype != PCIBus) return(FALSE); vid = pci_get_vendor(dev); did = pci_get_device(dev); subsys = pci_get_subdevice(dev); subsys = (subsys << 16) | pci_get_subvendor(dev); while(t->ndis_name != NULL) { if ((t->ndis_vid == vid) && (t->ndis_did == did) && (t->ndis_subsys == subsys || t->ndis_subsys == 0)) { device_set_desc(dev, t->ndis_name); return(TRUE); } t++; } return(FALSE); } /* * Probe for an NDIS device. Check the PCI vendor and device * IDs against our list and return a device name if we find a match. */ static int ndis_probe_pci(dev) device_t dev; { driver_object *drv; struct drvdb_ent *db; drv = windrv_lookup(0, "PCI Bus"); if (drv == NULL) return(ENXIO); db = windrv_match((matchfuncptr)ndis_devcompare, dev); if (db != NULL) { /* Create PDO for this device instance */ windrv_create_pdo(drv, dev); return(0); } return(ENXIO); } /* * Attach the interface. Allocate softc structures, do ifmedia * setup and ethernet/BPF attach. */ static int ndis_attach_pci(dev) device_t dev; { struct ndis_softc *sc; int unit, error = 0, rid; struct ndis_pci_type *t; int devidx = 0, defidx = 0; struct resource_list *rl; struct resource_list_entry *rle; struct drvdb_ent *db; uint16_t vid, did; uint32_t subsys; sc = device_get_softc(dev); unit = device_get_unit(dev); sc->ndis_dev = dev; db = windrv_match((matchfuncptr)ndis_devcompare, dev); if (db == NULL) return (ENXIO); sc->ndis_dobj = db->windrv_object; sc->ndis_regvals = db->windrv_regvals; /* * Map control/status registers. */ pci_enable_busmaster(dev); rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); if (rl != NULL) { STAILQ_FOREACH(rle, rl, link) { switch (rle->type) { case SYS_RES_IOPORT: sc->ndis_io_rid = rle->rid; sc->ndis_res_io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->ndis_io_rid, RF_ACTIVE); if (sc->ndis_res_io == NULL) { device_printf(dev, "couldn't map iospace\n"); error = ENXIO; goto fail; } break; case SYS_RES_MEMORY: if (sc->ndis_res_altmem != NULL && sc->ndis_res_mem != NULL) { device_printf(dev, "too many memory resources\n"); error = ENXIO; goto fail; } if (sc->ndis_res_mem) { sc->ndis_altmem_rid = rle->rid; sc->ndis_res_altmem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->ndis_altmem_rid, RF_ACTIVE); if (sc->ndis_res_altmem == NULL) { device_printf(dev, "couldn't map alt " "memory\n"); error = ENXIO; goto fail; } } else { sc->ndis_mem_rid = rle->rid; sc->ndis_res_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->ndis_mem_rid, RF_ACTIVE); if (sc->ndis_res_mem == NULL) { device_printf(dev, "couldn't map memory\n"); error = ENXIO; goto fail; } } break; case SYS_RES_IRQ: rid = rle->rid; sc->ndis_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); if (sc->ndis_irq == NULL) { device_printf(dev, "couldn't map interrupt\n"); error = ENXIO; goto fail; } break; default: break; } sc->ndis_rescnt++; } } /* * If the BIOS did not set up an interrupt for this device, * the resource traversal code above will fail to set up * an IRQ resource. This is usually a bad thing, so try to * force the allocation of an interrupt here. If one was * not assigned to us by the BIOS, bus_alloc_resource() * should route one for us. */ if (sc->ndis_irq == NULL) { rid = 0; sc->ndis_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); if (sc->ndis_irq == NULL) { device_printf(dev, "couldn't route interrupt\n"); error = ENXIO; goto fail; } sc->ndis_rescnt++; } /* * Allocate the parent bus DMA tag appropriate for PCI. */ #define NDIS_NSEG_NEW 32 error = bus_dma_tag_create(bus_get_dma_tag(dev),/* PCI parent */ 1, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ - BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ - NDIS_NSEG_NEW, /* nsegments */ + DFLTPHYS, NDIS_NSEG_NEW,/* maxsize, nsegments */ BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ BUS_DMA_ALLOCNOW, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->ndis_parent_tag); if (error) goto fail; sc->ndis_iftype = PCIBus; /* Figure out exactly which device we matched. */ vid = pci_get_vendor(dev); did = pci_get_device(dev); subsys = pci_get_subdevice(dev); subsys = (subsys << 16) | pci_get_subvendor(dev); t = db->windrv_devlist; while(t->ndis_name != NULL) { if (t->ndis_vid == vid && t->ndis_did == did) { if (t->ndis_subsys == 0) defidx = devidx; else if (t->ndis_subsys == subsys) break; } t++; devidx++; } if (t->ndis_name == NULL) sc->ndis_devidx = defidx; else sc->ndis_devidx = devidx; error = ndis_attach(dev); fail: return(error); } static struct resource_list * ndis_get_resource_list(dev, child) device_t dev; device_t child; { struct ndis_softc *sc; sc = device_get_softc(dev); return (BUS_GET_RESOURCE_LIST(device_get_parent(sc->ndis_dev), dev)); } Index: user/alc/PQ_LAUNDRY/sys/dev/ioat/ioat.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/dev/ioat/ioat.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/dev/ioat/ioat.c (revision 292449) @@ -1,1838 +1,1847 @@ /*- * Copyright (C) 2012 Intel Corporation * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ioat.h" #include "ioat_hw.h" #include "ioat_internal.h" #define IOAT_INTR_TIMO (hz / 10) #define IOAT_REFLK (&ioat->submit_lock) static int ioat_probe(device_t device); static int ioat_attach(device_t device); static int ioat_detach(device_t device); static int ioat_setup_intr(struct ioat_softc *ioat); static int ioat_teardown_intr(struct ioat_softc *ioat); static int ioat3_attach(device_t device); static int ioat_start_channel(struct ioat_softc *ioat); static int ioat_map_pci_bar(struct ioat_softc *ioat); static void ioat_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error); static void ioat_interrupt_handler(void *arg); static boolean_t ioat_model_resets_msix(struct ioat_softc *ioat); static int chanerr_to_errno(uint32_t); static void ioat_process_events(struct ioat_softc *ioat); static inline uint32_t ioat_get_active(struct ioat_softc *ioat); static inline uint32_t ioat_get_ring_space(struct ioat_softc *ioat); static void ioat_free_ring(struct ioat_softc *, uint32_t size, struct ioat_descriptor **); static void ioat_free_ring_entry(struct ioat_softc *ioat, struct ioat_descriptor *desc); static struct ioat_descriptor *ioat_alloc_ring_entry(struct ioat_softc *, int mflags); static int ioat_reserve_space(struct ioat_softc *, uint32_t, int mflags); static struct ioat_descriptor *ioat_get_ring_entry(struct ioat_softc *ioat, uint32_t index); static struct ioat_descriptor **ioat_prealloc_ring(struct ioat_softc *, uint32_t size, boolean_t need_dscr, int mflags); static int ring_grow(struct ioat_softc *, uint32_t oldorder, struct ioat_descriptor **); static int ring_shrink(struct ioat_softc *, uint32_t oldorder, struct ioat_descriptor **); static void ioat_halted_debug(struct ioat_softc *, uint32_t); static void ioat_timer_callback(void *arg); static void dump_descriptor(void *hw_desc); static void ioat_submit_single(struct ioat_softc *ioat); static void ioat_comp_update_map(void *arg, bus_dma_segment_t *seg, int nseg, int error); static int ioat_reset_hw(struct ioat_softc *ioat); static void ioat_setup_sysctl(device_t device); static int sysctl_handle_reset(SYSCTL_HANDLER_ARGS); static inline struct ioat_softc *ioat_get(struct ioat_softc *, enum ioat_ref_kind); static inline void ioat_put(struct ioat_softc *, enum ioat_ref_kind); static inline void _ioat_putn(struct ioat_softc *, uint32_t, enum ioat_ref_kind, boolean_t); static inline void ioat_putn(struct ioat_softc *, uint32_t, enum ioat_ref_kind); static inline void ioat_putn_locked(struct ioat_softc *, uint32_t, enum ioat_ref_kind); static void ioat_drain_locked(struct ioat_softc *); #define ioat_log_message(v, ...) do { \ if ((v) <= g_ioat_debug_level) { \ device_printf(ioat->device, __VA_ARGS__); \ } \ } while (0) MALLOC_DEFINE(M_IOAT, "ioat", "ioat driver memory allocations"); SYSCTL_NODE(_hw, OID_AUTO, ioat, CTLFLAG_RD, 0, "ioat node"); static int g_force_legacy_interrupts; SYSCTL_INT(_hw_ioat, OID_AUTO, force_legacy_interrupts, CTLFLAG_RDTUN, &g_force_legacy_interrupts, 0, "Set to non-zero to force MSI-X disabled"); int g_ioat_debug_level = 0; SYSCTL_INT(_hw_ioat, OID_AUTO, debug_level, CTLFLAG_RWTUN, &g_ioat_debug_level, 0, "Set log level (0-3) for ioat(4). Higher is more verbose."); /* * OS <-> Driver interface structures */ static device_method_t ioat_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ioat_probe), DEVMETHOD(device_attach, ioat_attach), DEVMETHOD(device_detach, ioat_detach), { 0, 0 } }; static driver_t ioat_pci_driver = { "ioat", ioat_pci_methods, sizeof(struct ioat_softc), }; static devclass_t ioat_devclass; DRIVER_MODULE(ioat, pci, ioat_pci_driver, ioat_devclass, 0, 0); MODULE_VERSION(ioat, 1); /* * Private data structures */ static struct ioat_softc *ioat_channel[IOAT_MAX_CHANNELS]; static int ioat_channel_index = 0; SYSCTL_INT(_hw_ioat, OID_AUTO, channels, CTLFLAG_RD, &ioat_channel_index, 0, "Number of IOAT channels attached"); static struct _pcsid { u_int32_t type; const char *desc; } pci_ids[] = { { 0x34308086, "TBG IOAT Ch0" }, { 0x34318086, "TBG IOAT Ch1" }, { 0x34328086, "TBG IOAT Ch2" }, { 0x34338086, "TBG IOAT Ch3" }, { 0x34298086, "TBG IOAT Ch4" }, { 0x342a8086, "TBG IOAT Ch5" }, { 0x342b8086, "TBG IOAT Ch6" }, { 0x342c8086, "TBG IOAT Ch7" }, { 0x37108086, "JSF IOAT Ch0" }, { 0x37118086, "JSF IOAT Ch1" }, { 0x37128086, "JSF IOAT Ch2" }, { 0x37138086, "JSF IOAT Ch3" }, { 0x37148086, "JSF IOAT Ch4" }, { 0x37158086, "JSF IOAT Ch5" }, { 0x37168086, "JSF IOAT Ch6" }, { 0x37178086, "JSF IOAT Ch7" }, { 0x37188086, "JSF IOAT Ch0 (RAID)" }, { 0x37198086, "JSF IOAT Ch1 (RAID)" }, { 0x3c208086, "SNB IOAT Ch0" }, { 0x3c218086, "SNB IOAT Ch1" }, { 0x3c228086, "SNB IOAT Ch2" }, { 0x3c238086, "SNB IOAT Ch3" }, { 0x3c248086, "SNB IOAT Ch4" }, { 0x3c258086, "SNB IOAT Ch5" }, { 0x3c268086, "SNB IOAT Ch6" }, { 0x3c278086, "SNB IOAT Ch7" }, { 0x3c2e8086, "SNB IOAT Ch0 (RAID)" }, { 0x3c2f8086, "SNB IOAT Ch1 (RAID)" }, { 0x0e208086, "IVB IOAT Ch0" }, { 0x0e218086, "IVB IOAT Ch1" }, { 0x0e228086, "IVB IOAT Ch2" }, { 0x0e238086, "IVB IOAT Ch3" }, { 0x0e248086, "IVB IOAT Ch4" }, { 0x0e258086, "IVB IOAT Ch5" }, { 0x0e268086, "IVB IOAT Ch6" }, { 0x0e278086, "IVB IOAT Ch7" }, { 0x0e2e8086, "IVB IOAT Ch0 (RAID)" }, { 0x0e2f8086, "IVB IOAT Ch1 (RAID)" }, { 0x2f208086, "HSW IOAT Ch0" }, { 0x2f218086, "HSW IOAT Ch1" }, { 0x2f228086, "HSW IOAT Ch2" }, { 0x2f238086, "HSW IOAT Ch3" }, { 0x2f248086, "HSW IOAT Ch4" }, { 0x2f258086, "HSW IOAT Ch5" }, { 0x2f268086, "HSW IOAT Ch6" }, { 0x2f278086, "HSW IOAT Ch7" }, { 0x2f2e8086, "HSW IOAT Ch0 (RAID)" }, { 0x2f2f8086, "HSW IOAT Ch1 (RAID)" }, { 0x0c508086, "BWD IOAT Ch0" }, { 0x0c518086, "BWD IOAT Ch1" }, { 0x0c528086, "BWD IOAT Ch2" }, { 0x0c538086, "BWD IOAT Ch3" }, { 0x6f508086, "BDXDE IOAT Ch0" }, { 0x6f518086, "BDXDE IOAT Ch1" }, { 0x6f528086, "BDXDE IOAT Ch2" }, { 0x6f538086, "BDXDE IOAT Ch3" }, { 0x6f208086, "BDX IOAT Ch0" }, { 0x6f218086, "BDX IOAT Ch1" }, { 0x6f228086, "BDX IOAT Ch2" }, { 0x6f238086, "BDX IOAT Ch3" }, { 0x6f248086, "BDX IOAT Ch4" }, { 0x6f258086, "BDX IOAT Ch5" }, { 0x6f268086, "BDX IOAT Ch6" }, { 0x6f278086, "BDX IOAT Ch7" }, { 0x6f2e8086, "BDX IOAT Ch0 (RAID)" }, { 0x6f2f8086, "BDX IOAT Ch1 (RAID)" }, { 0x00000000, NULL } }; /* * OS <-> Driver linkage functions */ static int ioat_probe(device_t device) { struct _pcsid *ep; u_int32_t type; type = pci_get_devid(device); for (ep = pci_ids; ep->type; ep++) { if (ep->type == type) { device_set_desc(device, ep->desc); return (0); } } return (ENXIO); } static int ioat_attach(device_t device) { struct ioat_softc *ioat; int error; ioat = DEVICE2SOFTC(device); ioat->device = device; error = ioat_map_pci_bar(ioat); if (error != 0) goto err; ioat->version = ioat_read_cbver(ioat); if (ioat->version < IOAT_VER_3_0) { error = ENODEV; goto err; } error = ioat3_attach(device); if (error != 0) goto err; error = pci_enable_busmaster(device); if (error != 0) goto err; error = ioat_setup_intr(ioat); if (error != 0) goto err; error = ioat_reset_hw(ioat); if (error != 0) goto err; ioat_process_events(ioat); ioat_setup_sysctl(device); ioat->chan_idx = ioat_channel_index; ioat_channel[ioat_channel_index++] = ioat; ioat_test_attach(); err: if (error != 0) ioat_detach(device); return (error); } static int ioat_detach(device_t device) { struct ioat_softc *ioat; ioat = DEVICE2SOFTC(device); ioat_test_detach(); mtx_lock(IOAT_REFLK); ioat->quiescing = TRUE; ioat_channel[ioat->chan_idx] = NULL; ioat_drain_locked(ioat); mtx_unlock(IOAT_REFLK); ioat_teardown_intr(ioat); callout_drain(&ioat->timer); pci_disable_busmaster(device); if (ioat->pci_resource != NULL) bus_release_resource(device, SYS_RES_MEMORY, ioat->pci_resource_id, ioat->pci_resource); if (ioat->ring != NULL) ioat_free_ring(ioat, 1 << ioat->ring_size_order, ioat->ring); if (ioat->comp_update != NULL) { bus_dmamap_unload(ioat->comp_update_tag, ioat->comp_update_map); bus_dmamem_free(ioat->comp_update_tag, ioat->comp_update, ioat->comp_update_map); bus_dma_tag_destroy(ioat->comp_update_tag); } bus_dma_tag_destroy(ioat->hw_desc_tag); return (0); } static int ioat_teardown_intr(struct ioat_softc *ioat) { if (ioat->tag != NULL) bus_teardown_intr(ioat->device, ioat->res, ioat->tag); if (ioat->res != NULL) bus_release_resource(ioat->device, SYS_RES_IRQ, rman_get_rid(ioat->res), ioat->res); pci_release_msi(ioat->device); return (0); } static int ioat_start_channel(struct ioat_softc *ioat) { uint64_t status; uint32_t chanerr; int i; ioat_acquire(&ioat->dmaengine); ioat_null(&ioat->dmaengine, NULL, NULL, 0); ioat_release(&ioat->dmaengine); for (i = 0; i < 100; i++) { DELAY(1); status = ioat_get_chansts(ioat); if (is_ioat_idle(status)) return (0); } chanerr = ioat_read_4(ioat, IOAT_CHANERR_OFFSET); ioat_log_message(0, "could not start channel: " "status = %#jx error = %b\n", (uintmax_t)status, (int)chanerr, IOAT_CHANERR_STR); return (ENXIO); } /* * Initialize Hardware */ static int ioat3_attach(device_t device) { struct ioat_softc *ioat; struct ioat_descriptor **ring; struct ioat_descriptor *next; struct ioat_dma_hw_descriptor *dma_hw_desc; int i, num_descriptors; int error; uint8_t xfercap; error = 0; ioat = DEVICE2SOFTC(device); ioat->capabilities = ioat_read_dmacapability(ioat); ioat_log_message(1, "Capabilities: %b\n", (int)ioat->capabilities, IOAT_DMACAP_STR); xfercap = ioat_read_xfercap(ioat); ioat->max_xfer_size = 1 << xfercap; ioat->intrdelay_supported = (ioat_read_2(ioat, IOAT_INTRDELAY_OFFSET) & IOAT_INTRDELAY_SUPPORTED) != 0; if (ioat->intrdelay_supported) ioat->intrdelay_max = IOAT_INTRDELAY_US_MASK; /* TODO: need to check DCA here if we ever do XOR/PQ */ mtx_init(&ioat->submit_lock, "ioat_submit", NULL, MTX_DEF); mtx_init(&ioat->cleanup_lock, "ioat_cleanup", NULL, MTX_DEF); callout_init(&ioat->timer, 1); /* Establish lock order for Witness */ mtx_lock(&ioat->submit_lock); mtx_lock(&ioat->cleanup_lock); mtx_unlock(&ioat->cleanup_lock); mtx_unlock(&ioat->submit_lock); ioat->is_resize_pending = FALSE; ioat->is_completion_pending = FALSE; ioat->is_reset_pending = FALSE; ioat->is_channel_running = FALSE; bus_dma_tag_create(bus_get_dma_tag(ioat->device), sizeof(uint64_t), 0x0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, sizeof(uint64_t), 1, sizeof(uint64_t), 0, NULL, NULL, &ioat->comp_update_tag); error = bus_dmamem_alloc(ioat->comp_update_tag, (void **)&ioat->comp_update, BUS_DMA_ZERO, &ioat->comp_update_map); if (ioat->comp_update == NULL) return (ENOMEM); error = bus_dmamap_load(ioat->comp_update_tag, ioat->comp_update_map, ioat->comp_update, sizeof(uint64_t), ioat_comp_update_map, ioat, 0); if (error != 0) return (error); ioat->ring_size_order = IOAT_MIN_ORDER; num_descriptors = 1 << ioat->ring_size_order; bus_dma_tag_create(bus_get_dma_tag(ioat->device), 0x40, 0x0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, sizeof(struct ioat_dma_hw_descriptor), 1, sizeof(struct ioat_dma_hw_descriptor), 0, NULL, NULL, &ioat->hw_desc_tag); ioat->ring = malloc(num_descriptors * sizeof(*ring), M_IOAT, M_ZERO | M_WAITOK); if (ioat->ring == NULL) return (ENOMEM); ring = ioat->ring; for (i = 0; i < num_descriptors; i++) { ring[i] = ioat_alloc_ring_entry(ioat, M_WAITOK); if (ring[i] == NULL) return (ENOMEM); ring[i]->id = i; } for (i = 0; i < num_descriptors - 1; i++) { next = ring[i + 1]; dma_hw_desc = ring[i]->u.dma; dma_hw_desc->next = next->hw_desc_bus_addr; } ring[i]->u.dma->next = ring[0]->hw_desc_bus_addr; ioat->head = ioat->hw_head = 0; ioat->tail = 0; ioat->last_seen = 0; return (0); } static int ioat_map_pci_bar(struct ioat_softc *ioat) { ioat->pci_resource_id = PCIR_BAR(0); ioat->pci_resource = bus_alloc_resource_any(ioat->device, SYS_RES_MEMORY, &ioat->pci_resource_id, RF_ACTIVE); if (ioat->pci_resource == NULL) { ioat_log_message(0, "unable to allocate pci resource\n"); return (ENODEV); } ioat->pci_bus_tag = rman_get_bustag(ioat->pci_resource); ioat->pci_bus_handle = rman_get_bushandle(ioat->pci_resource); return (0); } static void ioat_comp_update_map(void *arg, bus_dma_segment_t *seg, int nseg, int error) { struct ioat_softc *ioat = arg; KASSERT(error == 0, ("%s: error:%d", __func__, error)); ioat->comp_update_bus_addr = seg[0].ds_addr; } static void ioat_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) { bus_addr_t *baddr; KASSERT(error == 0, ("%s: error:%d", __func__, error)); baddr = arg; *baddr = segs->ds_addr; } /* * Interrupt setup and handlers */ static int ioat_setup_intr(struct ioat_softc *ioat) { uint32_t num_vectors; int error; boolean_t use_msix; boolean_t force_legacy_interrupts; use_msix = FALSE; force_legacy_interrupts = FALSE; if (!g_force_legacy_interrupts && pci_msix_count(ioat->device) >= 1) { num_vectors = 1; pci_alloc_msix(ioat->device, &num_vectors); if (num_vectors == 1) use_msix = TRUE; } if (use_msix) { ioat->rid = 1; ioat->res = bus_alloc_resource_any(ioat->device, SYS_RES_IRQ, &ioat->rid, RF_ACTIVE); } else { ioat->rid = 0; ioat->res = bus_alloc_resource_any(ioat->device, SYS_RES_IRQ, &ioat->rid, RF_SHAREABLE | RF_ACTIVE); } if (ioat->res == NULL) { ioat_log_message(0, "bus_alloc_resource failed\n"); return (ENOMEM); } ioat->tag = NULL; error = bus_setup_intr(ioat->device, ioat->res, INTR_MPSAFE | INTR_TYPE_MISC, NULL, ioat_interrupt_handler, ioat, &ioat->tag); if (error != 0) { ioat_log_message(0, "bus_setup_intr failed\n"); return (error); } ioat_write_intrctrl(ioat, IOAT_INTRCTRL_MASTER_INT_EN); return (0); } static boolean_t ioat_model_resets_msix(struct ioat_softc *ioat) { u_int32_t pciid; pciid = pci_get_devid(ioat->device); switch (pciid) { /* BWD: */ case 0x0c508086: case 0x0c518086: case 0x0c528086: case 0x0c538086: /* BDXDE: */ case 0x6f508086: case 0x6f518086: case 0x6f528086: case 0x6f538086: return (TRUE); } return (FALSE); } static void ioat_interrupt_handler(void *arg) { struct ioat_softc *ioat = arg; ioat->stats.interrupts++; ioat_process_events(ioat); } static int chanerr_to_errno(uint32_t chanerr) { if (chanerr == 0) return (0); if ((chanerr & (IOAT_CHANERR_XSADDERR | IOAT_CHANERR_XDADDERR)) != 0) return (EFAULT); if ((chanerr & (IOAT_CHANERR_RDERR | IOAT_CHANERR_WDERR)) != 0) return (EIO); /* This one is probably our fault: */ if ((chanerr & IOAT_CHANERR_NDADDERR) != 0) return (EIO); return (EIO); } static void ioat_process_events(struct ioat_softc *ioat) { struct ioat_descriptor *desc; struct bus_dmadesc *dmadesc; uint64_t comp_update, status; uint32_t completed, chanerr; int error; mtx_lock(&ioat->cleanup_lock); completed = 0; comp_update = *ioat->comp_update; status = comp_update & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_MASK; CTR0(KTR_IOAT, __func__); if (status == ioat->last_seen) goto out; while (1) { desc = ioat_get_ring_entry(ioat, ioat->tail); dmadesc = &desc->bus_dmadesc; CTR1(KTR_IOAT, "completing desc %d", ioat->tail); if (dmadesc->callback_fn != NULL) dmadesc->callback_fn(dmadesc->callback_arg, 0); completed++; ioat->tail++; if (desc->hw_desc_bus_addr == status) break; } ioat->last_seen = desc->hw_desc_bus_addr; if (ioat->head == ioat->tail) { ioat->is_completion_pending = FALSE; callout_reset(&ioat->timer, IOAT_INTR_TIMO, ioat_timer_callback, ioat); } ioat->stats.descriptors_processed += completed; out: ioat_write_chanctrl(ioat, IOAT_CHANCTRL_RUN); mtx_unlock(&ioat->cleanup_lock); ioat_putn(ioat, completed, IOAT_ACTIVE_DESCR_REF); wakeup(&ioat->tail); if (!is_ioat_halted(comp_update)) return; ioat->stats.channel_halts++; /* * Fatal programming error on this DMA channel. Flush any outstanding * work with error status and restart the engine. */ ioat_log_message(0, "Channel halted due to fatal programming error\n"); mtx_lock(&ioat->submit_lock); mtx_lock(&ioat->cleanup_lock); ioat->quiescing = TRUE; chanerr = ioat_read_4(ioat, IOAT_CHANERR_OFFSET); ioat_halted_debug(ioat, chanerr); ioat->stats.last_halt_chanerr = chanerr; while (ioat_get_active(ioat) > 0) { desc = ioat_get_ring_entry(ioat, ioat->tail); dmadesc = &desc->bus_dmadesc; CTR1(KTR_IOAT, "completing err desc %d", ioat->tail); if (dmadesc->callback_fn != NULL) dmadesc->callback_fn(dmadesc->callback_arg, chanerr_to_errno(chanerr)); ioat_putn_locked(ioat, 1, IOAT_ACTIVE_DESCR_REF); ioat->tail++; ioat->stats.descriptors_processed++; ioat->stats.descriptors_error++; } /* Clear error status */ ioat_write_4(ioat, IOAT_CHANERR_OFFSET, chanerr); mtx_unlock(&ioat->cleanup_lock); mtx_unlock(&ioat->submit_lock); ioat_log_message(0, "Resetting channel to recover from error\n"); error = ioat_reset_hw(ioat); KASSERT(error == 0, ("%s: reset failed: %d", __func__, error)); } /* * User API functions */ bus_dmaengine_t ioat_get_dmaengine(uint32_t index) { struct ioat_softc *sc; if (index >= ioat_channel_index) return (NULL); sc = ioat_channel[index]; if (sc == NULL || sc->quiescing) return (NULL); return (&ioat_get(sc, IOAT_DMAENGINE_REF)->dmaengine); } void ioat_put_dmaengine(bus_dmaengine_t dmaengine) { struct ioat_softc *ioat; ioat = to_ioat_softc(dmaengine); ioat_put(ioat, IOAT_DMAENGINE_REF); } int +ioat_get_hwversion(bus_dmaengine_t dmaengine) +{ + struct ioat_softc *ioat; + + ioat = to_ioat_softc(dmaengine); + return (ioat->version); +} + +int ioat_set_interrupt_coalesce(bus_dmaengine_t dmaengine, uint16_t delay) { struct ioat_softc *ioat; ioat = to_ioat_softc(dmaengine); if (!ioat->intrdelay_supported) return (ENODEV); if (delay > ioat->intrdelay_max) return (ERANGE); ioat_write_2(ioat, IOAT_INTRDELAY_OFFSET, delay); ioat->cached_intrdelay = ioat_read_2(ioat, IOAT_INTRDELAY_OFFSET) & IOAT_INTRDELAY_US_MASK; return (0); } uint16_t ioat_get_max_coalesce_period(bus_dmaengine_t dmaengine) { struct ioat_softc *ioat; ioat = to_ioat_softc(dmaengine); return (ioat->intrdelay_max); } void ioat_acquire(bus_dmaengine_t dmaengine) { struct ioat_softc *ioat; ioat = to_ioat_softc(dmaengine); mtx_lock(&ioat->submit_lock); CTR0(KTR_IOAT, __func__); } void ioat_release(bus_dmaengine_t dmaengine) { struct ioat_softc *ioat; ioat = to_ioat_softc(dmaengine); CTR0(KTR_IOAT, __func__); ioat_write_2(ioat, IOAT_DMACOUNT_OFFSET, (uint16_t)ioat->hw_head); mtx_unlock(&ioat->submit_lock); } static struct ioat_descriptor * ioat_op_generic(struct ioat_softc *ioat, uint8_t op, uint32_t size, uint64_t src, uint64_t dst, bus_dmaengine_callback_t callback_fn, void *callback_arg, uint32_t flags) { struct ioat_generic_hw_descriptor *hw_desc; struct ioat_descriptor *desc; int mflags; mtx_assert(&ioat->submit_lock, MA_OWNED); KASSERT((flags & ~DMA_ALL_FLAGS) == 0, ("Unrecognized flag(s): %#x", flags & ~DMA_ALL_FLAGS)); if ((flags & DMA_NO_WAIT) != 0) mflags = M_NOWAIT; else mflags = M_WAITOK; if (size > ioat->max_xfer_size) { ioat_log_message(0, "%s: max_xfer_size = %d, requested = %u\n", __func__, ioat->max_xfer_size, (unsigned)size); return (NULL); } if (ioat_reserve_space(ioat, 1, mflags) != 0) return (NULL); desc = ioat_get_ring_entry(ioat, ioat->head); hw_desc = desc->u.generic; hw_desc->u.control_raw = 0; hw_desc->u.control_generic.op = op; hw_desc->u.control_generic.completion_update = 1; if ((flags & DMA_INT_EN) != 0) hw_desc->u.control_generic.int_enable = 1; hw_desc->size = size; hw_desc->src_addr = src; hw_desc->dest_addr = dst; desc->bus_dmadesc.callback_fn = callback_fn; desc->bus_dmadesc.callback_arg = callback_arg; return (desc); } struct bus_dmadesc * ioat_null(bus_dmaengine_t dmaengine, bus_dmaengine_callback_t callback_fn, void *callback_arg, uint32_t flags) { struct ioat_dma_hw_descriptor *hw_desc; struct ioat_descriptor *desc; struct ioat_softc *ioat; CTR0(KTR_IOAT, __func__); ioat = to_ioat_softc(dmaengine); desc = ioat_op_generic(ioat, IOAT_OP_COPY, 8, 0, 0, callback_fn, callback_arg, flags); if (desc == NULL) return (NULL); hw_desc = desc->u.dma; hw_desc->u.control.null = 1; ioat_submit_single(ioat); return (&desc->bus_dmadesc); } struct bus_dmadesc * ioat_copy(bus_dmaengine_t dmaengine, bus_addr_t dst, bus_addr_t src, bus_size_t len, bus_dmaengine_callback_t callback_fn, void *callback_arg, uint32_t flags) { struct ioat_dma_hw_descriptor *hw_desc; struct ioat_descriptor *desc; struct ioat_softc *ioat; CTR0(KTR_IOAT, __func__); ioat = to_ioat_softc(dmaengine); if (((src | dst) & (0xffffull << 48)) != 0) { ioat_log_message(0, "%s: High 16 bits of src/dst invalid\n", __func__); return (NULL); } desc = ioat_op_generic(ioat, IOAT_OP_COPY, len, src, dst, callback_fn, callback_arg, flags); if (desc == NULL) return (NULL); hw_desc = desc->u.dma; if (g_ioat_debug_level >= 3) dump_descriptor(hw_desc); ioat_submit_single(ioat); return (&desc->bus_dmadesc); } struct bus_dmadesc * ioat_copy_8k_aligned(bus_dmaengine_t dmaengine, bus_addr_t dst1, bus_addr_t dst2, bus_addr_t src1, bus_addr_t src2, bus_dmaengine_callback_t callback_fn, void *callback_arg, uint32_t flags) { struct ioat_dma_hw_descriptor *hw_desc; struct ioat_descriptor *desc; struct ioat_softc *ioat; CTR0(KTR_IOAT, __func__); ioat = to_ioat_softc(dmaengine); if (((src1 | src2 | dst1 | dst2) & (0xffffull << 48)) != 0) { ioat_log_message(0, "%s: High 16 bits of src/dst invalid\n", __func__); return (NULL); } if (((src1 | src2 | dst1 | dst2) & PAGE_MASK) != 0) { ioat_log_message(0, "%s: Addresses must be page-aligned\n", __func__); return (NULL); } desc = ioat_op_generic(ioat, IOAT_OP_COPY, 2 * PAGE_SIZE, src1, dst1, callback_fn, callback_arg, flags); if (desc == NULL) return (NULL); hw_desc = desc->u.dma; if (src2 != src1 + PAGE_SIZE) { hw_desc->u.control.src_page_break = 1; hw_desc->next_src_addr = src2; } if (dst2 != dst1 + PAGE_SIZE) { hw_desc->u.control.dest_page_break = 1; hw_desc->next_dest_addr = dst2; } if (g_ioat_debug_level >= 3) dump_descriptor(hw_desc); ioat_submit_single(ioat); return (&desc->bus_dmadesc); } struct bus_dmadesc * ioat_blockfill(bus_dmaengine_t dmaengine, bus_addr_t dst, uint64_t fillpattern, bus_size_t len, bus_dmaengine_callback_t callback_fn, void *callback_arg, uint32_t flags) { struct ioat_fill_hw_descriptor *hw_desc; struct ioat_descriptor *desc; struct ioat_softc *ioat; CTR0(KTR_IOAT, __func__); ioat = to_ioat_softc(dmaengine); if ((ioat->capabilities & IOAT_DMACAP_BFILL) == 0) { ioat_log_message(0, "%s: Device lacks BFILL capability\n", __func__); return (NULL); } if ((dst & (0xffffull << 48)) != 0) { ioat_log_message(0, "%s: High 16 bits of dst invalid\n", __func__); return (NULL); } desc = ioat_op_generic(ioat, IOAT_OP_FILL, len, fillpattern, dst, callback_fn, callback_arg, flags); if (desc == NULL) return (NULL); hw_desc = desc->u.fill; if (g_ioat_debug_level >= 3) dump_descriptor(hw_desc); ioat_submit_single(ioat); return (&desc->bus_dmadesc); } /* * Ring Management */ static inline uint32_t ioat_get_active(struct ioat_softc *ioat) { return ((ioat->head - ioat->tail) & ((1 << ioat->ring_size_order) - 1)); } static inline uint32_t ioat_get_ring_space(struct ioat_softc *ioat) { return ((1 << ioat->ring_size_order) - ioat_get_active(ioat) - 1); } static struct ioat_descriptor * ioat_alloc_ring_entry(struct ioat_softc *ioat, int mflags) { struct ioat_generic_hw_descriptor *hw_desc; struct ioat_descriptor *desc; int error, busdmaflag; error = ENOMEM; hw_desc = NULL; if ((mflags & M_WAITOK) != 0) busdmaflag = BUS_DMA_WAITOK; else busdmaflag = BUS_DMA_NOWAIT; desc = malloc(sizeof(*desc), M_IOAT, mflags); if (desc == NULL) goto out; bus_dmamem_alloc(ioat->hw_desc_tag, (void **)&hw_desc, BUS_DMA_ZERO | busdmaflag, &ioat->hw_desc_map); if (hw_desc == NULL) goto out; memset(&desc->bus_dmadesc, 0, sizeof(desc->bus_dmadesc)); desc->u.generic = hw_desc; error = bus_dmamap_load(ioat->hw_desc_tag, ioat->hw_desc_map, hw_desc, sizeof(*hw_desc), ioat_dmamap_cb, &desc->hw_desc_bus_addr, busdmaflag); if (error) goto out; out: if (error) { ioat_free_ring_entry(ioat, desc); return (NULL); } return (desc); } static void ioat_free_ring_entry(struct ioat_softc *ioat, struct ioat_descriptor *desc) { if (desc == NULL) return; if (desc->u.generic) bus_dmamem_free(ioat->hw_desc_tag, desc->u.generic, ioat->hw_desc_map); free(desc, M_IOAT); } /* * Reserves space in this IOAT descriptor ring by ensuring enough slots remain * for 'num_descs'. * * If mflags contains M_WAITOK, blocks until enough space is available. * * Returns zero on success, or an errno on error. If num_descs is beyond the * maximum ring size, returns EINVAl; if allocation would block and mflags * contains M_NOWAIT, returns EAGAIN. * * Must be called with the submit_lock held; returns with the lock held. The * lock may be dropped to allocate the ring. * * (The submit_lock is needed to add any entries to the ring, so callers are * assured enough room is available.) */ static int ioat_reserve_space(struct ioat_softc *ioat, uint32_t num_descs, int mflags) { struct ioat_descriptor **new_ring; uint32_t order; int error; mtx_assert(&ioat->submit_lock, MA_OWNED); error = 0; if (num_descs < 1 || num_descs > (1 << IOAT_MAX_ORDER)) { error = EINVAL; goto out; } if (ioat->quiescing) { error = ENXIO; goto out; } for (;;) { if (ioat_get_ring_space(ioat) >= num_descs) goto out; order = ioat->ring_size_order; if (ioat->is_resize_pending || order == IOAT_MAX_ORDER) { if ((mflags & M_WAITOK) != 0) { msleep(&ioat->tail, &ioat->submit_lock, 0, "ioat_rsz", 0); continue; } error = EAGAIN; break; } ioat->is_resize_pending = TRUE; for (;;) { mtx_unlock(&ioat->submit_lock); new_ring = ioat_prealloc_ring(ioat, 1 << (order + 1), TRUE, mflags); mtx_lock(&ioat->submit_lock); KASSERT(ioat->ring_size_order == order, ("is_resize_pending should protect order")); if (new_ring == NULL) { KASSERT((mflags & M_WAITOK) == 0, ("allocation failed")); error = EAGAIN; break; } error = ring_grow(ioat, order, new_ring); if (error == 0) break; } ioat->is_resize_pending = FALSE; wakeup(&ioat->tail); if (error) break; } out: mtx_assert(&ioat->submit_lock, MA_OWNED); return (error); } static struct ioat_descriptor ** ioat_prealloc_ring(struct ioat_softc *ioat, uint32_t size, boolean_t need_dscr, int mflags) { struct ioat_descriptor **ring; uint32_t i; int error; KASSERT(size > 0 && powerof2(size), ("bogus size")); ring = malloc(size * sizeof(*ring), M_IOAT, M_ZERO | mflags); if (ring == NULL) return (NULL); if (need_dscr) { error = ENOMEM; for (i = size / 2; i < size; i++) { ring[i] = ioat_alloc_ring_entry(ioat, mflags); if (ring[i] == NULL) goto out; ring[i]->id = i; } } error = 0; out: if (error != 0 && ring != NULL) { ioat_free_ring(ioat, size, ring); ring = NULL; } return (ring); } static void ioat_free_ring(struct ioat_softc *ioat, uint32_t size, struct ioat_descriptor **ring) { uint32_t i; for (i = 0; i < size; i++) { if (ring[i] != NULL) ioat_free_ring_entry(ioat, ring[i]); } free(ring, M_IOAT); } static struct ioat_descriptor * ioat_get_ring_entry(struct ioat_softc *ioat, uint32_t index) { return (ioat->ring[index % (1 << ioat->ring_size_order)]); } static int ring_grow(struct ioat_softc *ioat, uint32_t oldorder, struct ioat_descriptor **newring) { struct ioat_descriptor *tmp, *next; struct ioat_dma_hw_descriptor *hw; uint32_t oldsize, newsize, head, tail, i, end; int error; CTR0(KTR_IOAT, __func__); mtx_assert(&ioat->submit_lock, MA_OWNED); if (oldorder != ioat->ring_size_order || oldorder >= IOAT_MAX_ORDER) { error = EINVAL; goto out; } oldsize = (1 << oldorder); newsize = (1 << (oldorder + 1)); mtx_lock(&ioat->cleanup_lock); head = ioat->head & (oldsize - 1); tail = ioat->tail & (oldsize - 1); /* Copy old descriptors to new ring */ for (i = 0; i < oldsize; i++) newring[i] = ioat->ring[i]; /* * If head has wrapped but tail hasn't, we must swap some descriptors * around so that tail can increment directly to head. */ if (head < tail) { for (i = 0; i <= head; i++) { tmp = newring[oldsize + i]; newring[oldsize + i] = newring[i]; newring[oldsize + i]->id = oldsize + i; newring[i] = tmp; newring[i]->id = i; } head += oldsize; } KASSERT(head >= tail, ("invariants")); /* Head didn't wrap; we only need to link in oldsize..newsize */ if (head < oldsize) { i = oldsize - 1; end = newsize; } else { /* Head did wrap; link newhead..newsize and 0..oldhead */ i = head; end = newsize + (head - oldsize) + 1; } /* * Fix up hardware ring, being careful not to trample the active * section (tail -> head). */ for (; i < end; i++) { KASSERT((i & (newsize - 1)) < tail || (i & (newsize - 1)) >= head, ("trampling snake")); next = newring[(i + 1) & (newsize - 1)]; hw = newring[i & (newsize - 1)]->u.dma; hw->next = next->hw_desc_bus_addr; } free(ioat->ring, M_IOAT); ioat->ring = newring; ioat->ring_size_order = oldorder + 1; ioat->tail = tail; ioat->head = head; error = 0; mtx_unlock(&ioat->cleanup_lock); out: if (error) ioat_free_ring(ioat, (1 << (oldorder + 1)), newring); return (error); } static int ring_shrink(struct ioat_softc *ioat, uint32_t oldorder, struct ioat_descriptor **newring) { struct ioat_dma_hw_descriptor *hw; struct ioat_descriptor *ent, *next; uint32_t oldsize, newsize, current_idx, new_idx, i; int error; CTR0(KTR_IOAT, __func__); mtx_assert(&ioat->submit_lock, MA_OWNED); if (oldorder != ioat->ring_size_order || oldorder <= IOAT_MIN_ORDER) { error = EINVAL; goto out_unlocked; } oldsize = (1 << oldorder); newsize = (1 << (oldorder - 1)); mtx_lock(&ioat->cleanup_lock); /* Can't shrink below current active set! */ if (ioat_get_active(ioat) >= newsize) { error = ENOMEM; goto out; } /* * Copy current descriptors to the new ring, dropping the removed * descriptors. */ for (i = 0; i < newsize; i++) { current_idx = (ioat->tail + i) & (oldsize - 1); new_idx = (ioat->tail + i) & (newsize - 1); newring[new_idx] = ioat->ring[current_idx]; newring[new_idx]->id = new_idx; } /* Free deleted descriptors */ for (i = newsize; i < oldsize; i++) { ent = ioat_get_ring_entry(ioat, ioat->tail + i); ioat_free_ring_entry(ioat, ent); } /* Fix up hardware ring. */ hw = newring[(ioat->tail + newsize - 1) & (newsize - 1)]->u.dma; next = newring[(ioat->tail + newsize) & (newsize - 1)]; hw->next = next->hw_desc_bus_addr; free(ioat->ring, M_IOAT); ioat->ring = newring; ioat->ring_size_order = oldorder - 1; error = 0; out: mtx_unlock(&ioat->cleanup_lock); out_unlocked: if (error) ioat_free_ring(ioat, (1 << (oldorder - 1)), newring); return (error); } static void ioat_halted_debug(struct ioat_softc *ioat, uint32_t chanerr) { struct ioat_descriptor *desc; ioat_log_message(0, "Channel halted (%b)\n", (int)chanerr, IOAT_CHANERR_STR); if (chanerr == 0) return; mtx_assert(&ioat->cleanup_lock, MA_OWNED); desc = ioat_get_ring_entry(ioat, ioat->tail + 0); dump_descriptor(desc->u.raw); desc = ioat_get_ring_entry(ioat, ioat->tail + 1); dump_descriptor(desc->u.raw); } static void ioat_timer_callback(void *arg) { struct ioat_descriptor **newring; struct ioat_softc *ioat; uint32_t order; ioat = arg; ioat_log_message(1, "%s\n", __func__); if (ioat->is_completion_pending) { ioat_process_events(ioat); return; } /* Slowly scale the ring down if idle. */ mtx_lock(&ioat->submit_lock); order = ioat->ring_size_order; if (ioat->is_resize_pending || order == IOAT_MIN_ORDER) { mtx_unlock(&ioat->submit_lock); goto out; } ioat->is_resize_pending = TRUE; mtx_unlock(&ioat->submit_lock); newring = ioat_prealloc_ring(ioat, 1 << (order - 1), FALSE, M_NOWAIT); mtx_lock(&ioat->submit_lock); KASSERT(ioat->ring_size_order == order, ("resize_pending protects order")); if (newring != NULL) ring_shrink(ioat, order, newring); ioat->is_resize_pending = FALSE; mtx_unlock(&ioat->submit_lock); out: if (ioat->ring_size_order > IOAT_MIN_ORDER) callout_reset(&ioat->timer, 10 * hz, ioat_timer_callback, ioat); } /* * Support Functions */ static void ioat_submit_single(struct ioat_softc *ioat) { ioat_get(ioat, IOAT_ACTIVE_DESCR_REF); atomic_add_rel_int(&ioat->head, 1); atomic_add_rel_int(&ioat->hw_head, 1); if (!ioat->is_completion_pending) { ioat->is_completion_pending = TRUE; callout_reset(&ioat->timer, IOAT_INTR_TIMO, ioat_timer_callback, ioat); } ioat->stats.descriptors_submitted++; } static int ioat_reset_hw(struct ioat_softc *ioat) { uint64_t status; uint32_t chanerr; unsigned timeout; int error; mtx_lock(IOAT_REFLK); ioat->quiescing = TRUE; ioat_drain_locked(ioat); mtx_unlock(IOAT_REFLK); status = ioat_get_chansts(ioat); if (is_ioat_active(status) || is_ioat_idle(status)) ioat_suspend(ioat); /* Wait at most 20 ms */ for (timeout = 0; (is_ioat_active(status) || is_ioat_idle(status)) && timeout < 20; timeout++) { DELAY(1000); status = ioat_get_chansts(ioat); } if (timeout == 20) { error = ETIMEDOUT; goto out; } KASSERT(ioat_get_active(ioat) == 0, ("active after quiesce")); chanerr = ioat_read_4(ioat, IOAT_CHANERR_OFFSET); ioat_write_4(ioat, IOAT_CHANERR_OFFSET, chanerr); /* * IOAT v3 workaround - CHANERRMSK_INT with 3E07h to masks out errors * that can cause stability issues for IOAT v3. */ pci_write_config(ioat->device, IOAT_CFG_CHANERRMASK_INT_OFFSET, 0x3e07, 4); chanerr = pci_read_config(ioat->device, IOAT_CFG_CHANERR_INT_OFFSET, 4); pci_write_config(ioat->device, IOAT_CFG_CHANERR_INT_OFFSET, chanerr, 4); /* * BDXDE and BWD models reset MSI-X registers on device reset. * Save/restore their contents manually. */ if (ioat_model_resets_msix(ioat)) { ioat_log_message(1, "device resets MSI-X registers; saving\n"); pci_save_state(ioat->device); } ioat_reset(ioat); /* Wait at most 20 ms */ for (timeout = 0; ioat_reset_pending(ioat) && timeout < 20; timeout++) DELAY(1000); if (timeout == 20) { error = ETIMEDOUT; goto out; } if (ioat_model_resets_msix(ioat)) { ioat_log_message(1, "device resets registers; restored\n"); pci_restore_state(ioat->device); } /* Reset attempts to return the hardware to "halted." */ status = ioat_get_chansts(ioat); if (is_ioat_active(status) || is_ioat_idle(status)) { /* So this really shouldn't happen... */ ioat_log_message(0, "Device is active after a reset?\n"); ioat_write_chanctrl(ioat, IOAT_CHANCTRL_RUN); error = 0; goto out; } chanerr = ioat_read_4(ioat, IOAT_CHANERR_OFFSET); if (chanerr != 0) { mtx_lock(&ioat->cleanup_lock); ioat_halted_debug(ioat, chanerr); mtx_unlock(&ioat->cleanup_lock); error = EIO; goto out; } /* * Bring device back online after reset. Writing CHAINADDR brings the * device back to active. * * The internal ring counter resets to zero, so we have to start over * at zero as well. */ ioat->tail = ioat->head = ioat->hw_head = 0; ioat->last_seen = 0; ioat_write_chanctrl(ioat, IOAT_CHANCTRL_RUN); ioat_write_chancmp(ioat, ioat->comp_update_bus_addr); ioat_write_chainaddr(ioat, ioat->ring[0]->hw_desc_bus_addr); error = 0; out: mtx_lock(IOAT_REFLK); ioat->quiescing = FALSE; mtx_unlock(IOAT_REFLK); if (error == 0) error = ioat_start_channel(ioat); return (error); } static int sysctl_handle_chansts(SYSCTL_HANDLER_ARGS) { struct ioat_softc *ioat; struct sbuf sb; uint64_t status; int error; ioat = arg1; status = ioat_get_chansts(ioat) & IOAT_CHANSTS_STATUS; sbuf_new_for_sysctl(&sb, NULL, 256, req); switch (status) { case IOAT_CHANSTS_ACTIVE: sbuf_printf(&sb, "ACTIVE"); break; case IOAT_CHANSTS_IDLE: sbuf_printf(&sb, "IDLE"); break; case IOAT_CHANSTS_SUSPENDED: sbuf_printf(&sb, "SUSPENDED"); break; case IOAT_CHANSTS_HALTED: sbuf_printf(&sb, "HALTED"); break; case IOAT_CHANSTS_ARMED: sbuf_printf(&sb, "ARMED"); break; default: sbuf_printf(&sb, "UNKNOWN"); break; } error = sbuf_finish(&sb); sbuf_delete(&sb); if (error != 0 || req->newptr == NULL) return (error); return (EINVAL); } static int sysctl_handle_dpi(SYSCTL_HANDLER_ARGS) { struct ioat_softc *ioat; struct sbuf sb; #define PRECISION "1" const uintmax_t factor = 10; uintmax_t rate; int error; ioat = arg1; sbuf_new_for_sysctl(&sb, NULL, 16, req); if (ioat->stats.interrupts == 0) { sbuf_printf(&sb, "NaN"); goto out; } rate = ioat->stats.descriptors_processed * factor / ioat->stats.interrupts; sbuf_printf(&sb, "%ju.%." PRECISION "ju", rate / factor, rate % factor); #undef PRECISION out: error = sbuf_finish(&sb); sbuf_delete(&sb); if (error != 0 || req->newptr == NULL) return (error); return (EINVAL); } static int sysctl_handle_error(SYSCTL_HANDLER_ARGS) { struct ioat_descriptor *desc; struct ioat_softc *ioat; int error, arg; ioat = arg1; arg = 0; error = SYSCTL_OUT(req, &arg, sizeof(arg)); if (error != 0 || req->newptr == NULL) return (error); error = SYSCTL_IN(req, &arg, sizeof(arg)); if (error != 0) return (error); if (arg != 0) { ioat_acquire(&ioat->dmaengine); desc = ioat_op_generic(ioat, IOAT_OP_COPY, 1, 0xffff000000000000ull, 0xffff000000000000ull, NULL, NULL, 0); if (desc == NULL) error = ENOMEM; else ioat_submit_single(ioat); ioat_release(&ioat->dmaengine); } return (error); } static int sysctl_handle_reset(SYSCTL_HANDLER_ARGS) { struct ioat_softc *ioat; int error, arg; ioat = arg1; arg = 0; error = SYSCTL_OUT(req, &arg, sizeof(arg)); if (error != 0 || req->newptr == NULL) return (error); error = SYSCTL_IN(req, &arg, sizeof(arg)); if (error != 0) return (error); if (arg != 0) error = ioat_reset_hw(ioat); return (error); } static void dump_descriptor(void *hw_desc) { int i, j; for (i = 0; i < 2; i++) { for (j = 0; j < 8; j++) printf("%08x ", ((uint32_t *)hw_desc)[i * 8 + j]); printf("\n"); } } static void ioat_setup_sysctl(device_t device) { struct sysctl_oid_list *par, *statpar, *state, *hammer; struct sysctl_ctx_list *ctx; struct sysctl_oid *tree, *tmp; struct ioat_softc *ioat; ioat = DEVICE2SOFTC(device); ctx = device_get_sysctl_ctx(device); tree = device_get_sysctl_tree(device); par = SYSCTL_CHILDREN(tree); SYSCTL_ADD_INT(ctx, par, OID_AUTO, "version", CTLFLAG_RD, &ioat->version, 0, "HW version (0xMM form)"); SYSCTL_ADD_UINT(ctx, par, OID_AUTO, "max_xfer_size", CTLFLAG_RD, &ioat->max_xfer_size, 0, "HW maximum transfer size"); SYSCTL_ADD_INT(ctx, par, OID_AUTO, "intrdelay_supported", CTLFLAG_RD, &ioat->intrdelay_supported, 0, "Is INTRDELAY supported"); SYSCTL_ADD_U16(ctx, par, OID_AUTO, "intrdelay_max", CTLFLAG_RD, &ioat->intrdelay_max, 0, "Maximum configurable INTRDELAY on this channel (microseconds)"); tmp = SYSCTL_ADD_NODE(ctx, par, OID_AUTO, "state", CTLFLAG_RD, NULL, "IOAT channel internal state"); state = SYSCTL_CHILDREN(tmp); SYSCTL_ADD_UINT(ctx, state, OID_AUTO, "ring_size_order", CTLFLAG_RD, &ioat->ring_size_order, 0, "SW descriptor ring size order"); SYSCTL_ADD_UINT(ctx, state, OID_AUTO, "head", CTLFLAG_RD, &ioat->head, 0, "SW descriptor head pointer index"); SYSCTL_ADD_UINT(ctx, state, OID_AUTO, "tail", CTLFLAG_RD, &ioat->tail, 0, "SW descriptor tail pointer index"); SYSCTL_ADD_UINT(ctx, state, OID_AUTO, "hw_head", CTLFLAG_RD, &ioat->hw_head, 0, "HW DMACOUNT"); SYSCTL_ADD_UQUAD(ctx, state, OID_AUTO, "last_completion", CTLFLAG_RD, ioat->comp_update, "HW addr of last completion"); SYSCTL_ADD_INT(ctx, state, OID_AUTO, "is_resize_pending", CTLFLAG_RD, &ioat->is_resize_pending, 0, "resize pending"); SYSCTL_ADD_INT(ctx, state, OID_AUTO, "is_completion_pending", CTLFLAG_RD, &ioat->is_completion_pending, 0, "completion pending"); SYSCTL_ADD_INT(ctx, state, OID_AUTO, "is_reset_pending", CTLFLAG_RD, &ioat->is_reset_pending, 0, "reset pending"); SYSCTL_ADD_INT(ctx, state, OID_AUTO, "is_channel_running", CTLFLAG_RD, &ioat->is_channel_running, 0, "channel running"); SYSCTL_ADD_PROC(ctx, state, OID_AUTO, "chansts", CTLTYPE_STRING | CTLFLAG_RD, ioat, 0, sysctl_handle_chansts, "A", "String of the channel status"); SYSCTL_ADD_U16(ctx, state, OID_AUTO, "intrdelay", CTLFLAG_RD, &ioat->cached_intrdelay, 0, "Current INTRDELAY on this channel (cached, microseconds)"); tmp = SYSCTL_ADD_NODE(ctx, par, OID_AUTO, "hammer", CTLFLAG_RD, NULL, "Big hammers (mostly for testing)"); hammer = SYSCTL_CHILDREN(tmp); SYSCTL_ADD_PROC(ctx, hammer, OID_AUTO, "force_hw_reset", CTLTYPE_INT | CTLFLAG_RW, ioat, 0, sysctl_handle_reset, "I", "Set to non-zero to reset the hardware"); SYSCTL_ADD_PROC(ctx, hammer, OID_AUTO, "force_hw_error", CTLTYPE_INT | CTLFLAG_RW, ioat, 0, sysctl_handle_error, "I", "Set to non-zero to inject a recoverable hardware error"); tmp = SYSCTL_ADD_NODE(ctx, par, OID_AUTO, "stats", CTLFLAG_RD, NULL, "IOAT channel statistics"); statpar = SYSCTL_CHILDREN(tmp); SYSCTL_ADD_UQUAD(ctx, statpar, OID_AUTO, "interrupts", CTLFLAG_RW, &ioat->stats.interrupts, "Number of interrupts processed on this channel"); SYSCTL_ADD_UQUAD(ctx, statpar, OID_AUTO, "descriptors", CTLFLAG_RW, &ioat->stats.descriptors_processed, "Number of descriptors processed on this channel"); SYSCTL_ADD_UQUAD(ctx, statpar, OID_AUTO, "submitted", CTLFLAG_RW, &ioat->stats.descriptors_submitted, "Number of descriptors submitted to this channel"); SYSCTL_ADD_UQUAD(ctx, statpar, OID_AUTO, "errored", CTLFLAG_RW, &ioat->stats.descriptors_error, "Number of descriptors failed by channel errors"); SYSCTL_ADD_U32(ctx, statpar, OID_AUTO, "halts", CTLFLAG_RW, &ioat->stats.channel_halts, 0, "Number of times the channel has halted"); SYSCTL_ADD_U32(ctx, statpar, OID_AUTO, "last_halt_chanerr", CTLFLAG_RW, &ioat->stats.last_halt_chanerr, 0, "The raw CHANERR when the channel was last halted"); SYSCTL_ADD_PROC(ctx, statpar, OID_AUTO, "desc_per_interrupt", CTLTYPE_STRING | CTLFLAG_RD, ioat, 0, sysctl_handle_dpi, "A", "Descriptors per interrupt"); } static inline struct ioat_softc * ioat_get(struct ioat_softc *ioat, enum ioat_ref_kind kind) { uint32_t old; KASSERT(kind < IOAT_NUM_REF_KINDS, ("bogus")); old = atomic_fetchadd_32(&ioat->refcnt, 1); KASSERT(old < UINT32_MAX, ("refcnt overflow")); #ifdef INVARIANTS old = atomic_fetchadd_32(&ioat->refkinds[kind], 1); KASSERT(old < UINT32_MAX, ("refcnt kind overflow")); #endif return (ioat); } static inline void ioat_putn(struct ioat_softc *ioat, uint32_t n, enum ioat_ref_kind kind) { _ioat_putn(ioat, n, kind, FALSE); } static inline void ioat_putn_locked(struct ioat_softc *ioat, uint32_t n, enum ioat_ref_kind kind) { _ioat_putn(ioat, n, kind, TRUE); } static inline void _ioat_putn(struct ioat_softc *ioat, uint32_t n, enum ioat_ref_kind kind, boolean_t locked) { uint32_t old; KASSERT(kind < IOAT_NUM_REF_KINDS, ("bogus")); if (n == 0) return; #ifdef INVARIANTS old = atomic_fetchadd_32(&ioat->refkinds[kind], -n); KASSERT(old >= n, ("refcnt kind underflow")); #endif /* Skip acquiring the lock if resulting refcnt > 0. */ for (;;) { old = ioat->refcnt; if (old <= n) break; if (atomic_cmpset_32(&ioat->refcnt, old, old - n)) return; } if (locked) mtx_assert(IOAT_REFLK, MA_OWNED); else mtx_lock(IOAT_REFLK); old = atomic_fetchadd_32(&ioat->refcnt, -n); KASSERT(old >= n, ("refcnt error")); if (old == n) wakeup(IOAT_REFLK); if (!locked) mtx_unlock(IOAT_REFLK); } static inline void ioat_put(struct ioat_softc *ioat, enum ioat_ref_kind kind) { ioat_putn(ioat, 1, kind); } static void ioat_drain_locked(struct ioat_softc *ioat) { mtx_assert(IOAT_REFLK, MA_OWNED); while (ioat->refcnt > 0) msleep(IOAT_REFLK, IOAT_REFLK, 0, "ioat_drain", 0); } Index: user/alc/PQ_LAUNDRY/sys/dev/ioat/ioat.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/dev/ioat/ioat.h (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/dev/ioat/ioat.h (revision 292449) @@ -1,130 +1,141 @@ /*- * Copyright (C) 2012 Intel Corporation * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ __FBSDID("$FreeBSD$"); #ifndef __IOAT_H__ #define __IOAT_H__ #include #include /* * This file defines the public interface to the IOAT driver. */ /* * Enables an interrupt for this operation. Typically, you would only enable * this on the last operation in a group */ #define DMA_INT_EN 0x1 /* * Like M_NOWAIT. Operations will return NULL if they cannot allocate a * descriptor without blocking. */ #define DMA_NO_WAIT 0x2 #define DMA_ALL_FLAGS (DMA_INT_EN | DMA_NO_WAIT) +/* + * Hardware revision number. Different hardware revisions support different + * features. For example, 3.2 cannot read from MMIO space, while 3.3 can. + */ +#define IOAT_VER_3_0 0x30 +#define IOAT_VER_3_2 0x32 +#define IOAT_VER_3_3 0x33 + typedef void *bus_dmaengine_t; struct bus_dmadesc; typedef void (*bus_dmaengine_callback_t)(void *arg, int error); /* * Called first to acquire a reference to the DMA channel */ bus_dmaengine_t ioat_get_dmaengine(uint32_t channel_index); /* Release the DMA channel */ void ioat_put_dmaengine(bus_dmaengine_t dmaengine); + +/* Check the DMA engine's HW version */ +int ioat_get_hwversion(bus_dmaengine_t dmaengine); /* * Set interrupt coalescing on a DMA channel. * * The argument is in microseconds. A zero value disables coalescing. Any * other value delays interrupt generation for N microseconds to provide * opportunity to coalesce multiple operations into a single interrupt. * * Returns an error status, or zero on success. * * - ERANGE if the given value exceeds the delay supported by the hardware. * (All current hardware supports a maximum of 0x3fff microseconds delay.) * - ENODEV if the hardware does not support interrupt coalescing. */ int ioat_set_interrupt_coalesce(bus_dmaengine_t dmaengine, uint16_t delay); /* * Return the maximum supported coalescing period, for use in * ioat_set_interrupt_coalesce(). If the hardware does not support coalescing, * returns zero. */ uint16_t ioat_get_max_coalesce_period(bus_dmaengine_t dmaengine); /* * Acquire must be called before issuing an operation to perform. Release is * called after. Multiple operations can be issued within the context of one * acquire and release */ void ioat_acquire(bus_dmaengine_t dmaengine); void ioat_release(bus_dmaengine_t dmaengine); /* * Issue a blockfill operation. The 64-bit pattern 'fillpattern' is written to * 'len' physically contiguous bytes at 'dst'. * * Only supported on devices with the BFILL capability. */ struct bus_dmadesc *ioat_blockfill(bus_dmaengine_t dmaengine, bus_addr_t dst, uint64_t fillpattern, bus_size_t len, bus_dmaengine_callback_t callback_fn, void *callback_arg, uint32_t flags); /* Issues the copy data operation */ struct bus_dmadesc *ioat_copy(bus_dmaengine_t dmaengine, bus_addr_t dst, bus_addr_t src, bus_size_t len, bus_dmaengine_callback_t callback_fn, void *callback_arg, uint32_t flags); /* * Issue a copy data operation, with constraints: * - src1, src2, dst1, dst2 are all page-aligned addresses * - The quantity to copy is exactly 2 pages; * - src1 -> dst1, src2 -> dst2 * * Why use this instead of normal _copy()? You can copy two non-contiguous * pages (src, dst, or both) with one descriptor. */ struct bus_dmadesc *ioat_copy_8k_aligned(bus_dmaengine_t dmaengine, bus_addr_t dst1, bus_addr_t dst2, bus_addr_t src1, bus_addr_t src2, bus_dmaengine_callback_t callback_fn, void *callback_arg, uint32_t flags); /* * Issues a null operation. This issues the operation to the hardware, but the * hardware doesn't do anything with it. */ struct bus_dmadesc *ioat_null(bus_dmaengine_t dmaengine, bus_dmaengine_callback_t callback_fn, void *callback_arg, uint32_t flags); #endif /* __IOAT_H__ */ Index: user/alc/PQ_LAUNDRY/sys/dev/ioat/ioat_hw.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/dev/ioat/ioat_hw.h (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/dev/ioat/ioat_hw.h (revision 292449) @@ -1,164 +1,161 @@ /*- * Copyright (C) 2012 Intel Corporation * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ __FBSDID("$FreeBSD$"); #ifndef __IOAT_HW_H__ #define __IOAT_HW_H__ #define IOAT_MAX_CHANNELS 32 #define IOAT_CHANCNT_OFFSET 0x00 #define IOAT_XFERCAP_OFFSET 0x01 /* Only bits [4:0] are valid. */ #define IOAT_XFERCAP_VALID_MASK 0x1f #define IOAT_GENCTRL_OFFSET 0x02 #define IOAT_INTRCTRL_OFFSET 0x03 #define IOAT_INTRCTRL_MASTER_INT_EN 0x01 #define IOAT_ATTNSTATUS_OFFSET 0x04 #define IOAT_CBVER_OFFSET 0x08 -#define IOAT_VER_3_0 0x30 -#define IOAT_VER_3_3 0x33 - #define IOAT_INTRDELAY_OFFSET 0x0C #define IOAT_INTRDELAY_SUPPORTED (1 << 15) /* Reserved. (1 << 14) */ /* [13:0] is the coalesce period, in microseconds. */ #define IOAT_INTRDELAY_US_MASK ((1 << 14) - 1) #define IOAT_CS_STATUS_OFFSET 0x0E #define IOAT_DMACAPABILITY_OFFSET 0x10 #define IOAT_DMACAP_PB (1 << 0) #define IOAT_DMACAP_DCA (1 << 4) #define IOAT_DMACAP_BFILL (1 << 6) #define IOAT_DMACAP_XOR (1 << 8) #define IOAT_DMACAP_PQ (1 << 9) #define IOAT_DMACAP_DMA_DIF (1 << 10) #define IOAT_DMACAP_DWBES (1 << 13) #define IOAT_DMACAP_RAID16SS (1 << 17) #define IOAT_DMACAP_DMAMC (1 << 18) #define IOAT_DMACAP_CTOS (1 << 19) #define IOAT_DMACAP_STR \ "\20\24Completion_Timeout_Support\23DMA_with_Multicasting_Support" \ "\22RAID_Super_descriptors\16Descriptor_Write_Back_Error_Support" \ "\13DMA_with_DIF\12PQ\11XOR\07Block_Fill\05DCA\01Page_Break" /* DMA Channel Registers */ #define IOAT_CHANCTRL_OFFSET 0x80 #define IOAT_CHANCTRL_CHANNEL_PRIORITY_MASK 0xF000 #define IOAT_CHANCTRL_COMPL_DCA_EN 0x0200 #define IOAT_CHANCTRL_CHANNEL_IN_USE 0x0100 #define IOAT_CHANCTRL_DESCRIPTOR_ADDR_SNOOP_CONTROL 0x0020 #define IOAT_CHANCTRL_ERR_INT_EN 0x0010 #define IOAT_CHANCTRL_ANY_ERR_ABORT_EN 0x0008 #define IOAT_CHANCTRL_ERR_COMPLETION_EN 0x0004 #define IOAT_CHANCTRL_INT_REARM 0x0001 #define IOAT_CHANCTRL_RUN (IOAT_CHANCTRL_INT_REARM |\ IOAT_CHANCTRL_ERR_COMPLETION_EN |\ IOAT_CHANCTRL_ANY_ERR_ABORT_EN |\ IOAT_CHANCTRL_ERR_INT_EN) #define IOAT_CHANCMD_OFFSET 0x84 #define IOAT_CHANCMD_RESET 0x20 #define IOAT_CHANCMD_SUSPEND 0x04 #define IOAT_DMACOUNT_OFFSET 0x86 #define IOAT_CHANSTS_OFFSET_LOW 0x88 #define IOAT_CHANSTS_OFFSET_HIGH 0x8C #define IOAT_CHANSTS_OFFSET 0x88 #define IOAT_CHANSTS_STATUS 0x7ULL #define IOAT_CHANSTS_ACTIVE 0x0 #define IOAT_CHANSTS_IDLE 0x1 #define IOAT_CHANSTS_SUSPENDED 0x2 #define IOAT_CHANSTS_HALTED 0x3 #define IOAT_CHANSTS_ARMED 0x4 #define IOAT_CHANSTS_UNAFFILIATED_ERROR 0x8ULL #define IOAT_CHANSTS_SOFT_ERROR 0x10ULL #define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_MASK (~0x3FULL) #define IOAT_CHAINADDR_OFFSET_LOW 0x90 #define IOAT_CHAINADDR_OFFSET_HIGH 0x94 #define IOAT_CHANCMP_OFFSET_LOW 0x98 #define IOAT_CHANCMP_OFFSET_HIGH 0x9C #define IOAT_CHANERR_OFFSET 0xA8 #define IOAT_CHANERR_XSADDERR (1 << 0) #define IOAT_CHANERR_XDADDERR (1 << 1) #define IOAT_CHANERR_NDADDERR (1 << 2) #define IOAT_CHANERR_DERR (1 << 3) #define IOAT_CHANERR_CHADDERR (1 << 4) #define IOAT_CHANERR_CCMDERR (1 << 5) #define IOAT_CHANERR_CUNCORERR (1 << 6) #define IOAT_CHANERR_DUNCORERR (1 << 7) #define IOAT_CHANERR_RDERR (1 << 8) #define IOAT_CHANERR_WDERR (1 << 9) #define IOAT_CHANERR_DCERR (1 << 10) #define IOAT_CHANERR_DXSERR (1 << 11) #define IOAT_CHANERR_CMPADDERR (1 << 12) #define IOAT_CHANERR_INTCFGERR (1 << 13) #define IOAT_CHANERR_SEDERR (1 << 14) #define IOAT_CHANERR_UNAFFERR (1 << 15) #define IOAT_CHANERR_CXPERR (1 << 16) /* Reserved. (1 << 17) */ #define IOAT_CHANERR_DCNTERR (1 << 18) #define IOAT_CHANERR_DIFFERR (1 << 19) #define IOAT_CHANERR_GTVERR (1 << 20) #define IOAT_CHANERR_ATVERR (1 << 21) #define IOAT_CHANERR_RTVERR (1 << 22) #define IOAT_CHANERR_BBERR (1 << 23) #define IOAT_CHANERR_RDIFFERR (1 << 24) #define IOAT_CHANERR_RGTVERR (1 << 25) #define IOAT_CHANERR_RATVERR (1 << 26) #define IOAT_CHANERR_RRTVERR (1 << 27) #define IOAT_CHANERR_STR \ "\20\34RRTVERR\33RATVERR\32RGTVERR\31RDIFFERR\30BBERR\27RTVERR\26ATVERR" \ "\25GTVERR\24DIFFERR\23DCNTERR\21CXPERR\20UNAFFERR\17SEDERR\16INTCFGERR" \ "\15CMPADDERR\14DXSERR\13DCERR\12WDERR\11RDERR\10DUNCORERR\07CUNCORERR" \ "\06CCMDERR\05CHADDERR\04DERR\03NDADDERR\02XDADDERR\01XSADDERR" #define IOAT_CFG_CHANERR_INT_OFFSET 0x180 #define IOAT_CFG_CHANERRMASK_INT_OFFSET 0x184 #define IOAT_MIN_ORDER 4 #define IOAT_MAX_ORDER 16 #endif /* __IOAT_HW_H__ */ Index: user/alc/PQ_LAUNDRY/sys/dev/mmc/mmc.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/dev/mmc/mmc.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/dev/mmc/mmc.c (revision 292449) @@ -1,1813 +1,1813 @@ /*- * Copyright (c) 2006 Bernd Walter. All rights reserved. * Copyright (c) 2006 M. Warner Losh. 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. * * Portions of this software may have been developed with reference to * the SD Simplified Specification. The following disclaimer may apply: * * The following conditions apply to the release of the simplified * specification ("Simplified Specification") by the SD Card Association and * the SD Group. The Simplified Specification is a subset of the complete SD * Specification which is owned by the SD Card Association and the SD * Group. This Simplified Specification is provided on a non-confidential * basis subject to the disclaimers below. Any implementation of the * Simplified Specification may require a license from the SD Card * Association, SD Group, SD-3C LLC or other third parties. * * Disclaimers: * * The information contained in the Simplified Specification is presented only * as a standard specification for SD Cards and SD Host/Ancillary products and * is provided "AS-IS" without any representations or warranties of any * kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD * Card Association for any damages, any infringements of patents or other * right of the SD Group, SD-3C LLC, the SD Card Association or any third * parties, which may result from its use. No license is granted by * implication, estoppel or otherwise under any patent or other rights of the * SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing * herein shall be construed as an obligation by the SD Group, the SD-3C LLC * or the SD Card Association to disclose or distribute any technical * information, know-how or other confidential information to any third party. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mmcbr_if.h" #include "mmcbus_if.h" struct mmc_softc { device_t dev; struct mtx sc_mtx; struct intr_config_hook config_intrhook; device_t owner; uint32_t last_rca; int squelched; /* suppress reporting of (expected) errors */ int log_count; struct timeval log_time; }; #define LOG_PPS 5 /* Log no more than 5 errors per second. */ /* * Per-card data */ struct mmc_ivars { uint32_t raw_cid[4]; /* Raw bits of the CID */ uint32_t raw_csd[4]; /* Raw bits of the CSD */ uint32_t raw_scr[2]; /* Raw bits of the SCR */ uint8_t raw_ext_csd[512]; /* Raw bits of the EXT_CSD */ uint32_t raw_sd_status[16]; /* Raw bits of the SD_STATUS */ uint16_t rca; enum mmc_card_mode mode; struct mmc_cid cid; /* cid decoded */ struct mmc_csd csd; /* csd decoded */ struct mmc_scr scr; /* scr decoded */ struct mmc_sd_status sd_status; /* SD_STATUS decoded */ u_char read_only; /* True when the device is read-only */ u_char bus_width; /* Bus width to use */ u_char timing; /* Bus timing support */ u_char high_cap; /* High Capacity card (block addressed) */ uint32_t sec_count; /* Card capacity in 512byte blocks */ uint32_t tran_speed; /* Max speed in normal mode */ uint32_t hs_tran_speed; /* Max speed in high speed mode */ uint32_t erase_sector; /* Card native erase sector size */ char card_id_string[64];/* Formatted CID info (serial, MFG, etc) */ char card_sn_string[16];/* Formatted serial # for disk->d_ident */ }; #define CMD_RETRIES 3 #define CARD_ID_FREQUENCY 400000 /* Spec requires 400kHz max during ID phase. */ static SYSCTL_NODE(_hw, OID_AUTO, mmc, CTLFLAG_RD, NULL, "mmc driver"); static int mmc_debug; -SYSCTL_INT(_hw_mmc, OID_AUTO, debug, CTLFLAG_RW, &mmc_debug, 0, "Debug level"); +SYSCTL_INT(_hw_mmc, OID_AUTO, debug, CTLFLAG_RWTUN, &mmc_debug, 0, "Debug level"); /* bus entry points */ static int mmc_acquire_bus(device_t busdev, device_t dev); static int mmc_attach(device_t dev); static int mmc_child_location_str(device_t dev, device_t child, char *buf, size_t buflen); static int mmc_detach(device_t dev); static int mmc_probe(device_t dev); static int mmc_read_ivar(device_t bus, device_t child, int which, uintptr_t *result); static int mmc_release_bus(device_t busdev, device_t dev); static int mmc_resume(device_t dev); static int mmc_suspend(device_t dev); static int mmc_wait_for_request(device_t brdev, device_t reqdev, struct mmc_request *req); static int mmc_write_ivar(device_t bus, device_t child, int which, uintptr_t value); #define MMC_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) #define MMC_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) #define MMC_LOCK_INIT(_sc) \ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \ "mmc", MTX_DEF) #define MMC_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); #define MMC_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); #define MMC_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); static int mmc_all_send_cid(struct mmc_softc *sc, uint32_t *rawcid); static void mmc_app_decode_scr(uint32_t *raw_scr, struct mmc_scr *scr); static void mmc_app_decode_sd_status(uint32_t *raw_sd_status, struct mmc_sd_status *sd_status); static int mmc_app_sd_status(struct mmc_softc *sc, uint16_t rca, uint32_t *rawsdstatus); static int mmc_app_send_scr(struct mmc_softc *sc, uint16_t rca, uint32_t *rawscr); static int mmc_calculate_clock(struct mmc_softc *sc); static void mmc_decode_cid_mmc(uint32_t *raw_cid, struct mmc_cid *cid); static void mmc_decode_cid_sd(uint32_t *raw_cid, struct mmc_cid *cid); static void mmc_decode_csd_mmc(uint32_t *raw_csd, struct mmc_csd *csd); static void mmc_decode_csd_sd(uint32_t *raw_csd, struct mmc_csd *csd); static void mmc_delayed_attach(void *xsc); static int mmc_delete_cards(struct mmc_softc *sc); static void mmc_discover_cards(struct mmc_softc *sc); static void mmc_format_card_id_string(struct mmc_ivars *ivar); static void mmc_go_discovery(struct mmc_softc *sc); static uint32_t mmc_get_bits(uint32_t *bits, int bit_len, int start, int size); static int mmc_highest_voltage(uint32_t ocr); static void mmc_idle_cards(struct mmc_softc *sc); static void mmc_ms_delay(int ms); static void mmc_log_card(device_t dev, struct mmc_ivars *ivar, int newcard); static void mmc_power_down(struct mmc_softc *sc); static void mmc_power_up(struct mmc_softc *sc); static void mmc_rescan_cards(struct mmc_softc *sc); static void mmc_scan(struct mmc_softc *sc); static int mmc_sd_switch(struct mmc_softc *sc, uint8_t mode, uint8_t grp, uint8_t value, uint8_t *res); static int mmc_select_card(struct mmc_softc *sc, uint16_t rca); static uint32_t mmc_select_vdd(struct mmc_softc *sc, uint32_t ocr); static int mmc_send_app_op_cond(struct mmc_softc *sc, uint32_t ocr, uint32_t *rocr); static int mmc_send_csd(struct mmc_softc *sc, uint16_t rca, uint32_t *rawcsd); static int mmc_send_ext_csd(struct mmc_softc *sc, uint8_t *rawextcsd); static int mmc_send_if_cond(struct mmc_softc *sc, uint8_t vhs); static int mmc_send_op_cond(struct mmc_softc *sc, uint32_t ocr, uint32_t *rocr); static int mmc_send_relative_addr(struct mmc_softc *sc, uint32_t *resp); static int mmc_send_status(struct mmc_softc *sc, uint16_t rca, uint32_t *status); static int mmc_set_blocklen(struct mmc_softc *sc, uint32_t len); static int mmc_set_card_bus_width(struct mmc_softc *sc, uint16_t rca, int width); static int mmc_set_relative_addr(struct mmc_softc *sc, uint16_t resp); static int mmc_set_timing(struct mmc_softc *sc, int timing); static int mmc_switch(struct mmc_softc *sc, uint8_t set, uint8_t index, uint8_t value); static int mmc_test_bus_width(struct mmc_softc *sc); static int mmc_wait_for_app_cmd(struct mmc_softc *sc, uint32_t rca, struct mmc_command *cmd, int retries); static int mmc_wait_for_cmd(struct mmc_softc *sc, struct mmc_command *cmd, int retries); static int mmc_wait_for_command(struct mmc_softc *sc, uint32_t opcode, uint32_t arg, uint32_t flags, uint32_t *resp, int retries); static int mmc_wait_for_req(struct mmc_softc *sc, struct mmc_request *req); static void mmc_wakeup(struct mmc_request *req); static void mmc_ms_delay(int ms) { DELAY(1000 * ms); /* XXX BAD */ } static int mmc_probe(device_t dev) { device_set_desc(dev, "MMC/SD bus"); return (0); } static int mmc_attach(device_t dev) { struct mmc_softc *sc; sc = device_get_softc(dev); sc->dev = dev; MMC_LOCK_INIT(sc); /* We'll probe and attach our children later, but before / mount */ sc->config_intrhook.ich_func = mmc_delayed_attach; sc->config_intrhook.ich_arg = sc; if (config_intrhook_establish(&sc->config_intrhook) != 0) device_printf(dev, "config_intrhook_establish failed\n"); return (0); } static int mmc_detach(device_t dev) { struct mmc_softc *sc = device_get_softc(dev); int err; if ((err = mmc_delete_cards(sc)) != 0) return (err); mmc_power_down(sc); MMC_LOCK_DESTROY(sc); return (0); } static int mmc_suspend(device_t dev) { struct mmc_softc *sc = device_get_softc(dev); int err; err = bus_generic_suspend(dev); if (err) return (err); mmc_power_down(sc); return (0); } static int mmc_resume(device_t dev) { struct mmc_softc *sc = device_get_softc(dev); mmc_scan(sc); return (bus_generic_resume(dev)); } static int mmc_acquire_bus(device_t busdev, device_t dev) { struct mmc_softc *sc; struct mmc_ivars *ivar; int err; int rca; err = MMCBR_ACQUIRE_HOST(device_get_parent(busdev), busdev); if (err) return (err); sc = device_get_softc(busdev); MMC_LOCK(sc); if (sc->owner) panic("mmc: host bridge didn't serialize us."); sc->owner = dev; MMC_UNLOCK(sc); if (busdev != dev) { /* * Keep track of the last rca that we've selected. If * we're asked to do it again, don't. We never * unselect unless the bus code itself wants the mmc * bus, and constantly reselecting causes problems. */ rca = mmc_get_rca(dev); if (sc->last_rca != rca) { mmc_select_card(sc, rca); sc->last_rca = rca; /* Prepare bus width for the new card. */ ivar = device_get_ivars(dev); if (bootverbose || mmc_debug) { device_printf(busdev, "setting bus width to %d bits\n", (ivar->bus_width == bus_width_4) ? 4 : (ivar->bus_width == bus_width_8) ? 8 : 1); } mmc_set_card_bus_width(sc, rca, ivar->bus_width); mmcbr_set_bus_width(busdev, ivar->bus_width); mmcbr_update_ios(busdev); } } else { /* * If there's a card selected, stand down. */ if (sc->last_rca != 0) { mmc_select_card(sc, 0); sc->last_rca = 0; } } return (0); } static int mmc_release_bus(device_t busdev, device_t dev) { struct mmc_softc *sc; int err; sc = device_get_softc(busdev); MMC_LOCK(sc); if (!sc->owner) panic("mmc: releasing unowned bus."); if (sc->owner != dev) panic("mmc: you don't own the bus. game over."); MMC_UNLOCK(sc); err = MMCBR_RELEASE_HOST(device_get_parent(busdev), busdev); if (err) return (err); MMC_LOCK(sc); sc->owner = NULL; MMC_UNLOCK(sc); return (0); } static uint32_t mmc_select_vdd(struct mmc_softc *sc, uint32_t ocr) { return (ocr & MMC_OCR_VOLTAGE); } static int mmc_highest_voltage(uint32_t ocr) { int i; for (i = MMC_OCR_MAX_VOLTAGE_SHIFT; i >= MMC_OCR_MIN_VOLTAGE_SHIFT; i--) if (ocr & (1 << i)) return (i); return (-1); } static void mmc_wakeup(struct mmc_request *req) { struct mmc_softc *sc; sc = (struct mmc_softc *)req->done_data; MMC_LOCK(sc); req->flags |= MMC_REQ_DONE; MMC_UNLOCK(sc); wakeup(req); } static int mmc_wait_for_req(struct mmc_softc *sc, struct mmc_request *req) { req->done = mmc_wakeup; req->done_data = sc; if (mmc_debug > 1) { device_printf(sc->dev, "REQUEST: CMD%d arg %#x flags %#x", req->cmd->opcode, req->cmd->arg, req->cmd->flags); if (req->cmd->data) { printf(" data %d\n", (int)req->cmd->data->len); } else printf("\n"); } MMCBR_REQUEST(device_get_parent(sc->dev), sc->dev, req); MMC_LOCK(sc); while ((req->flags & MMC_REQ_DONE) == 0) msleep(req, &sc->sc_mtx, 0, "mmcreq", 0); MMC_UNLOCK(sc); if (mmc_debug > 2 || (mmc_debug > 0 && req->cmd->error != MMC_ERR_NONE)) device_printf(sc->dev, "CMD%d RESULT: %d\n", req->cmd->opcode, req->cmd->error); return (0); } static int mmc_wait_for_request(device_t brdev, device_t reqdev, struct mmc_request *req) { struct mmc_softc *sc = device_get_softc(brdev); return (mmc_wait_for_req(sc, req)); } static int mmc_wait_for_cmd(struct mmc_softc *sc, struct mmc_command *cmd, int retries) { struct mmc_request mreq; int err; do { memset(&mreq, 0, sizeof(mreq)); memset(cmd->resp, 0, sizeof(cmd->resp)); cmd->retries = 0; /* Retries done here, not in hardware. */ cmd->mrq = &mreq; mreq.cmd = cmd; if (mmc_wait_for_req(sc, &mreq) != 0) err = MMC_ERR_FAILED; else err = cmd->error; } while (err != MMC_ERR_NONE && retries-- > 0); if (err != MMC_ERR_NONE && sc->squelched == 0) { if (ppsratecheck(&sc->log_time, &sc->log_count, LOG_PPS)) { device_printf(sc->dev, "CMD%d failed, RESULT: %d\n", cmd->opcode, err); } } return (err); } static int mmc_wait_for_app_cmd(struct mmc_softc *sc, uint32_t rca, struct mmc_command *cmd, int retries) { struct mmc_command appcmd; int err; /* Squelch error reporting at lower levels, we report below. */ sc->squelched++; do { memset(&appcmd, 0, sizeof(appcmd)); appcmd.opcode = MMC_APP_CMD; appcmd.arg = rca << 16; appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC; appcmd.data = NULL; if (mmc_wait_for_cmd(sc, &appcmd, 0) != 0) err = MMC_ERR_FAILED; else err = appcmd.error; if (err == MMC_ERR_NONE) { if (!(appcmd.resp[0] & R1_APP_CMD)) err = MMC_ERR_FAILED; else if (mmc_wait_for_cmd(sc, cmd, 0) != 0) err = MMC_ERR_FAILED; else err = cmd->error; } } while (err != MMC_ERR_NONE && retries-- > 0); sc->squelched--; if (err != MMC_ERR_NONE && sc->squelched == 0) { if (ppsratecheck(&sc->log_time, &sc->log_count, LOG_PPS)) { device_printf(sc->dev, "ACMD%d failed, RESULT: %d\n", cmd->opcode, err); } } return (err); } static int mmc_wait_for_command(struct mmc_softc *sc, uint32_t opcode, uint32_t arg, uint32_t flags, uint32_t *resp, int retries) { struct mmc_command cmd; int err; memset(&cmd, 0, sizeof(cmd)); cmd.opcode = opcode; cmd.arg = arg; cmd.flags = flags; cmd.data = NULL; err = mmc_wait_for_cmd(sc, &cmd, retries); if (err) return (err); if (resp) { if (flags & MMC_RSP_136) memcpy(resp, cmd.resp, 4 * sizeof(uint32_t)); else *resp = cmd.resp[0]; } return (0); } static void mmc_idle_cards(struct mmc_softc *sc) { device_t dev; struct mmc_command cmd; dev = sc->dev; mmcbr_set_chip_select(dev, cs_high); mmcbr_update_ios(dev); mmc_ms_delay(1); memset(&cmd, 0, sizeof(cmd)); cmd.opcode = MMC_GO_IDLE_STATE; cmd.arg = 0; cmd.flags = MMC_RSP_NONE | MMC_CMD_BC; cmd.data = NULL; mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES); mmc_ms_delay(1); mmcbr_set_chip_select(dev, cs_dontcare); mmcbr_update_ios(dev); mmc_ms_delay(1); } static int mmc_send_app_op_cond(struct mmc_softc *sc, uint32_t ocr, uint32_t *rocr) { struct mmc_command cmd; int err = MMC_ERR_NONE, i; memset(&cmd, 0, sizeof(cmd)); cmd.opcode = ACMD_SD_SEND_OP_COND; cmd.arg = ocr; cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR; cmd.data = NULL; for (i = 0; i < 1000; i++) { err = mmc_wait_for_app_cmd(sc, 0, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE) break; if ((cmd.resp[0] & MMC_OCR_CARD_BUSY) || (ocr & MMC_OCR_VOLTAGE) == 0) break; err = MMC_ERR_TIMEOUT; mmc_ms_delay(10); } if (rocr && err == MMC_ERR_NONE) *rocr = cmd.resp[0]; return (err); } static int mmc_send_op_cond(struct mmc_softc *sc, uint32_t ocr, uint32_t *rocr) { struct mmc_command cmd; int err = MMC_ERR_NONE, i; memset(&cmd, 0, sizeof(cmd)); cmd.opcode = MMC_SEND_OP_COND; cmd.arg = ocr; cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR; cmd.data = NULL; for (i = 0; i < 1000; i++) { err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE) break; if ((cmd.resp[0] & MMC_OCR_CARD_BUSY) || (ocr & MMC_OCR_VOLTAGE) == 0) break; err = MMC_ERR_TIMEOUT; mmc_ms_delay(10); } if (rocr && err == MMC_ERR_NONE) *rocr = cmd.resp[0]; return (err); } static int mmc_send_if_cond(struct mmc_softc *sc, uint8_t vhs) { struct mmc_command cmd; int err; memset(&cmd, 0, sizeof(cmd)); cmd.opcode = SD_SEND_IF_COND; cmd.arg = (vhs << 8) + 0xAA; cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR; cmd.data = NULL; err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES); return (err); } static void mmc_power_up(struct mmc_softc *sc) { device_t dev; dev = sc->dev; mmcbr_set_vdd(dev, mmc_highest_voltage(mmcbr_get_host_ocr(dev))); mmcbr_set_bus_mode(dev, opendrain); mmcbr_set_chip_select(dev, cs_dontcare); mmcbr_set_bus_width(dev, bus_width_1); mmcbr_set_power_mode(dev, power_up); mmcbr_set_clock(dev, 0); mmcbr_update_ios(dev); mmc_ms_delay(1); mmcbr_set_clock(dev, CARD_ID_FREQUENCY); mmcbr_set_timing(dev, bus_timing_normal); mmcbr_set_power_mode(dev, power_on); mmcbr_update_ios(dev); mmc_ms_delay(2); } static void mmc_power_down(struct mmc_softc *sc) { device_t dev = sc->dev; mmcbr_set_bus_mode(dev, opendrain); mmcbr_set_chip_select(dev, cs_dontcare); mmcbr_set_bus_width(dev, bus_width_1); mmcbr_set_power_mode(dev, power_off); mmcbr_set_clock(dev, 0); mmcbr_set_timing(dev, bus_timing_normal); mmcbr_update_ios(dev); } static int mmc_select_card(struct mmc_softc *sc, uint16_t rca) { int flags; flags = (rca ? MMC_RSP_R1B : MMC_RSP_NONE) | MMC_CMD_AC; return (mmc_wait_for_command(sc, MMC_SELECT_CARD, (uint32_t)rca << 16, flags, NULL, CMD_RETRIES)); } static int mmc_switch(struct mmc_softc *sc, uint8_t set, uint8_t index, uint8_t value) { struct mmc_command cmd; int err; memset(&cmd, 0, sizeof(cmd)); cmd.opcode = MMC_SWITCH_FUNC; cmd.arg = (MMC_SWITCH_FUNC_WR << 24) | (index << 16) | (value << 8) | set; cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; cmd.data = NULL; err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES); return (err); } static int mmc_sd_switch(struct mmc_softc *sc, uint8_t mode, uint8_t grp, uint8_t value, uint8_t *res) { int err; struct mmc_command cmd; struct mmc_data data; memset(&cmd, 0, sizeof(cmd)); memset(&data, 0, sizeof(data)); memset(res, 0, 64); cmd.opcode = SD_SWITCH_FUNC; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; cmd.arg = mode << 31; /* 0 - check, 1 - set */ cmd.arg |= 0x00FFFFFF; cmd.arg &= ~(0xF << (grp * 4)); cmd.arg |= value << (grp * 4); cmd.data = &data; data.data = res; data.len = 64; data.flags = MMC_DATA_READ; err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES); return (err); } static int mmc_set_card_bus_width(struct mmc_softc *sc, uint16_t rca, int width) { struct mmc_command cmd; int err; uint8_t value; if (mmcbr_get_mode(sc->dev) == mode_sd) { memset(&cmd, 0, sizeof(cmd)); cmd.opcode = ACMD_SET_CLR_CARD_DETECT; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; cmd.arg = SD_CLR_CARD_DETECT; err = mmc_wait_for_app_cmd(sc, rca, &cmd, CMD_RETRIES); if (err != 0) return (err); memset(&cmd, 0, sizeof(cmd)); cmd.opcode = ACMD_SET_BUS_WIDTH; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; switch (width) { case bus_width_1: cmd.arg = SD_BUS_WIDTH_1; break; case bus_width_4: cmd.arg = SD_BUS_WIDTH_4; break; default: return (MMC_ERR_INVALID); } err = mmc_wait_for_app_cmd(sc, rca, &cmd, CMD_RETRIES); } else { switch (width) { case bus_width_1: value = EXT_CSD_BUS_WIDTH_1; break; case bus_width_4: value = EXT_CSD_BUS_WIDTH_4; break; case bus_width_8: value = EXT_CSD_BUS_WIDTH_8; break; default: return (MMC_ERR_INVALID); } err = mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, value); } return (err); } static int mmc_set_timing(struct mmc_softc *sc, int timing) { int err; uint8_t value; u_char switch_res[64]; switch (timing) { case bus_timing_normal: value = 0; break; case bus_timing_hs: value = 1; break; default: return (MMC_ERR_INVALID); } if (mmcbr_get_mode(sc->dev) == mode_sd) err = mmc_sd_switch(sc, SD_SWITCH_MODE_SET, SD_SWITCH_GROUP1, value, switch_res); else err = mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, value); return (err); } static int mmc_test_bus_width(struct mmc_softc *sc) { struct mmc_command cmd; struct mmc_data data; int err; uint8_t buf[8]; uint8_t p8[8] = { 0x55, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t p8ok[8] = { 0xAA, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t p4[4] = { 0x5A, 0x00, 0x00, 0x00, }; uint8_t p4ok[4] = { 0xA5, 0x00, 0x00, 0x00, }; if (mmcbr_get_caps(sc->dev) & MMC_CAP_8_BIT_DATA) { mmcbr_set_bus_width(sc->dev, bus_width_8); mmcbr_update_ios(sc->dev); sc->squelched++; /* Errors are expected, squelch reporting. */ memset(&cmd, 0, sizeof(cmd)); memset(&data, 0, sizeof(data)); cmd.opcode = MMC_BUSTEST_W; cmd.arg = 0; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; cmd.data = &data; data.data = p8; data.len = 8; data.flags = MMC_DATA_WRITE; mmc_wait_for_cmd(sc, &cmd, 0); memset(&cmd, 0, sizeof(cmd)); memset(&data, 0, sizeof(data)); cmd.opcode = MMC_BUSTEST_R; cmd.arg = 0; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; cmd.data = &data; data.data = buf; data.len = 8; data.flags = MMC_DATA_READ; err = mmc_wait_for_cmd(sc, &cmd, 0); sc->squelched--; mmcbr_set_bus_width(sc->dev, bus_width_1); mmcbr_update_ios(sc->dev); if (err == MMC_ERR_NONE && memcmp(buf, p8ok, 8) == 0) return (bus_width_8); } if (mmcbr_get_caps(sc->dev) & MMC_CAP_4_BIT_DATA) { mmcbr_set_bus_width(sc->dev, bus_width_4); mmcbr_update_ios(sc->dev); sc->squelched++; /* Errors are expected, squelch reporting. */ memset(&cmd, 0, sizeof(cmd)); memset(&data, 0, sizeof(data)); cmd.opcode = MMC_BUSTEST_W; cmd.arg = 0; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; cmd.data = &data; data.data = p4; data.len = 4; data.flags = MMC_DATA_WRITE; mmc_wait_for_cmd(sc, &cmd, 0); memset(&cmd, 0, sizeof(cmd)); memset(&data, 0, sizeof(data)); cmd.opcode = MMC_BUSTEST_R; cmd.arg = 0; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; cmd.data = &data; data.data = buf; data.len = 4; data.flags = MMC_DATA_READ; err = mmc_wait_for_cmd(sc, &cmd, 0); sc->squelched--; mmcbr_set_bus_width(sc->dev, bus_width_1); mmcbr_update_ios(sc->dev); if (err == MMC_ERR_NONE && memcmp(buf, p4ok, 4) == 0) return (bus_width_4); } return (bus_width_1); } static uint32_t mmc_get_bits(uint32_t *bits, int bit_len, int start, int size) { const int i = (bit_len / 32) - (start / 32) - 1; const int shift = start & 31; uint32_t retval = bits[i] >> shift; if (size + shift > 32) retval |= bits[i - 1] << (32 - shift); return (retval & ((1llu << size) - 1)); } static void mmc_decode_cid_sd(uint32_t *raw_cid, struct mmc_cid *cid) { int i; /* There's no version info, so we take it on faith */ memset(cid, 0, sizeof(*cid)); cid->mid = mmc_get_bits(raw_cid, 128, 120, 8); cid->oid = mmc_get_bits(raw_cid, 128, 104, 16); for (i = 0; i < 5; i++) cid->pnm[i] = mmc_get_bits(raw_cid, 128, 96 - i * 8, 8); cid->pnm[5] = 0; cid->prv = mmc_get_bits(raw_cid, 128, 56, 8); cid->psn = mmc_get_bits(raw_cid, 128, 24, 32); cid->mdt_year = mmc_get_bits(raw_cid, 128, 12, 8) + 2000; cid->mdt_month = mmc_get_bits(raw_cid, 128, 8, 4); } static void mmc_decode_cid_mmc(uint32_t *raw_cid, struct mmc_cid *cid) { int i; /* There's no version info, so we take it on faith */ memset(cid, 0, sizeof(*cid)); cid->mid = mmc_get_bits(raw_cid, 128, 120, 8); cid->oid = mmc_get_bits(raw_cid, 128, 104, 8); for (i = 0; i < 6; i++) cid->pnm[i] = mmc_get_bits(raw_cid, 128, 96 - i * 8, 8); cid->pnm[6] = 0; cid->prv = mmc_get_bits(raw_cid, 128, 48, 8); cid->psn = mmc_get_bits(raw_cid, 128, 16, 32); cid->mdt_month = mmc_get_bits(raw_cid, 128, 12, 4); cid->mdt_year = mmc_get_bits(raw_cid, 128, 8, 4) + 1997; } static void mmc_format_card_id_string(struct mmc_ivars *ivar) { char oidstr[8]; uint8_t c1; uint8_t c2; /* * Format a card ID string for use by the mmcsd driver, it's what * appears between the <> in the following: * mmcsd0: 968MB at mmc0 * 22.5MHz/4bit/128-block * * Also format just the card serial number, which the mmcsd driver will * use as the disk->d_ident string. * * The card_id_string in mmc_ivars is currently allocated as 64 bytes, * and our max formatted length is currently 55 bytes if every field * contains the largest value. * * Sometimes the oid is two printable ascii chars; when it's not, * format it as 0xnnnn instead. */ c1 = (ivar->cid.oid >> 8) & 0x0ff; c2 = ivar->cid.oid & 0x0ff; if (c1 > 0x1f && c1 < 0x7f && c2 > 0x1f && c2 < 0x7f) snprintf(oidstr, sizeof(oidstr), "%c%c", c1, c2); else snprintf(oidstr, sizeof(oidstr), "0x%04x", ivar->cid.oid); snprintf(ivar->card_sn_string, sizeof(ivar->card_sn_string), "%08X", ivar->cid.psn); snprintf(ivar->card_id_string, sizeof(ivar->card_id_string), "%s%s %s %d.%d SN %08X MFG %02d/%04d by %d %s", ivar->mode == mode_sd ? "SD" : "MMC", ivar->high_cap ? "HC" : "", ivar->cid.pnm, ivar->cid.prv >> 4, ivar->cid.prv & 0x0f, ivar->cid.psn, ivar->cid.mdt_month, ivar->cid.mdt_year, ivar->cid.mid, oidstr); } static const int exp[8] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000 }; static const int mant[16] = { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 }; static const int cur_min[8] = { 500, 1000, 5000, 10000, 25000, 35000, 60000, 100000 }; static const int cur_max[8] = { 1000, 5000, 10000, 25000, 35000, 45000, 800000, 200000 }; static void mmc_decode_csd_sd(uint32_t *raw_csd, struct mmc_csd *csd) { int v; int m; int e; memset(csd, 0, sizeof(*csd)); csd->csd_structure = v = mmc_get_bits(raw_csd, 128, 126, 2); if (v == 0) { m = mmc_get_bits(raw_csd, 128, 115, 4); e = mmc_get_bits(raw_csd, 128, 112, 3); csd->tacc = (exp[e] * mant[m] + 9) / 10; csd->nsac = mmc_get_bits(raw_csd, 128, 104, 8) * 100; m = mmc_get_bits(raw_csd, 128, 99, 4); e = mmc_get_bits(raw_csd, 128, 96, 3); csd->tran_speed = exp[e] * 10000 * mant[m]; csd->ccc = mmc_get_bits(raw_csd, 128, 84, 12); csd->read_bl_len = 1 << mmc_get_bits(raw_csd, 128, 80, 4); csd->read_bl_partial = mmc_get_bits(raw_csd, 128, 79, 1); csd->write_blk_misalign = mmc_get_bits(raw_csd, 128, 78, 1); csd->read_blk_misalign = mmc_get_bits(raw_csd, 128, 77, 1); csd->dsr_imp = mmc_get_bits(raw_csd, 128, 76, 1); csd->vdd_r_curr_min = cur_min[mmc_get_bits(raw_csd, 128, 59, 3)]; csd->vdd_r_curr_max = cur_max[mmc_get_bits(raw_csd, 128, 56, 3)]; csd->vdd_w_curr_min = cur_min[mmc_get_bits(raw_csd, 128, 53, 3)]; csd->vdd_w_curr_max = cur_max[mmc_get_bits(raw_csd, 128, 50, 3)]; m = mmc_get_bits(raw_csd, 128, 62, 12); e = mmc_get_bits(raw_csd, 128, 47, 3); csd->capacity = ((1 + m) << (e + 2)) * csd->read_bl_len; csd->erase_blk_en = mmc_get_bits(raw_csd, 128, 46, 1); csd->erase_sector = mmc_get_bits(raw_csd, 128, 39, 7) + 1; csd->wp_grp_size = mmc_get_bits(raw_csd, 128, 32, 7); csd->wp_grp_enable = mmc_get_bits(raw_csd, 128, 31, 1); csd->r2w_factor = 1 << mmc_get_bits(raw_csd, 128, 26, 3); csd->write_bl_len = 1 << mmc_get_bits(raw_csd, 128, 22, 4); csd->write_bl_partial = mmc_get_bits(raw_csd, 128, 21, 1); } else if (v == 1) { m = mmc_get_bits(raw_csd, 128, 115, 4); e = mmc_get_bits(raw_csd, 128, 112, 3); csd->tacc = (exp[e] * mant[m] + 9) / 10; csd->nsac = mmc_get_bits(raw_csd, 128, 104, 8) * 100; m = mmc_get_bits(raw_csd, 128, 99, 4); e = mmc_get_bits(raw_csd, 128, 96, 3); csd->tran_speed = exp[e] * 10000 * mant[m]; csd->ccc = mmc_get_bits(raw_csd, 128, 84, 12); csd->read_bl_len = 1 << mmc_get_bits(raw_csd, 128, 80, 4); csd->read_bl_partial = mmc_get_bits(raw_csd, 128, 79, 1); csd->write_blk_misalign = mmc_get_bits(raw_csd, 128, 78, 1); csd->read_blk_misalign = mmc_get_bits(raw_csd, 128, 77, 1); csd->dsr_imp = mmc_get_bits(raw_csd, 128, 76, 1); csd->capacity = ((uint64_t)mmc_get_bits(raw_csd, 128, 48, 22) + 1) * 512 * 1024; csd->erase_blk_en = mmc_get_bits(raw_csd, 128, 46, 1); csd->erase_sector = mmc_get_bits(raw_csd, 128, 39, 7) + 1; csd->wp_grp_size = mmc_get_bits(raw_csd, 128, 32, 7); csd->wp_grp_enable = mmc_get_bits(raw_csd, 128, 31, 1); csd->r2w_factor = 1 << mmc_get_bits(raw_csd, 128, 26, 3); csd->write_bl_len = 1 << mmc_get_bits(raw_csd, 128, 22, 4); csd->write_bl_partial = mmc_get_bits(raw_csd, 128, 21, 1); } else panic("unknown SD CSD version"); } static void mmc_decode_csd_mmc(uint32_t *raw_csd, struct mmc_csd *csd) { int m; int e; memset(csd, 0, sizeof(*csd)); csd->csd_structure = mmc_get_bits(raw_csd, 128, 126, 2); csd->spec_vers = mmc_get_bits(raw_csd, 128, 122, 4); m = mmc_get_bits(raw_csd, 128, 115, 4); e = mmc_get_bits(raw_csd, 128, 112, 3); csd->tacc = exp[e] * mant[m] + 9 / 10; csd->nsac = mmc_get_bits(raw_csd, 128, 104, 8) * 100; m = mmc_get_bits(raw_csd, 128, 99, 4); e = mmc_get_bits(raw_csd, 128, 96, 3); csd->tran_speed = exp[e] * 10000 * mant[m]; csd->ccc = mmc_get_bits(raw_csd, 128, 84, 12); csd->read_bl_len = 1 << mmc_get_bits(raw_csd, 128, 80, 4); csd->read_bl_partial = mmc_get_bits(raw_csd, 128, 79, 1); csd->write_blk_misalign = mmc_get_bits(raw_csd, 128, 78, 1); csd->read_blk_misalign = mmc_get_bits(raw_csd, 128, 77, 1); csd->dsr_imp = mmc_get_bits(raw_csd, 128, 76, 1); csd->vdd_r_curr_min = cur_min[mmc_get_bits(raw_csd, 128, 59, 3)]; csd->vdd_r_curr_max = cur_max[mmc_get_bits(raw_csd, 128, 56, 3)]; csd->vdd_w_curr_min = cur_min[mmc_get_bits(raw_csd, 128, 53, 3)]; csd->vdd_w_curr_max = cur_max[mmc_get_bits(raw_csd, 128, 50, 3)]; m = mmc_get_bits(raw_csd, 128, 62, 12); e = mmc_get_bits(raw_csd, 128, 47, 3); csd->capacity = ((1 + m) << (e + 2)) * csd->read_bl_len; csd->erase_blk_en = 0; csd->erase_sector = (mmc_get_bits(raw_csd, 128, 42, 5) + 1) * (mmc_get_bits(raw_csd, 128, 37, 5) + 1); csd->wp_grp_size = mmc_get_bits(raw_csd, 128, 32, 5); csd->wp_grp_enable = mmc_get_bits(raw_csd, 128, 31, 1); csd->r2w_factor = 1 << mmc_get_bits(raw_csd, 128, 26, 3); csd->write_bl_len = 1 << mmc_get_bits(raw_csd, 128, 22, 4); csd->write_bl_partial = mmc_get_bits(raw_csd, 128, 21, 1); } static void mmc_app_decode_scr(uint32_t *raw_scr, struct mmc_scr *scr) { unsigned int scr_struct; memset(scr, 0, sizeof(*scr)); scr_struct = mmc_get_bits(raw_scr, 64, 60, 4); if (scr_struct != 0) { printf("Unrecognised SCR structure version %d\n", scr_struct); return; } scr->sda_vsn = mmc_get_bits(raw_scr, 64, 56, 4); scr->bus_widths = mmc_get_bits(raw_scr, 64, 48, 4); } static void mmc_app_decode_sd_status(uint32_t *raw_sd_status, struct mmc_sd_status *sd_status) { memset(sd_status, 0, sizeof(*sd_status)); sd_status->bus_width = mmc_get_bits(raw_sd_status, 512, 510, 2); sd_status->secured_mode = mmc_get_bits(raw_sd_status, 512, 509, 1); sd_status->card_type = mmc_get_bits(raw_sd_status, 512, 480, 16); sd_status->prot_area = mmc_get_bits(raw_sd_status, 512, 448, 12); sd_status->speed_class = mmc_get_bits(raw_sd_status, 512, 440, 8); sd_status->perf_move = mmc_get_bits(raw_sd_status, 512, 432, 8); sd_status->au_size = mmc_get_bits(raw_sd_status, 512, 428, 4); sd_status->erase_size = mmc_get_bits(raw_sd_status, 512, 408, 16); sd_status->erase_timeout = mmc_get_bits(raw_sd_status, 512, 402, 6); sd_status->erase_offset = mmc_get_bits(raw_sd_status, 512, 400, 2); } static int mmc_all_send_cid(struct mmc_softc *sc, uint32_t *rawcid) { struct mmc_command cmd; int err; memset(&cmd, 0, sizeof(cmd)); cmd.opcode = MMC_ALL_SEND_CID; cmd.arg = 0; cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR; cmd.data = NULL; err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES); memcpy(rawcid, cmd.resp, 4 * sizeof(uint32_t)); return (err); } static int mmc_send_csd(struct mmc_softc *sc, uint16_t rca, uint32_t *rawcsd) { struct mmc_command cmd; int err; memset(&cmd, 0, sizeof(cmd)); cmd.opcode = MMC_SEND_CSD; cmd.arg = rca << 16; cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR; cmd.data = NULL; err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES); memcpy(rawcsd, cmd.resp, 4 * sizeof(uint32_t)); return (err); } static int mmc_app_send_scr(struct mmc_softc *sc, uint16_t rca, uint32_t *rawscr) { int err; struct mmc_command cmd; struct mmc_data data; memset(&cmd, 0, sizeof(cmd)); memset(&data, 0, sizeof(data)); memset(rawscr, 0, 8); cmd.opcode = ACMD_SEND_SCR; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; cmd.arg = 0; cmd.data = &data; data.data = rawscr; data.len = 8; data.flags = MMC_DATA_READ; err = mmc_wait_for_app_cmd(sc, rca, &cmd, CMD_RETRIES); rawscr[0] = be32toh(rawscr[0]); rawscr[1] = be32toh(rawscr[1]); return (err); } static int mmc_send_ext_csd(struct mmc_softc *sc, uint8_t *rawextcsd) { int err; struct mmc_command cmd; struct mmc_data data; memset(&cmd, 0, sizeof(cmd)); memset(&data, 0, sizeof(data)); memset(rawextcsd, 0, 512); cmd.opcode = MMC_SEND_EXT_CSD; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; cmd.arg = 0; cmd.data = &data; data.data = rawextcsd; data.len = 512; data.flags = MMC_DATA_READ; err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES); return (err); } static int mmc_app_sd_status(struct mmc_softc *sc, uint16_t rca, uint32_t *rawsdstatus) { int err, i; struct mmc_command cmd; struct mmc_data data; memset(&cmd, 0, sizeof(cmd)); memset(&data, 0, sizeof(data)); memset(rawsdstatus, 0, 64); cmd.opcode = ACMD_SD_STATUS; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; cmd.arg = 0; cmd.data = &data; data.data = rawsdstatus; data.len = 64; data.flags = MMC_DATA_READ; err = mmc_wait_for_app_cmd(sc, rca, &cmd, CMD_RETRIES); for (i = 0; i < 16; i++) rawsdstatus[i] = be32toh(rawsdstatus[i]); return (err); } static int mmc_set_relative_addr(struct mmc_softc *sc, uint16_t resp) { struct mmc_command cmd; int err; memset(&cmd, 0, sizeof(cmd)); cmd.opcode = MMC_SET_RELATIVE_ADDR; cmd.arg = resp << 16; cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR; cmd.data = NULL; err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES); return (err); } static int mmc_send_relative_addr(struct mmc_softc *sc, uint32_t *resp) { struct mmc_command cmd; int err; memset(&cmd, 0, sizeof(cmd)); cmd.opcode = SD_SEND_RELATIVE_ADDR; cmd.arg = 0; cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR; cmd.data = NULL; err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES); *resp = cmd.resp[0]; return (err); } static int mmc_send_status(struct mmc_softc *sc, uint16_t rca, uint32_t *status) { struct mmc_command cmd; int err; memset(&cmd, 0, sizeof(cmd)); cmd.opcode = MMC_SEND_STATUS; cmd.arg = rca << 16; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; cmd.data = NULL; err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES); *status = cmd.resp[0]; return (err); } static int mmc_set_blocklen(struct mmc_softc *sc, uint32_t len) { struct mmc_command cmd; int err; memset(&cmd, 0, sizeof(cmd)); cmd.opcode = MMC_SET_BLOCKLEN; cmd.arg = len; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; cmd.data = NULL; err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES); return (err); } static void mmc_log_card(device_t dev, struct mmc_ivars *ivar, int newcard) { device_printf(dev, "Card at relative address 0x%04x%s:\n", ivar->rca, newcard ? " added" : ""); device_printf(dev, " card: %s\n", ivar->card_id_string); device_printf(dev, " bus: %ubit, %uMHz%s\n", (ivar->bus_width == bus_width_1 ? 1 : (ivar->bus_width == bus_width_4 ? 4 : 8)), (ivar->timing == bus_timing_hs ? ivar->hs_tran_speed : ivar->tran_speed) / 1000000, ivar->timing == bus_timing_hs ? ", high speed timing" : ""); device_printf(dev, " memory: %u blocks, erase sector %u blocks%s\n", ivar->sec_count, ivar->erase_sector, ivar->read_only ? ", read-only" : ""); } static void mmc_discover_cards(struct mmc_softc *sc) { struct mmc_ivars *ivar = NULL; device_t *devlist; int err, i, devcount, newcard; uint32_t raw_cid[4], resp, sec_count, status; device_t child; uint16_t rca = 2; u_char switch_res[64]; if (bootverbose || mmc_debug) device_printf(sc->dev, "Probing cards\n"); while (1) { sc->squelched++; /* Errors are expected, squelch reporting. */ err = mmc_all_send_cid(sc, raw_cid); sc->squelched--; if (err == MMC_ERR_TIMEOUT) break; if (err != MMC_ERR_NONE) { device_printf(sc->dev, "Error reading CID %d\n", err); break; } newcard = 1; if ((err = device_get_children(sc->dev, &devlist, &devcount)) != 0) return; for (i = 0; i < devcount; i++) { ivar = device_get_ivars(devlist[i]); if (memcmp(ivar->raw_cid, raw_cid, sizeof(raw_cid)) == 0) { newcard = 0; break; } } free(devlist, M_TEMP); if (bootverbose || mmc_debug) { device_printf(sc->dev, "%sard detected (CID %08x%08x%08x%08x)\n", newcard ? "New c" : "C", raw_cid[0], raw_cid[1], raw_cid[2], raw_cid[3]); } if (newcard) { ivar = malloc(sizeof(struct mmc_ivars), M_DEVBUF, M_WAITOK | M_ZERO); memcpy(ivar->raw_cid, raw_cid, sizeof(raw_cid)); } if (mmcbr_get_ro(sc->dev)) ivar->read_only = 1; ivar->bus_width = bus_width_1; ivar->timing = bus_timing_normal; ivar->mode = mmcbr_get_mode(sc->dev); if (ivar->mode == mode_sd) { mmc_decode_cid_sd(ivar->raw_cid, &ivar->cid); mmc_send_relative_addr(sc, &resp); ivar->rca = resp >> 16; /* Get card CSD. */ mmc_send_csd(sc, ivar->rca, ivar->raw_csd); if (bootverbose || mmc_debug) device_printf(sc->dev, "%sard detected (CSD %08x%08x%08x%08x)\n", newcard ? "New c" : "C", ivar->raw_csd[0], ivar->raw_csd[1], ivar->raw_csd[2], ivar->raw_csd[3]); mmc_decode_csd_sd(ivar->raw_csd, &ivar->csd); ivar->sec_count = ivar->csd.capacity / MMC_SECTOR_SIZE; if (ivar->csd.csd_structure > 0) ivar->high_cap = 1; ivar->tran_speed = ivar->csd.tran_speed; ivar->erase_sector = ivar->csd.erase_sector * ivar->csd.write_bl_len / MMC_SECTOR_SIZE; err = mmc_send_status(sc, ivar->rca, &status); if (err != MMC_ERR_NONE) { device_printf(sc->dev, "Error reading card status %d\n", err); break; } if ((status & R1_CARD_IS_LOCKED) != 0) { device_printf(sc->dev, "Card is password protected, skipping.\n"); break; } /* Get card SCR. Card must be selected to fetch it. */ mmc_select_card(sc, ivar->rca); mmc_app_send_scr(sc, ivar->rca, ivar->raw_scr); mmc_app_decode_scr(ivar->raw_scr, &ivar->scr); /* Get card switch capabilities (command class 10). */ if ((ivar->scr.sda_vsn >= 1) && (ivar->csd.ccc & (1<<10))) { mmc_sd_switch(sc, SD_SWITCH_MODE_CHECK, SD_SWITCH_GROUP1, SD_SWITCH_NOCHANGE, switch_res); if (switch_res[13] & 2) { ivar->timing = bus_timing_hs; ivar->hs_tran_speed = SD_MAX_HS; } } /* * We deselect then reselect the card here. Some cards * become unselected and timeout with the above two * commands, although the state tables / diagrams in the * standard suggest they go back to the transfer state. * Other cards don't become deselected, and if we * atttempt to blindly re-select them, we get timeout * errors from some controllers. So we deselect then * reselect to handle all situations. The only thing we * use from the sd_status is the erase sector size, but * it is still nice to get that right. */ mmc_select_card(sc, 0); mmc_select_card(sc, ivar->rca); mmc_app_sd_status(sc, ivar->rca, ivar->raw_sd_status); mmc_app_decode_sd_status(ivar->raw_sd_status, &ivar->sd_status); if (ivar->sd_status.au_size != 0) { ivar->erase_sector = 16 << ivar->sd_status.au_size; } /* Find max supported bus width. */ if ((mmcbr_get_caps(sc->dev) & MMC_CAP_4_BIT_DATA) && (ivar->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) ivar->bus_width = bus_width_4; /* * Some cards that report maximum I/O block sizes * greater than 512 require the block length to be * set to 512, even though that is supposed to be * the default. Example: * * Transcend 2GB SDSC card, CID: * mid=0x1b oid=0x534d pnm="00000" prv=1.0 mdt=00.2000 */ if (ivar->csd.read_bl_len != MMC_SECTOR_SIZE || ivar->csd.write_bl_len != MMC_SECTOR_SIZE) mmc_set_blocklen(sc, MMC_SECTOR_SIZE); mmc_format_card_id_string(ivar); if (bootverbose || mmc_debug) mmc_log_card(sc->dev, ivar, newcard); if (newcard) { /* Add device. */ child = device_add_child(sc->dev, NULL, -1); device_set_ivars(child, ivar); } mmc_select_card(sc, 0); return; } mmc_decode_cid_mmc(ivar->raw_cid, &ivar->cid); ivar->rca = rca++; mmc_set_relative_addr(sc, ivar->rca); /* Get card CSD. */ mmc_send_csd(sc, ivar->rca, ivar->raw_csd); if (bootverbose || mmc_debug) device_printf(sc->dev, "%sard detected (CSD %08x%08x%08x%08x)\n", newcard ? "New c" : "C", ivar->raw_csd[0], ivar->raw_csd[1], ivar->raw_csd[2], ivar->raw_csd[3]); mmc_decode_csd_mmc(ivar->raw_csd, &ivar->csd); ivar->sec_count = ivar->csd.capacity / MMC_SECTOR_SIZE; ivar->tran_speed = ivar->csd.tran_speed; ivar->erase_sector = ivar->csd.erase_sector * ivar->csd.write_bl_len / MMC_SECTOR_SIZE; err = mmc_send_status(sc, ivar->rca, &status); if (err != MMC_ERR_NONE) { device_printf(sc->dev, "Error reading card status %d\n", err); break; } if ((status & R1_CARD_IS_LOCKED) != 0) { device_printf(sc->dev, "Card is password protected, skipping.\n"); break; } mmc_select_card(sc, ivar->rca); /* Only MMC >= 4.x cards support EXT_CSD. */ if (ivar->csd.spec_vers >= 4) { mmc_send_ext_csd(sc, ivar->raw_ext_csd); /* Handle extended capacity from EXT_CSD */ sec_count = ivar->raw_ext_csd[EXT_CSD_SEC_CNT] + (ivar->raw_ext_csd[EXT_CSD_SEC_CNT + 1] << 8) + (ivar->raw_ext_csd[EXT_CSD_SEC_CNT + 2] << 16) + (ivar->raw_ext_csd[EXT_CSD_SEC_CNT + 3] << 24); if (sec_count != 0) { ivar->sec_count = sec_count; ivar->high_cap = 1; } /* Get card speed in high speed mode. */ ivar->timing = bus_timing_hs; if (ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_52) ivar->hs_tran_speed = MMC_TYPE_52_MAX_HS; else if (ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_26) ivar->hs_tran_speed = MMC_TYPE_26_MAX_HS; else ivar->hs_tran_speed = ivar->tran_speed; /* Find max supported bus width. */ ivar->bus_width = mmc_test_bus_width(sc); /* Handle HC erase sector size. */ if (ivar->raw_ext_csd[EXT_CSD_ERASE_GRP_SIZE] != 0) { ivar->erase_sector = 1024 * ivar->raw_ext_csd[EXT_CSD_ERASE_GRP_SIZE]; mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_ERASE_GRP_DEF, 1); } } else { ivar->bus_width = bus_width_1; ivar->timing = bus_timing_normal; } /* * Some cards that report maximum I/O block sizes greater * than 512 require the block length to be set to 512, even * though that is supposed to be the default. Example: * * Transcend 2GB SDSC card, CID: * mid=0x1b oid=0x534d pnm="00000" prv=1.0 mdt=00.2000 */ if (ivar->csd.read_bl_len != MMC_SECTOR_SIZE || ivar->csd.write_bl_len != MMC_SECTOR_SIZE) mmc_set_blocklen(sc, MMC_SECTOR_SIZE); mmc_format_card_id_string(ivar); if (bootverbose || mmc_debug) mmc_log_card(sc->dev, ivar, newcard); if (newcard) { /* Add device. */ child = device_add_child(sc->dev, NULL, -1); device_set_ivars(child, ivar); } mmc_select_card(sc, 0); } } static void mmc_rescan_cards(struct mmc_softc *sc) { struct mmc_ivars *ivar = NULL; device_t *devlist; int err, i, devcount; if ((err = device_get_children(sc->dev, &devlist, &devcount)) != 0) return; for (i = 0; i < devcount; i++) { ivar = device_get_ivars(devlist[i]); if (mmc_select_card(sc, ivar->rca)) { if (bootverbose || mmc_debug) device_printf(sc->dev, "Card at relative address %d lost.\n", ivar->rca); device_delete_child(sc->dev, devlist[i]); free(ivar, M_DEVBUF); } } free(devlist, M_TEMP); mmc_select_card(sc, 0); } static int mmc_delete_cards(struct mmc_softc *sc) { struct mmc_ivars *ivar; device_t *devlist; int err, i, devcount; if ((err = device_get_children(sc->dev, &devlist, &devcount)) != 0) return (err); for (i = 0; i < devcount; i++) { ivar = device_get_ivars(devlist[i]); if (bootverbose || mmc_debug) device_printf(sc->dev, "Card at relative address %d deleted.\n", ivar->rca); device_delete_child(sc->dev, devlist[i]); free(ivar, M_DEVBUF); } free(devlist, M_TEMP); return (0); } static void mmc_go_discovery(struct mmc_softc *sc) { uint32_t ocr; device_t dev; int err; dev = sc->dev; if (mmcbr_get_power_mode(dev) != power_on) { /* * First, try SD modes */ sc->squelched++; /* Errors are expected, squelch reporting. */ mmcbr_set_mode(dev, mode_sd); mmc_power_up(sc); mmcbr_set_bus_mode(dev, pushpull); if (bootverbose || mmc_debug) device_printf(sc->dev, "Probing bus\n"); mmc_idle_cards(sc); err = mmc_send_if_cond(sc, 1); if ((bootverbose || mmc_debug) && err == 0) device_printf(sc->dev, "SD 2.0 interface conditions: OK\n"); if (mmc_send_app_op_cond(sc, 0, &ocr) != MMC_ERR_NONE) { if (bootverbose || mmc_debug) device_printf(sc->dev, "SD probe: failed\n"); /* * Failed, try MMC */ mmcbr_set_mode(dev, mode_mmc); if (mmc_send_op_cond(sc, 0, &ocr) != MMC_ERR_NONE) { if (bootverbose || mmc_debug) device_printf(sc->dev, "MMC probe: failed\n"); ocr = 0; /* Failed both, powerdown. */ } else if (bootverbose || mmc_debug) device_printf(sc->dev, "MMC probe: OK (OCR: 0x%08x)\n", ocr); } else if (bootverbose || mmc_debug) device_printf(sc->dev, "SD probe: OK (OCR: 0x%08x)\n", ocr); sc->squelched--; mmcbr_set_ocr(dev, mmc_select_vdd(sc, ocr)); if (mmcbr_get_ocr(dev) != 0) mmc_idle_cards(sc); } else { mmcbr_set_bus_mode(dev, opendrain); mmcbr_set_clock(dev, CARD_ID_FREQUENCY); mmcbr_update_ios(dev); /* XXX recompute vdd based on new cards? */ } /* * Make sure that we have a mutually agreeable voltage to at least * one card on the bus. */ if (bootverbose || mmc_debug) device_printf(sc->dev, "Current OCR: 0x%08x\n", mmcbr_get_ocr(dev)); if (mmcbr_get_ocr(dev) == 0) { device_printf(sc->dev, "No compatible cards found on bus\n"); mmc_delete_cards(sc); mmc_power_down(sc); return; } /* * Reselect the cards after we've idled them above. */ if (mmcbr_get_mode(dev) == mode_sd) { err = mmc_send_if_cond(sc, 1); mmc_send_app_op_cond(sc, (err ? 0 : MMC_OCR_CCS) | mmcbr_get_ocr(dev), NULL); } else mmc_send_op_cond(sc, MMC_OCR_CCS | mmcbr_get_ocr(dev), NULL); mmc_discover_cards(sc); mmc_rescan_cards(sc); mmcbr_set_bus_mode(dev, pushpull); mmcbr_update_ios(dev); mmc_calculate_clock(sc); bus_generic_attach(dev); /* mmc_update_children_sysctl(dev);*/ } static int mmc_calculate_clock(struct mmc_softc *sc) { int max_dtr, max_hs_dtr, max_timing; int nkid, i, f_max; device_t *kids; struct mmc_ivars *ivar; f_max = mmcbr_get_f_max(sc->dev); max_dtr = max_hs_dtr = f_max; if ((mmcbr_get_caps(sc->dev) & MMC_CAP_HSPEED)) max_timing = bus_timing_hs; else max_timing = bus_timing_normal; if (device_get_children(sc->dev, &kids, &nkid) != 0) panic("can't get children"); for (i = 0; i < nkid; i++) { ivar = device_get_ivars(kids[i]); if (ivar->timing < max_timing) max_timing = ivar->timing; if (ivar->tran_speed < max_dtr) max_dtr = ivar->tran_speed; if (ivar->hs_tran_speed < max_hs_dtr) max_hs_dtr = ivar->hs_tran_speed; } for (i = 0; i < nkid; i++) { ivar = device_get_ivars(kids[i]); if (ivar->timing == bus_timing_normal) continue; mmc_select_card(sc, ivar->rca); mmc_set_timing(sc, max_timing); } mmc_select_card(sc, 0); free(kids, M_TEMP); if (max_timing == bus_timing_hs) max_dtr = max_hs_dtr; if (bootverbose || mmc_debug) { device_printf(sc->dev, "setting transfer rate to %d.%03dMHz%s\n", max_dtr / 1000000, (max_dtr / 1000) % 1000, max_timing == bus_timing_hs ? " (high speed timing)" : ""); } mmcbr_set_timing(sc->dev, max_timing); mmcbr_set_clock(sc->dev, max_dtr); mmcbr_update_ios(sc->dev); return max_dtr; } static void mmc_scan(struct mmc_softc *sc) { device_t dev = sc->dev; mmc_acquire_bus(dev, dev); mmc_go_discovery(sc); mmc_release_bus(dev, dev); } static int mmc_read_ivar(device_t bus, device_t child, int which, uintptr_t *result) { struct mmc_ivars *ivar = device_get_ivars(child); switch (which) { default: return (EINVAL); case MMC_IVAR_DSR_IMP: *result = ivar->csd.dsr_imp; break; case MMC_IVAR_MEDIA_SIZE: *result = ivar->sec_count; break; case MMC_IVAR_RCA: *result = ivar->rca; break; case MMC_IVAR_SECTOR_SIZE: *result = MMC_SECTOR_SIZE; break; case MMC_IVAR_TRAN_SPEED: *result = mmcbr_get_clock(bus); break; case MMC_IVAR_READ_ONLY: *result = ivar->read_only; break; case MMC_IVAR_HIGH_CAP: *result = ivar->high_cap; break; case MMC_IVAR_CARD_TYPE: *result = ivar->mode; break; case MMC_IVAR_BUS_WIDTH: *result = ivar->bus_width; break; case MMC_IVAR_ERASE_SECTOR: *result = ivar->erase_sector; break; case MMC_IVAR_MAX_DATA: *result = mmcbr_get_max_data(bus); break; case MMC_IVAR_CARD_ID_STRING: *(char **)result = ivar->card_id_string; break; case MMC_IVAR_CARD_SN_STRING: *(char **)result = ivar->card_sn_string; break; } return (0); } static int mmc_write_ivar(device_t bus, device_t child, int which, uintptr_t value) { /* * None are writable ATM */ return (EINVAL); } static void mmc_delayed_attach(void *xsc) { struct mmc_softc *sc = xsc; mmc_scan(sc); config_intrhook_disestablish(&sc->config_intrhook); } static int mmc_child_location_str(device_t dev, device_t child, char *buf, size_t buflen) { snprintf(buf, buflen, "rca=0x%04x", mmc_get_rca(child)); return (0); } static device_method_t mmc_methods[] = { /* device_if */ DEVMETHOD(device_probe, mmc_probe), DEVMETHOD(device_attach, mmc_attach), DEVMETHOD(device_detach, mmc_detach), DEVMETHOD(device_suspend, mmc_suspend), DEVMETHOD(device_resume, mmc_resume), /* Bus interface */ DEVMETHOD(bus_read_ivar, mmc_read_ivar), DEVMETHOD(bus_write_ivar, mmc_write_ivar), DEVMETHOD(bus_child_location_str, mmc_child_location_str), /* MMC Bus interface */ DEVMETHOD(mmcbus_wait_for_request, mmc_wait_for_request), DEVMETHOD(mmcbus_acquire_bus, mmc_acquire_bus), DEVMETHOD(mmcbus_release_bus, mmc_release_bus), DEVMETHOD_END }; driver_t mmc_driver = { "mmc", mmc_methods, sizeof(struct mmc_softc), }; devclass_t mmc_devclass; Index: user/alc/PQ_LAUNDRY/sys/dev/nand/nand_cdev.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/dev/nand/nand_cdev.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/dev/nand/nand_cdev.c (revision 292449) @@ -1,452 +1,452 @@ /*- * Copyright (C) 2009-2012 Semihalf * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include "nand_if.h" #include "nandbus_if.h" static int nand_page_stat(struct nand_chip *, struct page_stat_io *); static int nand_block_stat(struct nand_chip *, struct block_stat_io *); static d_ioctl_t nand_ioctl; static d_open_t nand_open; static d_strategy_t nand_strategy; static struct cdevsw nand_cdevsw = { .d_version = D_VERSION, .d_name = "nand", .d_open = nand_open, .d_read = physread, .d_write = physwrite, .d_ioctl = nand_ioctl, .d_strategy = nand_strategy, }; static int offset_to_page(struct chip_geom *cg, uint32_t offset) { return (offset / cg->page_size); } static int offset_to_page_off(struct chip_geom *cg, uint32_t offset) { return (offset % cg->page_size); } int nand_make_dev(struct nand_chip *chip) { struct nandbus_ivar *ivar; device_t parent, nandbus; int parent_unit, unit; char *name; ivar = device_get_ivars(chip->dev); nandbus = device_get_parent(chip->dev); if (ivar->chip_cdev_name) { name = ivar->chip_cdev_name; /* * If we got distinct name for chip device we can enumarete it * based on contoller number. */ parent = device_get_parent(nandbus); } else { name = "nand"; parent = nandbus; } parent_unit = device_get_unit(parent); unit = parent_unit * 4 + chip->num; chip->cdev = make_dev(&nand_cdevsw, unit, UID_ROOT, GID_WHEEL, 0666, "%s%d.%d", name, parent_unit, chip->num); if (chip->cdev == NULL) return (ENXIO); if (bootverbose) device_printf(chip->dev, "Created cdev %s%d.%d for chip " "[0x%0x, 0x%0x]\n", name, parent_unit, chip->num, ivar->man_id, ivar->dev_id); chip->cdev->si_drv1 = chip; return (0); } void nand_destroy_dev(struct nand_chip *chip) { if (chip->cdev) destroy_dev(chip->cdev); } static int nand_open(struct cdev *dev, int oflags, int devtype, struct thread *td) { return (0); } static int nand_read(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len) { struct chip_geom *cg; device_t nandbus; int start_page, count, off, err = 0; uint8_t *ptr, *tmp; nand_debug(NDBG_CDEV, "Read from chip%d [%p] at %d\n", chip->num, chip, offset); nandbus = device_get_parent(chip->dev); NANDBUS_LOCK(nandbus); NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num); cg = &chip->chip_geom; start_page = offset_to_page(cg, offset); off = offset_to_page_off(cg, offset); count = (len > cg->page_size - off) ? cg->page_size - off : len; ptr = (uint8_t *)buf; while (len > 0) { if (len < cg->page_size) { tmp = malloc(cg->page_size, M_NAND, M_WAITOK); if (!tmp) { err = ENOMEM; break; } err = NAND_READ_PAGE(chip->dev, start_page, tmp, cg->page_size, 0); if (err) { free(tmp, M_NAND); break; } bcopy(tmp + off, ptr, count); free(tmp, M_NAND); } else { err = NAND_READ_PAGE(chip->dev, start_page, ptr, cg->page_size, 0); if (err) break; } len -= count; start_page++; ptr += count; count = (len > cg->page_size) ? cg->page_size : len; off = 0; } NANDBUS_UNLOCK(nandbus); return (err); } static int nand_write(struct nand_chip *chip, uint32_t offset, void* buf, uint32_t len) { struct chip_geom *cg; device_t nandbus; int off, start_page, err = 0; uint8_t *ptr; nand_debug(NDBG_CDEV, "Write to chip %d [%p] at %d\n", chip->num, chip, offset); nandbus = device_get_parent(chip->dev); NANDBUS_LOCK(nandbus); NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num); cg = &chip->chip_geom; start_page = offset_to_page(cg, offset); off = offset_to_page_off(cg, offset); if (off != 0 || (len % cg->page_size) != 0) { printf("Not aligned write start [0x%08x] size [0x%08x]\n", off, len); NANDBUS_UNLOCK(nandbus); return (EINVAL); } ptr = (uint8_t *)buf; while (len > 0) { err = NAND_PROGRAM_PAGE(chip->dev, start_page, ptr, cg->page_size, 0); if (err) break; len -= cg->page_size; start_page++; ptr += cg->page_size; } NANDBUS_UNLOCK(nandbus); return (err); } static void nand_strategy(struct bio *bp) { struct nand_chip *chip; struct cdev *dev; int err = 0; dev = bp->bio_dev; chip = dev->si_drv1; nand_debug(NDBG_CDEV, "Strategy %s on chip %d [%p]\n", - (bp->bio_cmd & BIO_READ) == BIO_READ ? "READ" : "WRITE", + bp->bio_cmd == BIO_READ ? "READ" : "WRITE", chip->num, chip); - if ((bp->bio_cmd & BIO_READ) == BIO_READ) { + if (bp->bio_cmd == BIO_READ) { err = nand_read(chip, bp->bio_offset & 0xffffffff, bp->bio_data, bp->bio_bcount); } else { err = nand_write(chip, bp->bio_offset & 0xffffffff, bp->bio_data, bp->bio_bcount); } if (err == 0) bp->bio_resid = 0; else { bp->bio_error = EIO; bp->bio_flags |= BIO_ERROR; bp->bio_resid = bp->bio_bcount; } biodone(bp); } static int nand_oob_access(struct nand_chip *chip, uint32_t page, uint32_t offset, uint32_t len, uint8_t *data, uint8_t write) { struct chip_geom *cg; uint8_t *buf = NULL; int ret = 0; cg = &chip->chip_geom; buf = malloc(cg->oob_size, M_NAND, M_WAITOK); if (!buf) return (ENOMEM); memset(buf, 0xff, cg->oob_size); if (!write) { ret = nand_read_oob(chip, page, buf, cg->oob_size); copyout(buf, data, len); } else { copyin(data, buf, len); ret = nand_prog_oob(chip, page, buf, cg->oob_size); } free(buf, M_NAND); return (ret); } static int nand_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td) { struct nand_chip *chip; struct chip_geom *cg; struct nand_oob_rw *oob_rw = NULL; struct nand_raw_rw *raw_rw = NULL; device_t nandbus; size_t bufsize = 0, len = 0; size_t raw_size; off_t off; uint8_t *buf = NULL; int ret = 0; uint8_t status; chip = (struct nand_chip *)dev->si_drv1; cg = &chip->chip_geom; nandbus = device_get_parent(chip->dev); if ((cmd == NAND_IO_RAW_READ) || (cmd == NAND_IO_RAW_PROG)) { raw_rw = (struct nand_raw_rw *)data; raw_size = cg->pgs_per_blk * (cg->page_size + cg->oob_size); /* Check if len is not bigger than chip size */ if (raw_rw->len > raw_size) return (EFBIG); /* * Do not ask for too much memory, in case of large transfers * read/write in 16-pages chunks */ bufsize = 16 * (cg->page_size + cg->oob_size); if (raw_rw->len < bufsize) bufsize = raw_rw->len; buf = malloc(bufsize, M_NAND, M_WAITOK); len = raw_rw->len; off = 0; } switch(cmd) { case NAND_IO_ERASE: ret = nand_erase_blocks(chip, ((off_t *)data)[0], ((off_t *)data)[1]); break; case NAND_IO_OOB_READ: oob_rw = (struct nand_oob_rw *)data; ret = nand_oob_access(chip, oob_rw->page, 0, oob_rw->len, oob_rw->data, 0); break; case NAND_IO_OOB_PROG: oob_rw = (struct nand_oob_rw *)data; ret = nand_oob_access(chip, oob_rw->page, 0, oob_rw->len, oob_rw->data, 1); break; case NAND_IO_GET_STATUS: NANDBUS_LOCK(nandbus); ret = NANDBUS_GET_STATUS(nandbus, &status); if (ret == 0) *(uint8_t *)data = status; NANDBUS_UNLOCK(nandbus); break; case NAND_IO_RAW_PROG: while (len > 0) { if (len < bufsize) bufsize = len; ret = copyin(raw_rw->data + off, buf, bufsize); if (ret) break; ret = nand_prog_pages_raw(chip, raw_rw->off + off, buf, bufsize); if (ret) break; len -= bufsize; off += bufsize; } break; case NAND_IO_RAW_READ: while (len > 0) { if (len < bufsize) bufsize = len; ret = nand_read_pages_raw(chip, raw_rw->off + off, buf, bufsize); if (ret) break; ret = copyout(buf, raw_rw->data + off, bufsize); if (ret) break; len -= bufsize; off += bufsize; } break; case NAND_IO_PAGE_STAT: ret = nand_page_stat(chip, (struct page_stat_io *)data); break; case NAND_IO_BLOCK_STAT: ret = nand_block_stat(chip, (struct block_stat_io *)data); break; case NAND_IO_GET_CHIP_PARAM: nand_get_chip_param(chip, (struct chip_param_io *)data); break; default: printf("Unknown nand_ioctl request \n"); ret = EIO; } if (buf) free(buf, M_NAND); return (ret); } static int nand_page_stat(struct nand_chip *chip, struct page_stat_io *page_stat) { struct chip_geom *cg; struct page_stat *stat; int num_pages; cg = &chip->chip_geom; num_pages = cg->pgs_per_blk * cg->blks_per_lun * cg->luns; if (page_stat->page_num >= num_pages) return (EINVAL); stat = &chip->pg_stat[page_stat->page_num]; page_stat->page_read = stat->page_read; page_stat->page_written = stat->page_written; page_stat->page_raw_read = stat->page_raw_read; page_stat->page_raw_written = stat->page_raw_written; page_stat->ecc_succeded = stat->ecc_stat.ecc_succeded; page_stat->ecc_corrected = stat->ecc_stat.ecc_corrected; page_stat->ecc_failed = stat->ecc_stat.ecc_failed; return (0); } static int nand_block_stat(struct nand_chip *chip, struct block_stat_io *block_stat) { struct chip_geom *cg; uint32_t block_num = block_stat->block_num; cg = &chip->chip_geom; if (block_num >= cg->blks_per_lun * cg->luns) return (EINVAL); block_stat->block_erased = chip->blk_stat[block_num].block_erased; return (0); } Index: user/alc/PQ_LAUNDRY/sys/dev/nand/nand_geom.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/dev/nand/nand_geom.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/dev/nand/nand_geom.c (revision 292449) @@ -1,463 +1,463 @@ /*- * Copyright (C) 2009-2012 Semihalf * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include "nand_if.h" #include "nandbus_if.h" #define BIO_NAND_STD ((void *)1) #define BIO_NAND_RAW ((void *)2) static disk_ioctl_t nand_ioctl; static disk_getattr_t nand_getattr; static disk_strategy_t nand_strategy; static disk_strategy_t nand_strategy_raw; static int nand_read(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len) { nand_debug(NDBG_GEOM, "Read from chip %d [%p] at %d", chip->num, chip, offset); return (nand_read_pages(chip, offset, buf, len)); } static int nand_write(struct nand_chip *chip, uint32_t offset, void* buf, uint32_t len) { nand_debug(NDBG_GEOM, "Write to chip %d [%p] at %d", chip->num, chip, offset); return (nand_prog_pages(chip, offset, buf, len)); } static int nand_read_raw(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len) { nand_debug(NDBG_GEOM, "Raw read from chip %d [%p] at %d", chip->num, chip, offset); return (nand_read_pages_raw(chip, offset, buf, len)); } static int nand_write_raw(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len) { nand_debug(NDBG_GEOM, "Raw write to chip %d [%p] at %d", chip->num, chip, offset); return (nand_prog_pages_raw(chip, offset, buf, len)); } static void nand_strategy(struct bio *bp) { struct nand_chip *chip; chip = (struct nand_chip *)bp->bio_disk->d_drv1; bp->bio_driver1 = BIO_NAND_STD; nand_debug(NDBG_GEOM, "Strategy %s on chip %d [%p]", - (bp->bio_cmd & BIO_READ) == BIO_READ ? "READ" : - ((bp->bio_cmd & BIO_WRITE) == BIO_WRITE ? "WRITE" : - ((bp->bio_cmd & BIO_DELETE) == BIO_DELETE ? "DELETE" : "UNKNOWN")), + bp->bio_cmd == BIO_READ ? "READ" : + (bp->bio_cmd == BIO_WRITE ? "WRITE" : + (bp->bio_cmd == BIO_DELETE ? "DELETE" : "UNKNOWN")), chip->num, chip); mtx_lock(&chip->qlock); bioq_insert_tail(&chip->bioq, bp); mtx_unlock(&chip->qlock); taskqueue_enqueue(chip->tq, &chip->iotask); } static void nand_strategy_raw(struct bio *bp) { struct nand_chip *chip; chip = (struct nand_chip *)bp->bio_disk->d_drv1; /* Inform taskqueue that it's a raw access */ bp->bio_driver1 = BIO_NAND_RAW; nand_debug(NDBG_GEOM, "Strategy %s on chip %d [%p]", - (bp->bio_cmd & BIO_READ) == BIO_READ ? "READ" : - ((bp->bio_cmd & BIO_WRITE) == BIO_WRITE ? "WRITE" : - ((bp->bio_cmd & BIO_DELETE) == BIO_DELETE ? "DELETE" : "UNKNOWN")), + bp->bio_cmd == BIO_READ ? "READ" : + (bp->bio_cmd == BIO_WRITE ? "WRITE" : + (bp->bio_cmd == BIO_DELETE ? "DELETE" : "UNKNOWN")), chip->num, chip); mtx_lock(&chip->qlock); bioq_insert_tail(&chip->bioq, bp); mtx_unlock(&chip->qlock); taskqueue_enqueue(chip->tq, &chip->iotask); } static int nand_oob_access(struct nand_chip *chip, uint32_t page, uint32_t offset, uint32_t len, uint8_t *data, uint8_t write) { struct chip_geom *cg; int ret = 0; cg = &chip->chip_geom; if (!write) ret = nand_read_oob(chip, page, data, cg->oob_size); else ret = nand_prog_oob(chip, page, data, cg->oob_size); return (ret); } static int nand_getattr(struct bio *bp) { struct nand_chip *chip; struct chip_geom *cg; device_t dev; int val; if (bp->bio_disk == NULL || bp->bio_disk->d_drv1 == NULL) return (ENXIO); chip = (struct nand_chip *)bp->bio_disk->d_drv1; cg = &(chip->chip_geom); dev = device_get_parent(chip->dev); dev = device_get_parent(dev); if (strcmp(bp->bio_attribute, "NAND::device") == 0) { if (bp->bio_length != sizeof(dev)) return (EFAULT); bcopy(&dev, bp->bio_data, sizeof(dev)); } else { if (strcmp(bp->bio_attribute, "NAND::oobsize") == 0) val = cg->oob_size; else if (strcmp(bp->bio_attribute, "NAND::pagesize") == 0) val = cg->page_size; else if (strcmp(bp->bio_attribute, "NAND::blocksize") == 0) val = cg->block_size; else return (-1); if (bp->bio_length != sizeof(val)) return (EFAULT); bcopy(&val, bp->bio_data, sizeof(val)); } bp->bio_completed = bp->bio_length; return (0); } static int nand_ioctl(struct disk *ndisk, u_long cmd, void *data, int fflag, struct thread *td) { struct nand_chip *chip; struct chip_geom *cg; struct nand_oob_rw *oob_rw = NULL; struct nand_raw_rw *raw_rw = NULL; device_t nandbus; size_t bufsize = 0, len = 0; size_t raw_size; off_t off; uint8_t *buf = NULL; int ret = 0; uint8_t status; chip = (struct nand_chip *)ndisk->d_drv1; cg = &chip->chip_geom; nandbus = device_get_parent(chip->dev); if ((cmd == NAND_IO_RAW_READ) || (cmd == NAND_IO_RAW_PROG)) { raw_rw = (struct nand_raw_rw *)data; raw_size = cg->pgs_per_blk * (cg->page_size + cg->oob_size); /* Check if len is not bigger than chip size */ if (raw_rw->len > raw_size) return (EFBIG); /* * Do not ask for too much memory, in case of large transfers * read/write in 16-pages chunks */ bufsize = 16 * (cg->page_size + cg->oob_size); if (raw_rw->len < bufsize) bufsize = raw_rw->len; buf = malloc(bufsize, M_NAND, M_WAITOK); len = raw_rw->len; off = 0; } switch (cmd) { case NAND_IO_ERASE: ret = nand_erase_blocks(chip, ((off_t *)data)[0], ((off_t *)data)[1]); break; case NAND_IO_OOB_READ: oob_rw = (struct nand_oob_rw *)data; ret = nand_oob_access(chip, oob_rw->page, 0, oob_rw->len, oob_rw->data, 0); break; case NAND_IO_OOB_PROG: oob_rw = (struct nand_oob_rw *)data; ret = nand_oob_access(chip, oob_rw->page, 0, oob_rw->len, oob_rw->data, 1); break; case NAND_IO_GET_STATUS: NANDBUS_LOCK(nandbus); ret = NANDBUS_GET_STATUS(nandbus, &status); if (ret == 0) *(uint8_t *)data = status; NANDBUS_UNLOCK(nandbus); break; case NAND_IO_RAW_PROG: while (len > 0) { if (len < bufsize) bufsize = len; ret = copyin(raw_rw->data + off, buf, bufsize); if (ret) break; ret = nand_prog_pages_raw(chip, raw_rw->off + off, buf, bufsize); if (ret) break; len -= bufsize; off += bufsize; } break; case NAND_IO_RAW_READ: while (len > 0) { if (len < bufsize) bufsize = len; ret = nand_read_pages_raw(chip, raw_rw->off + off, buf, bufsize); if (ret) break; ret = copyout(buf, raw_rw->data + off, bufsize); if (ret) break; len -= bufsize; off += bufsize; } break; case NAND_IO_GET_CHIP_PARAM: nand_get_chip_param(chip, (struct chip_param_io *)data); break; default: printf("Unknown nand_ioctl request \n"); ret = EIO; } if (buf) free(buf, M_NAND); return (ret); } static void nand_io_proc(void *arg, int pending) { struct nand_chip *chip = arg; struct bio *bp; int err = 0; for (;;) { mtx_lock(&chip->qlock); bp = bioq_takefirst(&chip->bioq); mtx_unlock(&chip->qlock); if (bp == NULL) break; if (bp->bio_driver1 == BIO_NAND_STD) { - if ((bp->bio_cmd & BIO_READ) == BIO_READ) { + if (bp->bio_cmd == BIO_READ) { err = nand_read(chip, bp->bio_offset & 0xffffffff, bp->bio_data, bp->bio_bcount); - } else if ((bp->bio_cmd & BIO_WRITE) == BIO_WRITE) { + } else if (bp->bio_cmd == BIO_WRITE) { err = nand_write(chip, bp->bio_offset & 0xffffffff, bp->bio_data, bp->bio_bcount); } } else if (bp->bio_driver1 == BIO_NAND_RAW) { - if ((bp->bio_cmd & BIO_READ) == BIO_READ) { + if (bp->bio_cmd == BIO_READ) { err = nand_read_raw(chip, bp->bio_offset & 0xffffffff, bp->bio_data, bp->bio_bcount); - } else if ((bp->bio_cmd & BIO_WRITE) == BIO_WRITE) { + } else if (bp->bio_cmd == BIO_WRITE) { err = nand_write_raw(chip, bp->bio_offset & 0xffffffff, bp->bio_data, bp->bio_bcount); } } else panic("Unknown access type in bio->bio_driver1\n"); - if ((bp->bio_cmd & BIO_DELETE) == BIO_DELETE) { + if (bp->bio_cmd == BIO_DELETE) { nand_debug(NDBG_GEOM, "Delete on chip%d offset %lld " "length %ld\n", chip->num, bp->bio_offset, bp->bio_bcount); err = nand_erase_blocks(chip, bp->bio_offset & 0xffffffff, bp->bio_bcount); } if (err == 0 || err == ECC_CORRECTABLE) bp->bio_resid = 0; else { nand_debug(NDBG_GEOM,"nand_[read|write|erase_blocks] " "error: %d\n", err); bp->bio_error = EIO; bp->bio_flags |= BIO_ERROR; bp->bio_resid = bp->bio_bcount; } biodone(bp); } } int create_geom_disk(struct nand_chip *chip) { struct disk *ndisk, *rdisk; /* Create the disk device */ ndisk = disk_alloc(); ndisk->d_strategy = nand_strategy; ndisk->d_ioctl = nand_ioctl; ndisk->d_getattr = nand_getattr; ndisk->d_name = "gnand"; ndisk->d_drv1 = chip; ndisk->d_maxsize = chip->chip_geom.block_size; ndisk->d_sectorsize = chip->chip_geom.page_size; ndisk->d_mediasize = chip->chip_geom.chip_size; ndisk->d_unit = chip->num + 10 * device_get_unit(device_get_parent(chip->dev)); /* * When using BBT, make two last blocks of device unavailable * to user (because those are used to store BBT table). */ if (chip->bbt != NULL) ndisk->d_mediasize -= (2 * chip->chip_geom.block_size); ndisk->d_flags = DISKFLAG_CANDELETE; snprintf(ndisk->d_ident, sizeof(ndisk->d_ident), "nand: Man:0x%02x Dev:0x%02x", chip->id.man_id, chip->id.dev_id); disk_create(ndisk, DISK_VERSION); /* Create the RAW disk device */ rdisk = disk_alloc(); rdisk->d_strategy = nand_strategy_raw; rdisk->d_ioctl = nand_ioctl; rdisk->d_getattr = nand_getattr; rdisk->d_name = "gnand.raw"; rdisk->d_drv1 = chip; rdisk->d_maxsize = chip->chip_geom.block_size; rdisk->d_sectorsize = chip->chip_geom.page_size; rdisk->d_mediasize = chip->chip_geom.chip_size; rdisk->d_unit = chip->num + 10 * device_get_unit(device_get_parent(chip->dev)); rdisk->d_flags = DISKFLAG_CANDELETE; snprintf(rdisk->d_ident, sizeof(rdisk->d_ident), "nand_raw: Man:0x%02x Dev:0x%02x", chip->id.man_id, chip->id.dev_id); disk_create(rdisk, DISK_VERSION); chip->ndisk = ndisk; chip->rdisk = rdisk; mtx_init(&chip->qlock, "NAND I/O lock", NULL, MTX_DEF); bioq_init(&chip->bioq); TASK_INIT(&chip->iotask, 0, nand_io_proc, chip); chip->tq = taskqueue_create("nand_taskq", M_WAITOK, taskqueue_thread_enqueue, &chip->tq); taskqueue_start_threads(&chip->tq, 1, PI_DISK, "nand taskq"); if (bootverbose) device_printf(chip->dev, "Created gnand%d for chip [0x%0x, " "0x%0x]\n", ndisk->d_unit, chip->id.man_id, chip->id.dev_id); return (0); } void destroy_geom_disk(struct nand_chip *chip) { struct bio *bp; taskqueue_free(chip->tq); disk_destroy(chip->ndisk); disk_destroy(chip->rdisk); mtx_lock(&chip->qlock); for (;;) { bp = bioq_takefirst(&chip->bioq); if (bp == NULL) break; bp->bio_error = EIO; bp->bio_flags |= BIO_ERROR; bp->bio_resid = bp->bio_bcount; biodone(bp); } mtx_unlock(&chip->qlock); mtx_destroy(&chip->qlock); } Index: user/alc/PQ_LAUNDRY/sys/dev/ofw/ofw_bus_subr.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/dev/ofw/ofw_bus_subr.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/dev/ofw/ofw_bus_subr.c (revision 292449) @@ -1,740 +1,753 @@ /*- * Copyright (c) 2001 - 2003 by Thomas Moestl . * Copyright (c) 2005 Marius Strobl * 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, * without modification, immediately at the beginning of the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_platform.h" #include #include #include #include #include #include #include #include #include #include "ofw_bus_if.h" int ofw_bus_gen_setup_devinfo(struct ofw_bus_devinfo *obd, phandle_t node) { if (obd == NULL) return (ENOMEM); /* The 'name' property is considered mandatory. */ if ((OF_getprop_alloc(node, "name", 1, (void **)&obd->obd_name)) == -1) return (EINVAL); OF_getprop_alloc(node, "compatible", 1, (void **)&obd->obd_compat); OF_getprop_alloc(node, "device_type", 1, (void **)&obd->obd_type); OF_getprop_alloc(node, "model", 1, (void **)&obd->obd_model); OF_getprop_alloc(node, "status", 1, (void **)&obd->obd_status); obd->obd_node = node; return (0); } void ofw_bus_gen_destroy_devinfo(struct ofw_bus_devinfo *obd) { if (obd == NULL) return; if (obd->obd_compat != NULL) free(obd->obd_compat, M_OFWPROP); if (obd->obd_model != NULL) free(obd->obd_model, M_OFWPROP); if (obd->obd_name != NULL) free(obd->obd_name, M_OFWPROP); if (obd->obd_type != NULL) free(obd->obd_type, M_OFWPROP); if (obd->obd_status != NULL) free(obd->obd_status, M_OFWPROP); } int ofw_bus_gen_child_pnpinfo_str(device_t cbdev, device_t child, char *buf, size_t buflen) { if (ofw_bus_get_name(child) != NULL) { strlcat(buf, "name=", buflen); strlcat(buf, ofw_bus_get_name(child), buflen); } if (ofw_bus_get_compat(child) != NULL) { strlcat(buf, " compat=", buflen); strlcat(buf, ofw_bus_get_compat(child), buflen); } return (0); }; const char * ofw_bus_gen_get_compat(device_t bus, device_t dev) { const struct ofw_bus_devinfo *obd; obd = OFW_BUS_GET_DEVINFO(bus, dev); if (obd == NULL) return (NULL); return (obd->obd_compat); } const char * ofw_bus_gen_get_model(device_t bus, device_t dev) { const struct ofw_bus_devinfo *obd; obd = OFW_BUS_GET_DEVINFO(bus, dev); if (obd == NULL) return (NULL); return (obd->obd_model); } const char * ofw_bus_gen_get_name(device_t bus, device_t dev) { const struct ofw_bus_devinfo *obd; obd = OFW_BUS_GET_DEVINFO(bus, dev); if (obd == NULL) return (NULL); return (obd->obd_name); } phandle_t ofw_bus_gen_get_node(device_t bus, device_t dev) { const struct ofw_bus_devinfo *obd; obd = OFW_BUS_GET_DEVINFO(bus, dev); if (obd == NULL) return (0); return (obd->obd_node); } const char * ofw_bus_gen_get_type(device_t bus, device_t dev) { const struct ofw_bus_devinfo *obd; obd = OFW_BUS_GET_DEVINFO(bus, dev); if (obd == NULL) return (NULL); return (obd->obd_type); } const char * ofw_bus_get_status(device_t dev) { const struct ofw_bus_devinfo *obd; obd = OFW_BUS_GET_DEVINFO(device_get_parent(dev), dev); if (obd == NULL) return (NULL); return (obd->obd_status); } int ofw_bus_status_okay(device_t dev) { const char *status; status = ofw_bus_get_status(dev); if (status == NULL || strcmp(status, "okay") == 0 || strcmp(status, "ok") == 0) return (1); return (0); } static int ofw_bus_node_is_compatible(const char *compat, int len, const char *onecompat) { int onelen, l, ret; onelen = strlen(onecompat); ret = 0; while (len > 0) { if (strlen(compat) == onelen && strncasecmp(compat, onecompat, onelen) == 0) { /* Found it. */ ret = 1; break; } /* Slide to the next sub-string. */ l = strlen(compat) + 1; compat += l; len -= l; } return (ret); } int ofw_bus_is_compatible(device_t dev, const char *onecompat) { phandle_t node; const char *compat; int len; if ((compat = ofw_bus_get_compat(dev)) == NULL) return (0); if ((node = ofw_bus_get_node(dev)) == -1) return (0); /* Get total 'compatible' prop len */ if ((len = OF_getproplen(node, "compatible")) <= 0) return (0); return (ofw_bus_node_is_compatible(compat, len, onecompat)); } int ofw_bus_is_compatible_strict(device_t dev, const char *compatible) { const char *compat; size_t len; if ((compat = ofw_bus_get_compat(dev)) == NULL) return (0); len = strlen(compatible); if (strlen(compat) == len && strncasecmp(compat, compatible, len) == 0) return (1); return (0); } const struct ofw_compat_data * ofw_bus_search_compatible(device_t dev, const struct ofw_compat_data *compat) { if (compat == NULL) return NULL; for (; compat->ocd_str != NULL; ++compat) { if (ofw_bus_is_compatible(dev, compat->ocd_str)) break; } return (compat); } int ofw_bus_has_prop(device_t dev, const char *propname) { phandle_t node; if ((node = ofw_bus_get_node(dev)) == -1) return (0); return (OF_hasprop(node, propname)); } void ofw_bus_setup_iinfo(phandle_t node, struct ofw_bus_iinfo *ii, int intrsz) { pcell_t addrc; int msksz; if (OF_getencprop(node, "#address-cells", &addrc, sizeof(addrc)) == -1) addrc = 2; ii->opi_addrc = addrc * sizeof(pcell_t); ii->opi_imapsz = OF_getencprop_alloc(node, "interrupt-map", 1, (void **)&ii->opi_imap); if (ii->opi_imapsz > 0) { msksz = OF_getencprop_alloc(node, "interrupt-map-mask", 1, (void **)&ii->opi_imapmsk); /* * Failure to get the mask is ignored; a full mask is used * then. We barf on bad mask sizes, however. */ if (msksz != -1 && msksz != ii->opi_addrc + intrsz) panic("ofw_bus_setup_iinfo: bad interrupt-map-mask " "property!"); } } int ofw_bus_lookup_imap(phandle_t node, struct ofw_bus_iinfo *ii, void *reg, int regsz, void *pintr, int pintrsz, void *mintr, int mintrsz, phandle_t *iparent) { uint8_t maskbuf[regsz + pintrsz]; int rv; if (ii->opi_imapsz <= 0) return (0); KASSERT(regsz >= ii->opi_addrc, ("ofw_bus_lookup_imap: register size too small: %d < %d", regsz, ii->opi_addrc)); if (node != -1) { rv = OF_getencprop(node, "reg", reg, regsz); if (rv < regsz) panic("ofw_bus_lookup_imap: cannot get reg property"); } return (ofw_bus_search_intrmap(pintr, pintrsz, reg, ii->opi_addrc, ii->opi_imap, ii->opi_imapsz, ii->opi_imapmsk, maskbuf, mintr, mintrsz, iparent)); } /* * Map an interrupt using the firmware reg, interrupt-map and * interrupt-map-mask properties. * The interrupt property to be mapped must be of size intrsz, and pointed to * by intr. The regs property of the node for which the mapping is done must * be passed as regs. This property is an array of register specifications; * the size of the address part of such a specification must be passed as * physsz. Only the first element of the property is used. * imap and imapsz hold the interrupt mask and it's size. * imapmsk is a pointer to the interrupt-map-mask property, which must have * a size of physsz + intrsz; it may be NULL, in which case a full mask is * assumed. * maskbuf must point to a buffer of length physsz + intrsz. * The interrupt is returned in result, which must point to a buffer of length * rintrsz (which gives the expected size of the mapped interrupt). * Returns number of cells in the interrupt if a mapping was found, 0 otherwise. */ int ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz, void *imap, int imapsz, void *imapmsk, void *maskbuf, void *result, int rintrsz, phandle_t *iparent) { phandle_t parent; uint8_t *ref = maskbuf; uint8_t *uiintr = intr; uint8_t *uiregs = regs; uint8_t *uiimapmsk = imapmsk; uint8_t *mptr; + pcell_t paddrsz; pcell_t pintrsz; int i, rsz, tsz; rsz = -1; if (imapmsk != NULL) { for (i = 0; i < physsz; i++) ref[i] = uiregs[i] & uiimapmsk[i]; for (i = 0; i < intrsz; i++) ref[physsz + i] = uiintr[i] & uiimapmsk[physsz + i]; } else { bcopy(regs, ref, physsz); bcopy(intr, ref + physsz, intrsz); } mptr = imap; i = imapsz; + paddrsz = 0; while (i > 0) { bcopy(mptr + physsz + intrsz, &parent, sizeof(parent)); +#ifdef OFW_EPAPR + /* + * Find if we need to read the parent address data. Sparc64 + * uses a different encoding that doesn't include this data. + */ + if (OF_getencprop(OF_node_from_xref(parent), + "#address-cells", &paddrsz, sizeof(paddrsz)) == -1) + paddrsz = 0; /* default */ + paddrsz *= sizeof(pcell_t); +#endif + if (OF_searchencprop(OF_node_from_xref(parent), "#interrupt-cells", &pintrsz, sizeof(pintrsz)) == -1) pintrsz = 1; /* default */ pintrsz *= sizeof(pcell_t); /* Compute the map stride size. */ - tsz = physsz + intrsz + sizeof(phandle_t) + pintrsz; + tsz = physsz + intrsz + sizeof(phandle_t) + paddrsz + pintrsz; KASSERT(i >= tsz, ("ofw_bus_search_intrmap: truncated map")); if (bcmp(ref, mptr, physsz + intrsz) == 0) { - bcopy(mptr + physsz + intrsz + sizeof(parent), + bcopy(mptr + physsz + intrsz + sizeof(parent) + paddrsz, result, MIN(rintrsz, pintrsz)); if (iparent != NULL) *iparent = parent; return (pintrsz/sizeof(pcell_t)); } mptr += tsz; i -= tsz; } return (0); } int ofw_bus_reg_to_rl(device_t dev, phandle_t node, pcell_t acells, pcell_t scells, struct resource_list *rl) { uint64_t phys, size; ssize_t i, j, rid, nreg, ret; uint32_t *reg; char *name; /* * This may be just redundant when having ofw_bus_devinfo * but makes this routine independent of it. */ ret = OF_getprop_alloc(node, "name", sizeof(*name), (void **)&name); if (ret == -1) name = NULL; ret = OF_getencprop_alloc(node, "reg", sizeof(*reg), (void **)®); nreg = (ret == -1) ? 0 : ret; if (nreg % (acells + scells) != 0) { if (bootverbose) device_printf(dev, "Malformed reg property on <%s>\n", (name == NULL) ? "unknown" : name); nreg = 0; } for (i = 0, rid = 0; i < nreg; i += acells + scells, rid++) { phys = size = 0; for (j = 0; j < acells; j++) { phys <<= 32; phys |= reg[i + j]; } for (j = 0; j < scells; j++) { size <<= 32; size |= reg[i + acells + j]; } /* Skip the dummy reg property of glue devices like ssm(4). */ if (size != 0) resource_list_add(rl, SYS_RES_MEMORY, rid, phys, phys + size - 1, size); } free(name, M_OFWPROP); free(reg, M_OFWPROP); return (0); } /* * Get interrupt parent for given node. * Returns 0 if interrupt parent doesn't exist. */ phandle_t ofw_bus_find_iparent(phandle_t node) { phandle_t iparent; if (OF_searchencprop(node, "interrupt-parent", &iparent, sizeof(iparent)) == -1) { for (iparent = node; iparent != 0; iparent = OF_parent(iparent)) { if (OF_hasprop(iparent, "interrupt-controller")) break; } iparent = OF_xref_from_node(iparent); } return (iparent); } int ofw_bus_intr_to_rl(device_t dev, phandle_t node, struct resource_list *rl, int *rlen) { phandle_t iparent; uint32_t icells, *intr; int err, i, irqnum, nintr, rid; boolean_t extended; nintr = OF_getencprop_alloc(node, "interrupts", sizeof(*intr), (void **)&intr); if (nintr > 0) { iparent = ofw_bus_find_iparent(node); if (iparent == 0) { device_printf(dev, "No interrupt-parent found, " "assuming direct parent\n"); iparent = OF_parent(node); iparent = OF_xref_from_node(iparent); } if (OF_searchencprop(OF_node_from_xref(iparent), "#interrupt-cells", &icells, sizeof(icells)) == -1) { device_printf(dev, "Missing #interrupt-cells " "property, assuming <1>\n"); icells = 1; } if (icells < 1 || icells > nintr) { device_printf(dev, "Invalid #interrupt-cells property " "value <%d>, assuming <1>\n", icells); icells = 1; } extended = false; } else { nintr = OF_getencprop_alloc(node, "interrupts-extended", sizeof(*intr), (void **)&intr); if (nintr <= 0) return (0); extended = true; } err = 0; rid = 0; for (i = 0; i < nintr; i += icells) { if (extended) { iparent = intr[i++]; if (OF_searchencprop(OF_node_from_xref(iparent), "#interrupt-cells", &icells, sizeof(icells)) == -1) { device_printf(dev, "Missing #interrupt-cells " "property\n"); err = ENOENT; break; } if (icells < 1 || (i + icells) > nintr) { device_printf(dev, "Invalid #interrupt-cells " "property value <%d>\n", icells); err = ERANGE; break; } } irqnum = ofw_bus_map_intr(dev, iparent, icells, &intr[i]); resource_list_add(rl, SYS_RES_IRQ, rid++, irqnum, irqnum, 1); } if (rlen != NULL) *rlen = rid; free(intr, M_OFWPROP); return (err); } phandle_t ofw_bus_find_child(phandle_t start, const char *child_name) { char *name; int ret; phandle_t child; for (child = OF_child(start); child != 0; child = OF_peer(child)) { ret = OF_getprop_alloc(child, "name", sizeof(*name), (void **)&name); if (ret == -1) continue; if (strcmp(name, child_name) == 0) { free(name, M_OFWPROP); return (child); } free(name, M_OFWPROP); } return (0); } phandle_t ofw_bus_find_compatible(phandle_t node, const char *onecompat) { phandle_t child, ret; void *compat; int len; /* * Traverse all children of 'start' node, and find first with * matching 'compatible' property. */ for (child = OF_child(node); child != 0; child = OF_peer(child)) { len = OF_getprop_alloc(child, "compatible", 1, &compat); if (len >= 0) { ret = ofw_bus_node_is_compatible(compat, len, onecompat); free(compat, M_OFWPROP); if (ret != 0) return (child); } ret = ofw_bus_find_compatible(child, onecompat); if (ret != 0) return (ret); } return (0); } /** * @brief Return child of bus whose phandle is node * * A direct child of @p will be returned if it its phandle in the * OFW tree is @p node. Otherwise, NULL is returned. * * @param bus The bus to examine * @param node The phandle_t to look for. */ device_t ofw_bus_find_child_device_by_phandle(device_t bus, phandle_t node) { device_t *children, retval, child; int nkid, i; /* * Nothing can match the flag value for no node. */ if (node == -1) return (NULL); /* * Search the children for a match. We microoptimize * a bit by not using ofw_bus_get since we already know * the parent. We do not recurse. */ if (device_get_children(bus, &children, &nkid) != 0) return (NULL); retval = NULL; for (i = 0; i < nkid; i++) { child = children[i]; if (OFW_BUS_GET_NODE(bus, child) == node) { retval = child; break; } } free(children, M_TEMP); return (retval); } /* * Parse property that contain list of xrefs and values * (like standard "clocks" and "resets" properties) * Input arguments: * node - consumers device node * list_name - name of parsed list - "clocks" * cells_name - name of size property - "#clock-cells" * Output arguments: * producer - handle of producer * ncells - number of cells in result * cells - array of decoded cells */ int ofw_bus_parse_xref_list_alloc(phandle_t node, const char *list_name, const char *cells_name, int idx, phandle_t *producer, int *ncells, pcell_t **cells) { phandle_t pnode; phandle_t *elems; uint32_t pcells; int rv, i, j, nelems, cnt; elems = NULL; nelems = OF_getencprop_alloc(node, list_name, sizeof(*elems), (void **)&elems); if (nelems <= 0) return (ENOENT); rv = ENOENT; for (i = 0, cnt = 0; i < nelems; i += pcells, cnt++) { pnode = elems[i++]; if (OF_getencprop(OF_node_from_xref(pnode), cells_name, &pcells, sizeof(pcells)) == -1) { printf("Missing %s property\n", cells_name); rv = ENOENT; break; } if ((i + pcells) > nelems) { printf("Invalid %s property value <%d>\n", cells_name, pcells); rv = ERANGE; break; } if (cnt == idx) { *cells= malloc(pcells * sizeof(**cells), M_OFWPROP, M_WAITOK); *producer = pnode; *ncells = pcells; for (j = 0; j < pcells; j++) (*cells)[j] = elems[i + j]; rv = 0; break; } } if (elems != NULL) free(elems, M_OFWPROP); return (rv); } /* * Find index of string in string list property (case sensitive). */ int ofw_bus_find_string_index(phandle_t node, const char *list_name, const char *name, int *idx) { char *elems; int rv, i, cnt, nelems; elems = NULL; nelems = OF_getprop_alloc(node, list_name, 1, (void **)&elems); if (nelems <= 0) return (ENOENT); rv = ENOENT; for (i = 0, cnt = 0; i < nelems; cnt++) { if (strcmp(elems + i, name) == 0) { *idx = cnt; rv = 0; break; } i += strlen(elems + i) + 1; } if (elems != NULL) free(elems, M_OFWPROP); return (rv); } /* * Create zero terminated array of strings from string list property. */ int ofw_bus_string_list_to_array(phandle_t node, const char *list_name, const char ***array) { char *elems, *tptr; int i, cnt, nelems, len; elems = NULL; nelems = OF_getprop_alloc(node, list_name, 1, (void **)&elems); if (nelems <= 0) return (nelems); /* Count number of strings. */ for (i = 0, cnt = 0; i < nelems; cnt++) i += strlen(elems + i) + 1; /* Allocate space for arrays and all strings. */ *array = malloc((cnt + 1) * sizeof(char *) + nelems, M_OFWPROP, M_WAITOK); /* Get address of first string. */ tptr = (char *)(*array + cnt); /* Copy strings. */ memcpy(tptr, elems, nelems); free(elems, M_OFWPROP); /* Fill string pointers. */ for (i = 0, cnt = 0; i < nelems; cnt++) { len = strlen(tptr + i) + 1; *array[cnt] = tptr; i += len; tptr += len; } *array[cnt] = 0; return (cnt); } Index: user/alc/PQ_LAUNDRY/sys/dev/ofw/ofw_bus_subr.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/dev/ofw/ofw_bus_subr.h (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/dev/ofw/ofw_bus_subr.h (revision 292449) @@ -1,122 +1,126 @@ /*- * Copyright (c) 2005 Marius Strobl * 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, * without modification, immediately at the beginning of the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _DEV_OFW_OFW_BUS_SUBR_H_ #define _DEV_OFW_OFW_BUS_SUBR_H_ #include #include #include "ofw_bus_if.h" #define ORIP_NOINT -1 #define ORIR_NOTFOUND 0xffffffff struct ofw_bus_iinfo { uint8_t *opi_imap; uint8_t *opi_imapmsk; int opi_imapsz; pcell_t opi_addrc; }; struct ofw_compat_data { const char *ocd_str; uintptr_t ocd_data; }; +#define SIMPLEBUS_PNP_DESCR "Z:compat;P:private;" +#define SIMPLEBUS_PNP_INFO(t) \ + MODULE_PNP_INFO(SIMPLEBUS_PNP_DESCR, simplebus, t, t, sizeof(t[0]), sizeof(t) / sizeof(t[0])); + /* Generic implementation of ofw_bus_if.m methods and helper routines */ int ofw_bus_gen_setup_devinfo(struct ofw_bus_devinfo *, phandle_t); void ofw_bus_gen_destroy_devinfo(struct ofw_bus_devinfo *); ofw_bus_get_compat_t ofw_bus_gen_get_compat; ofw_bus_get_model_t ofw_bus_gen_get_model; ofw_bus_get_name_t ofw_bus_gen_get_name; ofw_bus_get_node_t ofw_bus_gen_get_node; ofw_bus_get_type_t ofw_bus_gen_get_type; /* Helper method to report interesting OF properties in pnpinfo */ bus_child_pnpinfo_str_t ofw_bus_gen_child_pnpinfo_str; /* Routines for processing firmware interrupt maps */ void ofw_bus_setup_iinfo(phandle_t, struct ofw_bus_iinfo *, int); int ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int, void *, int, void *, int, phandle_t *); int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *, void *, void *, int, phandle_t *); /* Routines for parsing device-tree data into resource lists. */ int ofw_bus_reg_to_rl(device_t, phandle_t, pcell_t, pcell_t, struct resource_list *); int ofw_bus_intr_to_rl(device_t, phandle_t, struct resource_list *, int *); /* Helper to get device status property */ const char *ofw_bus_get_status(device_t dev); int ofw_bus_status_okay(device_t dev); /* Helper to get node's interrupt parent */ phandle_t ofw_bus_find_iparent(phandle_t); /* Helper routine for checking compat prop */ int ofw_bus_is_compatible(device_t, const char *); int ofw_bus_is_compatible_strict(device_t, const char *); /* * Helper routine to search a list of compat properties. The table is * terminated by an entry with a NULL compat-string pointer; a pointer to that * table entry is returned if none of the compat strings match for the device, * giving you control over the not-found value. Will not return NULL unless the * provided table pointer is NULL. */ const struct ofw_compat_data * ofw_bus_search_compatible(device_t, const struct ofw_compat_data *); /* Helper routine for checking existence of a prop */ int ofw_bus_has_prop(device_t, const char *); /* Helper to search for a child with a given compat prop */ phandle_t ofw_bus_find_compatible(phandle_t, const char *); /* Helper to search for a child with a given name */ phandle_t ofw_bus_find_child(phandle_t, const char *); /* Helper routine to find a device_t child matchig a given phandle_t */ device_t ofw_bus_find_child_device_by_phandle(device_t bus, phandle_t node); /* Helper routines for parsing lists */ int ofw_bus_parse_xref_list_alloc(phandle_t node, const char *list_name, const char *cells_name, int idx, phandle_t *producer, int *ncells, pcell_t **cells); int ofw_bus_find_string_index(phandle_t node, const char *list_name, const char *name, int *idx); int ofw_bus_string_list_to_array(phandle_t node, const char *list_name, const char ***array); #endif /* !_DEV_OFW_OFW_BUS_SUBR_H_ */ Index: user/alc/PQ_LAUNDRY/sys/geom/sched/gs_delay.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/geom/sched/gs_delay.c (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/geom/sched/gs_delay.c (revision 292449) @@ -0,0 +1,264 @@ +/*- + * Copyright (c) 2015 Netflix, Inc. + * + * Derived from gs_rr.c: + * Copyright (c) 2009-2010 Fabio Checconi + * Copyright (c) 2009-2010 Luigi Rizzo, Universita` di Pisa + * 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 AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + * $FreeBSD$ + * + * A simple scheduler that just delays certain transactions by a certain + * amount. We collect all the transactions that are 'done' and put them on + * a queue. The queue is run through every so often and the transactions that + * have taken longer than the threshold delay are completed. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gs_scheduler.h" + +/* Useful constants */ +#define BTFRAC_1US 18446744073709ULL /* 2^64 / 1000000 */ + +/* list of scheduler instances */ +LIST_HEAD(g_scheds, g_delay_softc); + +/* + * Per device descriptor, holding the Round Robin list of queues + * accessing the disk, a reference to the geom, and the timer. + */ +struct g_delay_softc { + struct g_geom *sc_geom; + + struct bio_queue_head sc_bioq; /* queue of pending requests */ + struct callout sc_wait; /* timer for completing with delays */ + + /* Statistics */ + int sc_in_flight; /* requests in the driver */ +}; + +/* + * parameters, config and stats + */ +struct g_delay_params { + uint64_t io; + int bypass; /* bypass scheduling */ + int units; /* how many instances */ + int latency; /* How big a latncy are hoping for */ +}; + +static struct g_delay_params me = { + .bypass = 0, + .units = 0, + .latency = 0, + .io = 0, +}; +struct g_delay_params *gs_delay_me = &me; + +SYSCTL_DECL(_kern_geom_sched); +static SYSCTL_NODE(_kern_geom_sched, OID_AUTO, delay, CTLFLAG_RW, 0, + "GEOM_SCHED DELAY stuff"); +SYSCTL_INT(_kern_geom_sched_delay, OID_AUTO, bypass, CTLFLAG_RD, + &me.bypass, 0, "Scheduler bypass"); +SYSCTL_INT(_kern_geom_sched_delay, OID_AUTO, units, CTLFLAG_RD, + &me.units, 0, "Scheduler instances"); +SYSCTL_INT(_kern_geom_sched_delay, OID_AUTO, latency, CTLFLAG_RW, + &me.latency, 0, "Minimum latency for requests, in microseconds (1/hz resolution)"); +SYSCTL_QUAD(_kern_geom_sched_delay, OID_AUTO, io, CTLFLAG_RW, + &me.io, 0, "I/Os delayed\n"); + +static int +g_delay_init_class(void *data, void *priv) +{ + return (0); +} + +static void +g_delay_fini_class(void *data, void *priv) +{ +} + +/* + * Called on a request arrival, timeout or completion. + * Try to serve a request among those queued. + */ +static struct bio * +g_delay_next(void *data, int force) +{ + struct g_delay_softc *sc = data; + struct bio *bp; + struct bintime bt; + + bp = bioq_first(&sc->sc_bioq); + if (bp == NULL) + return (NULL); + + /* + * If the time isn't yet ripe for this bp to be let loose, + * then the time isn't ripe for any of its friends either + * since we insert in-order. Terminate if the bio hasn't + * aged appropriately. Note that there's pathology here + * such that we may be up to one tick early in releasing + * this I/O. We could implement this up to a tick late too + * but choose not to. + */ + getbinuptime(&bt); /* BIO's bio_t0 is uptime */ + if (bintime_cmp(&bp->bio_t0, &bt, >)) + return (NULL); + me.io++; + + /* + * The bp has mellowed enough, let it through and update stats. + * If there's others, we'll catch them next time we get called. + */ + sc->sc_in_flight++; + + bp = bioq_takefirst(&sc->sc_bioq); + return (bp); +} + +/* + * Called when a real request for disk I/O arrives. + * Locate the queue associated with the client. + * If the queue is the one we are anticipating for, reset its timeout; + * if the queue is not in the round robin list, insert it in the list. + * On any error, do not queue the request and return -1, the caller + * will take care of this request. + */ +static int +g_delay_start(void *data, struct bio *bp) +{ + struct g_delay_softc *sc = data; + + if (me.bypass) + return (-1); /* bypass the scheduler */ + + bp->bio_caller1 = sc; + getbinuptime(&bp->bio_t0); /* BIO's bio_t0 is uptime */ + bintime_addx(&bp->bio_t0, BTFRAC_1US * me.latency); + + /* + * Keep the I/Os ordered. Lower layers will reorder as we release them down. + * We rely on this in g_delay_next() so that we delay all things equally. Even + * if we move to multiple queues to push stuff down the stack, we'll want to + * insert in order and let the lower layers do whatever reordering they want. + */ + bioq_insert_tail(&sc->sc_bioq, bp); + + return (0); +} + +static void +g_delay_timeout(void *data) +{ + struct g_delay_softc *sc = data; + + g_sched_lock(sc->sc_geom); + g_sched_dispatch(sc->sc_geom); + g_sched_unlock(sc->sc_geom); + callout_reset(&sc->sc_wait, 1, g_delay_timeout, sc); +} + +/* + * Module glue: allocate descriptor, initialize its fields. + */ +static void * +g_delay_init(struct g_geom *geom) +{ + struct g_delay_softc *sc; + + sc = malloc(sizeof *sc, M_GEOM_SCHED, M_WAITOK | M_ZERO); + sc->sc_geom = geom; + bioq_init(&sc->sc_bioq); + callout_init(&sc->sc_wait, CALLOUT_MPSAFE); + callout_reset(&sc->sc_wait, 1, g_delay_timeout, sc); + me.units++; + + return (sc); +} + +/* + * Module glue -- drain the callout structure, destroy the + * hash table and its element, and free the descriptor. + */ +static void +g_delay_fini(void *data) +{ + struct g_delay_softc *sc = data; + + /* We're force drained before getting here */ + + /* Kick out timers */ + callout_drain(&sc->sc_wait); + me.units--; + free(sc, M_GEOM_SCHED); +} + +/* + * Called when the request under service terminates. + * Start the anticipation timer if needed. + */ +static void +g_delay_done(void *data, struct bio *bp) +{ + struct g_delay_softc *sc = data; + + sc->sc_in_flight--; + + g_sched_dispatch(sc->sc_geom); +} + +static void +g_delay_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, + struct g_consumer *cp, struct g_provider *pp) +{ +} + +static struct g_gsched g_delay = { + .gs_name = "delay", + .gs_priv_size = 0, + .gs_init = g_delay_init, + .gs_fini = g_delay_fini, + .gs_start = g_delay_start, + .gs_done = g_delay_done, + .gs_next = g_delay_next, + .gs_dumpconf = g_delay_dumpconf, + .gs_init_class = g_delay_init_class, + .gs_fini_class = g_delay_fini_class, +}; + +DECLARE_GSCHED_MODULE(delay, &g_delay); Property changes on: user/alc/PQ_LAUNDRY/sys/geom/sched/gs_delay.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/kern/kern_proc.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/kern/kern_proc.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/kern/kern_proc.c (revision 292449) @@ -1,3053 +1,3054 @@ /*- * Copyright (c) 1982, 1986, 1989, 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. * 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. * * @(#)kern_proc.c 8.7 (Berkeley) 2/14/95 */ #include __FBSDID("$FreeBSD$"); #include "opt_compat.h" #include "opt_ddb.h" #include "opt_ktrace.h" #include "opt_kstack_pages.h" #include "opt_stack.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DDB #include #endif #include #include #include #include #include #include #include #include #ifdef COMPAT_FREEBSD32 #include #include #endif SDT_PROVIDER_DEFINE(proc); SDT_PROBE_DEFINE4(proc, , ctor, entry, "struct proc *", "int", "void *", "int"); SDT_PROBE_DEFINE4(proc, , ctor, return, "struct proc *", "int", "void *", "int"); SDT_PROBE_DEFINE4(proc, , dtor, entry, "struct proc *", "int", "void *", "struct thread *"); SDT_PROBE_DEFINE3(proc, , dtor, return, "struct proc *", "int", "void *"); SDT_PROBE_DEFINE3(proc, , init, entry, "struct proc *", "int", "int"); SDT_PROBE_DEFINE3(proc, , init, return, "struct proc *", "int", "int"); MALLOC_DEFINE(M_PGRP, "pgrp", "process group header"); MALLOC_DEFINE(M_SESSION, "session", "session header"); static MALLOC_DEFINE(M_PROC, "proc", "Proc structures"); MALLOC_DEFINE(M_SUBPROC, "subproc", "Proc sub-structures"); static void doenterpgrp(struct proc *, struct pgrp *); static void orphanpg(struct pgrp *pg); static void fill_kinfo_aggregate(struct proc *p, struct kinfo_proc *kp); static void fill_kinfo_proc_only(struct proc *p, struct kinfo_proc *kp); static void fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp, int preferthread); static void pgadjustjobc(struct pgrp *pgrp, int entering); static void pgdelete(struct pgrp *); static int proc_ctor(void *mem, int size, void *arg, int flags); static void proc_dtor(void *mem, int size, void *arg); static int proc_init(void *mem, int size, int flags); static void proc_fini(void *mem, int size); static void pargs_free(struct pargs *pa); static struct proc *zpfind_locked(pid_t pid); /* * Other process lists */ struct pidhashhead *pidhashtbl; u_long pidhash; struct pgrphashhead *pgrphashtbl; u_long pgrphash; struct proclist allproc; struct proclist zombproc; struct sx allproc_lock; struct sx proctree_lock; struct mtx ppeers_lock; uma_zone_t proc_zone; /* * The offset of various fields in struct proc and struct thread. * These are used by kernel debuggers to enumerate kernel threads and * processes. */ const int proc_off_p_pid = offsetof(struct proc, p_pid); const int proc_off_p_comm = offsetof(struct proc, p_comm); const int proc_off_p_list = offsetof(struct proc, p_list); const int proc_off_p_threads = offsetof(struct proc, p_threads); const int thread_off_td_tid = offsetof(struct thread, td_tid); const int thread_off_td_name = offsetof(struct thread, td_name); const int thread_off_td_oncpu = offsetof(struct thread, td_oncpu); const int thread_off_td_pcb = offsetof(struct thread, td_pcb); const int thread_off_td_plist = offsetof(struct thread, td_plist); int kstack_pages = KSTACK_PAGES; SYSCTL_INT(_kern, OID_AUTO, kstack_pages, CTLFLAG_RD, &kstack_pages, 0, "Kernel stack size in pages"); static int vmmap_skip_res_cnt = 0; SYSCTL_INT(_kern, OID_AUTO, proc_vmmap_skip_resident_count, CTLFLAG_RW, &vmmap_skip_res_cnt, 0, "Skip calculation of the pages resident count in kern.proc.vmmap"); CTASSERT(sizeof(struct kinfo_proc) == KINFO_PROC_SIZE); #ifdef COMPAT_FREEBSD32 CTASSERT(sizeof(struct kinfo_proc32) == KINFO_PROC32_SIZE); #endif /* * Initialize global process hashing structures. */ void procinit() { sx_init(&allproc_lock, "allproc"); sx_init(&proctree_lock, "proctree"); mtx_init(&ppeers_lock, "p_peers", NULL, MTX_DEF); LIST_INIT(&allproc); LIST_INIT(&zombproc); pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash); pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash); proc_zone = uma_zcreate("PROC", sched_sizeof_proc(), proc_ctor, proc_dtor, proc_init, proc_fini, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); uihashinit(); } /* * Prepare a proc for use. */ static int proc_ctor(void *mem, int size, void *arg, int flags) { struct proc *p; p = (struct proc *)mem; SDT_PROBE4(proc, , ctor , entry, p, size, arg, flags); EVENTHANDLER_INVOKE(process_ctor, p); SDT_PROBE4(proc, , ctor , return, p, size, arg, flags); return (0); } /* * Reclaim a proc after use. */ static void proc_dtor(void *mem, int size, void *arg) { struct proc *p; struct thread *td; /* INVARIANTS checks go here */ p = (struct proc *)mem; td = FIRST_THREAD_IN_PROC(p); SDT_PROBE4(proc, , dtor, entry, p, size, arg, td); if (td != NULL) { #ifdef INVARIANTS KASSERT((p->p_numthreads == 1), ("bad number of threads in exiting process")); KASSERT(STAILQ_EMPTY(&p->p_ktr), ("proc_dtor: non-empty p_ktr")); #endif /* Free all OSD associated to this thread. */ osd_thread_exit(td); } EVENTHANDLER_INVOKE(process_dtor, p); if (p->p_ksi != NULL) KASSERT(! KSI_ONQ(p->p_ksi), ("SIGCHLD queue")); SDT_PROBE3(proc, , dtor, return, p, size, arg); } /* * Initialize type-stable parts of a proc (when newly created). */ static int proc_init(void *mem, int size, int flags) { struct proc *p; p = (struct proc *)mem; SDT_PROBE3(proc, , init, entry, p, size, flags); p->p_sched = (struct p_sched *)&p[1]; mtx_init(&p->p_mtx, "process lock", NULL, MTX_DEF | MTX_DUPOK | MTX_NEW); mtx_init(&p->p_slock, "process slock", NULL, MTX_SPIN | MTX_NEW); mtx_init(&p->p_statmtx, "pstatl", NULL, MTX_SPIN | MTX_NEW); mtx_init(&p->p_itimmtx, "pitiml", NULL, MTX_SPIN | MTX_NEW); mtx_init(&p->p_profmtx, "pprofl", NULL, MTX_SPIN | MTX_NEW); cv_init(&p->p_pwait, "ppwait"); cv_init(&p->p_dbgwait, "dbgwait"); TAILQ_INIT(&p->p_threads); /* all threads in proc */ EVENTHANDLER_INVOKE(process_init, p); p->p_stats = pstats_alloc(); + p->p_pgrp = NULL; SDT_PROBE3(proc, , init, return, p, size, flags); return (0); } /* * UMA should ensure that this function is never called. * Freeing a proc structure would violate type stability. */ static void proc_fini(void *mem, int size) { #ifdef notnow struct proc *p; p = (struct proc *)mem; EVENTHANDLER_INVOKE(process_fini, p); pstats_free(p->p_stats); thread_free(FIRST_THREAD_IN_PROC(p)); mtx_destroy(&p->p_mtx); if (p->p_ksi != NULL) ksiginfo_free(p->p_ksi); #else panic("proc reclaimed"); #endif } /* * Is p an inferior of the current process? */ int inferior(struct proc *p) { sx_assert(&proctree_lock, SX_LOCKED); PROC_LOCK_ASSERT(p, MA_OWNED); for (; p != curproc; p = proc_realparent(p)) { if (p->p_pid == 0) return (0); } return (1); } struct proc * pfind_locked(pid_t pid) { struct proc *p; sx_assert(&allproc_lock, SX_LOCKED); LIST_FOREACH(p, PIDHASH(pid), p_hash) { if (p->p_pid == pid) { PROC_LOCK(p); if (p->p_state == PRS_NEW) { PROC_UNLOCK(p); p = NULL; } break; } } return (p); } /* * Locate a process by number; return only "live" processes -- i.e., neither * zombies nor newly born but incompletely initialized processes. By not * returning processes in the PRS_NEW state, we allow callers to avoid * testing for that condition to avoid dereferencing p_ucred, et al. */ struct proc * pfind(pid_t pid) { struct proc *p; sx_slock(&allproc_lock); p = pfind_locked(pid); sx_sunlock(&allproc_lock); return (p); } static struct proc * pfind_tid_locked(pid_t tid) { struct proc *p; struct thread *td; sx_assert(&allproc_lock, SX_LOCKED); FOREACH_PROC_IN_SYSTEM(p) { PROC_LOCK(p); if (p->p_state == PRS_NEW) { PROC_UNLOCK(p); continue; } FOREACH_THREAD_IN_PROC(p, td) { if (td->td_tid == tid) goto found; } PROC_UNLOCK(p); } found: return (p); } /* * Locate a process group by number. * The caller must hold proctree_lock. */ struct pgrp * pgfind(pgid) register pid_t pgid; { register struct pgrp *pgrp; sx_assert(&proctree_lock, SX_LOCKED); LIST_FOREACH(pgrp, PGRPHASH(pgid), pg_hash) { if (pgrp->pg_id == pgid) { PGRP_LOCK(pgrp); return (pgrp); } } return (NULL); } /* * Locate process and do additional manipulations, depending on flags. */ int pget(pid_t pid, int flags, struct proc **pp) { struct proc *p; int error; sx_slock(&allproc_lock); if (pid <= PID_MAX) { p = pfind_locked(pid); if (p == NULL && (flags & PGET_NOTWEXIT) == 0) p = zpfind_locked(pid); } else if ((flags & PGET_NOTID) == 0) { p = pfind_tid_locked(pid); } else { p = NULL; } sx_sunlock(&allproc_lock); if (p == NULL) return (ESRCH); if ((flags & PGET_CANSEE) != 0) { error = p_cansee(curthread, p); if (error != 0) goto errout; } if ((flags & PGET_CANDEBUG) != 0) { error = p_candebug(curthread, p); if (error != 0) goto errout; } if ((flags & PGET_ISCURRENT) != 0 && curproc != p) { error = EPERM; goto errout; } if ((flags & PGET_NOTWEXIT) != 0 && (p->p_flag & P_WEXIT) != 0) { error = ESRCH; goto errout; } if ((flags & PGET_NOTINEXEC) != 0 && (p->p_flag & P_INEXEC) != 0) { /* * XXXRW: Not clear ESRCH is the right error during proc * execve(). */ error = ESRCH; goto errout; } if ((flags & PGET_HOLD) != 0) { _PHOLD(p); PROC_UNLOCK(p); } *pp = p; return (0); errout: PROC_UNLOCK(p); return (error); } /* * Create a new process group. * pgid must be equal to the pid of p. * Begin a new session if required. */ int enterpgrp(p, pgid, pgrp, sess) register struct proc *p; pid_t pgid; struct pgrp *pgrp; struct session *sess; { sx_assert(&proctree_lock, SX_XLOCKED); KASSERT(pgrp != NULL, ("enterpgrp: pgrp == NULL")); KASSERT(p->p_pid == pgid, ("enterpgrp: new pgrp and pid != pgid")); KASSERT(pgfind(pgid) == NULL, ("enterpgrp: pgrp with pgid exists")); KASSERT(!SESS_LEADER(p), ("enterpgrp: session leader attempted setpgrp")); mtx_init(&pgrp->pg_mtx, "process group", NULL, MTX_DEF | MTX_DUPOK); if (sess != NULL) { /* * new session */ mtx_init(&sess->s_mtx, "session", NULL, MTX_DEF); PROC_LOCK(p); p->p_flag &= ~P_CONTROLT; PROC_UNLOCK(p); PGRP_LOCK(pgrp); sess->s_leader = p; sess->s_sid = p->p_pid; refcount_init(&sess->s_count, 1); sess->s_ttyvp = NULL; sess->s_ttydp = NULL; sess->s_ttyp = NULL; bcopy(p->p_session->s_login, sess->s_login, sizeof(sess->s_login)); pgrp->pg_session = sess; KASSERT(p == curproc, ("enterpgrp: mksession and p != curproc")); } else { pgrp->pg_session = p->p_session; sess_hold(pgrp->pg_session); PGRP_LOCK(pgrp); } pgrp->pg_id = pgid; LIST_INIT(&pgrp->pg_members); /* * As we have an exclusive lock of proctree_lock, * this should not deadlock. */ LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash); pgrp->pg_jobc = 0; SLIST_INIT(&pgrp->pg_sigiolst); PGRP_UNLOCK(pgrp); doenterpgrp(p, pgrp); return (0); } /* * Move p to an existing process group */ int enterthispgrp(p, pgrp) register struct proc *p; struct pgrp *pgrp; { sx_assert(&proctree_lock, SX_XLOCKED); PROC_LOCK_ASSERT(p, MA_NOTOWNED); PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED); PGRP_LOCK_ASSERT(p->p_pgrp, MA_NOTOWNED); SESS_LOCK_ASSERT(p->p_session, MA_NOTOWNED); KASSERT(pgrp->pg_session == p->p_session, ("%s: pgrp's session %p, p->p_session %p.\n", __func__, pgrp->pg_session, p->p_session)); KASSERT(pgrp != p->p_pgrp, ("%s: p belongs to pgrp.", __func__)); doenterpgrp(p, pgrp); return (0); } /* * Move p to a process group */ static void doenterpgrp(p, pgrp) struct proc *p; struct pgrp *pgrp; { struct pgrp *savepgrp; sx_assert(&proctree_lock, SX_XLOCKED); PROC_LOCK_ASSERT(p, MA_NOTOWNED); PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED); PGRP_LOCK_ASSERT(p->p_pgrp, MA_NOTOWNED); SESS_LOCK_ASSERT(p->p_session, MA_NOTOWNED); savepgrp = p->p_pgrp; /* * Adjust eligibility of affected pgrps to participate in job control. * Increment eligibility counts before decrementing, otherwise we * could reach 0 spuriously during the first call. */ fixjobc(p, pgrp, 1); fixjobc(p, p->p_pgrp, 0); PGRP_LOCK(pgrp); PGRP_LOCK(savepgrp); PROC_LOCK(p); LIST_REMOVE(p, p_pglist); p->p_pgrp = pgrp; PROC_UNLOCK(p); LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist); PGRP_UNLOCK(savepgrp); PGRP_UNLOCK(pgrp); if (LIST_EMPTY(&savepgrp->pg_members)) pgdelete(savepgrp); } /* * remove process from process group */ int leavepgrp(p) register struct proc *p; { struct pgrp *savepgrp; sx_assert(&proctree_lock, SX_XLOCKED); savepgrp = p->p_pgrp; PGRP_LOCK(savepgrp); PROC_LOCK(p); LIST_REMOVE(p, p_pglist); p->p_pgrp = NULL; PROC_UNLOCK(p); PGRP_UNLOCK(savepgrp); if (LIST_EMPTY(&savepgrp->pg_members)) pgdelete(savepgrp); return (0); } /* * delete a process group */ static void pgdelete(pgrp) register struct pgrp *pgrp; { struct session *savesess; struct tty *tp; sx_assert(&proctree_lock, SX_XLOCKED); PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED); SESS_LOCK_ASSERT(pgrp->pg_session, MA_NOTOWNED); /* * Reset any sigio structures pointing to us as a result of * F_SETOWN with our pgid. */ funsetownlst(&pgrp->pg_sigiolst); PGRP_LOCK(pgrp); tp = pgrp->pg_session->s_ttyp; LIST_REMOVE(pgrp, pg_hash); savesess = pgrp->pg_session; PGRP_UNLOCK(pgrp); /* Remove the reference to the pgrp before deallocating it. */ if (tp != NULL) { tty_lock(tp); tty_rel_pgrp(tp, pgrp); } mtx_destroy(&pgrp->pg_mtx); free(pgrp, M_PGRP); sess_release(savesess); } static void pgadjustjobc(pgrp, entering) struct pgrp *pgrp; int entering; { PGRP_LOCK(pgrp); if (entering) pgrp->pg_jobc++; else { --pgrp->pg_jobc; if (pgrp->pg_jobc == 0) orphanpg(pgrp); } PGRP_UNLOCK(pgrp); } /* * Adjust pgrp jobc counters when specified process changes process group. * We count the number of processes in each process group that "qualify" * the group for terminal job control (those with a parent in a different * process group of the same session). If that count reaches zero, the * process group becomes orphaned. Check both the specified process' * process group and that of its children. * entering == 0 => p is leaving specified group. * entering == 1 => p is entering specified group. */ void fixjobc(p, pgrp, entering) register struct proc *p; register struct pgrp *pgrp; int entering; { register struct pgrp *hispgrp; register struct session *mysession; sx_assert(&proctree_lock, SX_LOCKED); PROC_LOCK_ASSERT(p, MA_NOTOWNED); PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED); SESS_LOCK_ASSERT(pgrp->pg_session, MA_NOTOWNED); /* * Check p's parent to see whether p qualifies its own process * group; if so, adjust count for p's process group. */ mysession = pgrp->pg_session; if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && hispgrp->pg_session == mysession) pgadjustjobc(pgrp, entering); /* * Check this process' children to see whether they qualify * their process groups; if so, adjust counts for children's * process groups. */ LIST_FOREACH(p, &p->p_children, p_sibling) { hispgrp = p->p_pgrp; if (hispgrp == pgrp || hispgrp->pg_session != mysession) continue; PROC_LOCK(p); if (p->p_state == PRS_ZOMBIE) { PROC_UNLOCK(p); continue; } PROC_UNLOCK(p); pgadjustjobc(hispgrp, entering); } } /* * A process group has become orphaned; * if there are any stopped processes in the group, * hang-up all process in that group. */ static void orphanpg(pg) struct pgrp *pg; { register struct proc *p; PGRP_LOCK_ASSERT(pg, MA_OWNED); LIST_FOREACH(p, &pg->pg_members, p_pglist) { PROC_LOCK(p); if (P_SHOULDSTOP(p) == P_STOPPED_SIG) { PROC_UNLOCK(p); LIST_FOREACH(p, &pg->pg_members, p_pglist) { PROC_LOCK(p); kern_psignal(p, SIGHUP); kern_psignal(p, SIGCONT); PROC_UNLOCK(p); } return; } PROC_UNLOCK(p); } } void sess_hold(struct session *s) { refcount_acquire(&s->s_count); } void sess_release(struct session *s) { if (refcount_release(&s->s_count)) { if (s->s_ttyp != NULL) { tty_lock(s->s_ttyp); tty_rel_sess(s->s_ttyp, s); } mtx_destroy(&s->s_mtx); free(s, M_SESSION); } } #ifdef DDB DB_SHOW_COMMAND(pgrpdump, pgrpdump) { register struct pgrp *pgrp; register struct proc *p; register int i; for (i = 0; i <= pgrphash; i++) { if (!LIST_EMPTY(&pgrphashtbl[i])) { printf("\tindx %d\n", i); LIST_FOREACH(pgrp, &pgrphashtbl[i], pg_hash) { printf( "\tpgrp %p, pgid %ld, sess %p, sesscnt %d, mem %p\n", (void *)pgrp, (long)pgrp->pg_id, (void *)pgrp->pg_session, pgrp->pg_session->s_count, (void *)LIST_FIRST(&pgrp->pg_members)); LIST_FOREACH(p, &pgrp->pg_members, p_pglist) { printf("\t\tpid %ld addr %p pgrp %p\n", (long)p->p_pid, (void *)p, (void *)p->p_pgrp); } } } } } #endif /* DDB */ /* * Calculate the kinfo_proc members which contain process-wide * informations. * Must be called with the target process locked. */ static void fill_kinfo_aggregate(struct proc *p, struct kinfo_proc *kp) { struct thread *td; PROC_LOCK_ASSERT(p, MA_OWNED); kp->ki_estcpu = 0; kp->ki_pctcpu = 0; FOREACH_THREAD_IN_PROC(p, td) { thread_lock(td); kp->ki_pctcpu += sched_pctcpu(td); kp->ki_estcpu += td->td_estcpu; thread_unlock(td); } } /* * Clear kinfo_proc and fill in any information that is common * to all threads in the process. * Must be called with the target process locked. */ static void fill_kinfo_proc_only(struct proc *p, struct kinfo_proc *kp) { struct thread *td0; struct tty *tp; struct session *sp; struct ucred *cred; struct sigacts *ps; /* For proc_realparent. */ sx_assert(&proctree_lock, SX_LOCKED); PROC_LOCK_ASSERT(p, MA_OWNED); bzero(kp, sizeof(*kp)); kp->ki_structsize = sizeof(*kp); kp->ki_paddr = p; kp->ki_addr =/* p->p_addr; */0; /* XXX */ kp->ki_args = p->p_args; kp->ki_textvp = p->p_textvp; #ifdef KTRACE kp->ki_tracep = p->p_tracevp; kp->ki_traceflag = p->p_traceflag; #endif kp->ki_fd = p->p_fd; kp->ki_vmspace = p->p_vmspace; kp->ki_flag = p->p_flag; kp->ki_flag2 = p->p_flag2; cred = p->p_ucred; if (cred) { kp->ki_uid = cred->cr_uid; kp->ki_ruid = cred->cr_ruid; kp->ki_svuid = cred->cr_svuid; kp->ki_cr_flags = 0; if (cred->cr_flags & CRED_FLAG_CAPMODE) kp->ki_cr_flags |= KI_CRF_CAPABILITY_MODE; /* XXX bde doesn't like KI_NGROUPS */ if (cred->cr_ngroups > KI_NGROUPS) { kp->ki_ngroups = KI_NGROUPS; kp->ki_cr_flags |= KI_CRF_GRP_OVERFLOW; } else kp->ki_ngroups = cred->cr_ngroups; bcopy(cred->cr_groups, kp->ki_groups, kp->ki_ngroups * sizeof(gid_t)); kp->ki_rgid = cred->cr_rgid; kp->ki_svgid = cred->cr_svgid; /* If jailed(cred), emulate the old P_JAILED flag. */ if (jailed(cred)) { kp->ki_flag |= P_JAILED; /* If inside the jail, use 0 as a jail ID. */ if (cred->cr_prison != curthread->td_ucred->cr_prison) kp->ki_jid = cred->cr_prison->pr_id; } strlcpy(kp->ki_loginclass, cred->cr_loginclass->lc_name, sizeof(kp->ki_loginclass)); } ps = p->p_sigacts; if (ps) { mtx_lock(&ps->ps_mtx); kp->ki_sigignore = ps->ps_sigignore; kp->ki_sigcatch = ps->ps_sigcatch; mtx_unlock(&ps->ps_mtx); } if (p->p_state != PRS_NEW && p->p_state != PRS_ZOMBIE && p->p_vmspace != NULL) { struct vmspace *vm = p->p_vmspace; kp->ki_size = vm->vm_map.size; kp->ki_rssize = vmspace_resident_count(vm); /*XXX*/ FOREACH_THREAD_IN_PROC(p, td0) { if (!TD_IS_SWAPPED(td0)) kp->ki_rssize += td0->td_kstack_pages; } kp->ki_swrss = vm->vm_swrss; kp->ki_tsize = vm->vm_tsize; kp->ki_dsize = vm->vm_dsize; kp->ki_ssize = vm->vm_ssize; } else if (p->p_state == PRS_ZOMBIE) kp->ki_stat = SZOMB; if (kp->ki_flag & P_INMEM) kp->ki_sflag = PS_INMEM; else kp->ki_sflag = 0; /* Calculate legacy swtime as seconds since 'swtick'. */ kp->ki_swtime = (ticks - p->p_swtick) / hz; kp->ki_pid = p->p_pid; kp->ki_nice = p->p_nice; kp->ki_fibnum = p->p_fibnum; kp->ki_start = p->p_stats->p_start; timevaladd(&kp->ki_start, &boottime); PROC_STATLOCK(p); rufetch(p, &kp->ki_rusage); kp->ki_runtime = cputick2usec(p->p_rux.rux_runtime); calcru(p, &kp->ki_rusage.ru_utime, &kp->ki_rusage.ru_stime); PROC_STATUNLOCK(p); calccru(p, &kp->ki_childutime, &kp->ki_childstime); /* Some callers want child times in a single value. */ kp->ki_childtime = kp->ki_childstime; timevaladd(&kp->ki_childtime, &kp->ki_childutime); FOREACH_THREAD_IN_PROC(p, td0) kp->ki_cow += td0->td_cow; tp = NULL; if (p->p_pgrp) { kp->ki_pgid = p->p_pgrp->pg_id; kp->ki_jobc = p->p_pgrp->pg_jobc; sp = p->p_pgrp->pg_session; if (sp != NULL) { kp->ki_sid = sp->s_sid; SESS_LOCK(sp); strlcpy(kp->ki_login, sp->s_login, sizeof(kp->ki_login)); if (sp->s_ttyvp) kp->ki_kiflag |= KI_CTTY; if (SESS_LEADER(p)) kp->ki_kiflag |= KI_SLEADER; /* XXX proctree_lock */ tp = sp->s_ttyp; SESS_UNLOCK(sp); } } if ((p->p_flag & P_CONTROLT) && tp != NULL) { kp->ki_tdev = tty_udev(tp); kp->ki_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; if (tp->t_session) kp->ki_tsid = tp->t_session->s_sid; } else kp->ki_tdev = NODEV; if (p->p_comm[0] != '\0') strlcpy(kp->ki_comm, p->p_comm, sizeof(kp->ki_comm)); if (p->p_sysent && p->p_sysent->sv_name != NULL && p->p_sysent->sv_name[0] != '\0') strlcpy(kp->ki_emul, p->p_sysent->sv_name, sizeof(kp->ki_emul)); kp->ki_siglist = p->p_siglist; kp->ki_xstat = KW_EXITCODE(p->p_xexit, p->p_xsig); kp->ki_acflag = p->p_acflag; kp->ki_lock = p->p_lock; if (p->p_pptr) { kp->ki_ppid = proc_realparent(p)->p_pid; if (p->p_flag & P_TRACED) kp->ki_tracer = p->p_pptr->p_pid; } } /* * Fill in information that is thread specific. Must be called with * target process locked. If 'preferthread' is set, overwrite certain * process-related fields that are maintained for both threads and * processes. */ static void fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp, int preferthread) { struct proc *p; p = td->td_proc; kp->ki_tdaddr = td; PROC_LOCK_ASSERT(p, MA_OWNED); if (preferthread) PROC_STATLOCK(p); thread_lock(td); if (td->td_wmesg != NULL) strlcpy(kp->ki_wmesg, td->td_wmesg, sizeof(kp->ki_wmesg)); else bzero(kp->ki_wmesg, sizeof(kp->ki_wmesg)); strlcpy(kp->ki_tdname, td->td_name, sizeof(kp->ki_tdname)); if (TD_ON_LOCK(td)) { kp->ki_kiflag |= KI_LOCKBLOCK; strlcpy(kp->ki_lockname, td->td_lockname, sizeof(kp->ki_lockname)); } else { kp->ki_kiflag &= ~KI_LOCKBLOCK; bzero(kp->ki_lockname, sizeof(kp->ki_lockname)); } if (p->p_state == PRS_NORMAL) { /* approximate. */ if (TD_ON_RUNQ(td) || TD_CAN_RUN(td) || TD_IS_RUNNING(td)) { kp->ki_stat = SRUN; } else if (P_SHOULDSTOP(p)) { kp->ki_stat = SSTOP; } else if (TD_IS_SLEEPING(td)) { kp->ki_stat = SSLEEP; } else if (TD_ON_LOCK(td)) { kp->ki_stat = SLOCK; } else { kp->ki_stat = SWAIT; } } else if (p->p_state == PRS_ZOMBIE) { kp->ki_stat = SZOMB; } else { kp->ki_stat = SIDL; } /* Things in the thread */ kp->ki_wchan = td->td_wchan; kp->ki_pri.pri_level = td->td_priority; kp->ki_pri.pri_native = td->td_base_pri; /* * Note: legacy fields; clamp at the old NOCPU value and/or * the maximum u_char CPU value. */ if (td->td_lastcpu == NOCPU) kp->ki_lastcpu_old = NOCPU_OLD; else if (td->td_lastcpu > MAXCPU_OLD) kp->ki_lastcpu_old = MAXCPU_OLD; else kp->ki_lastcpu_old = td->td_lastcpu; if (td->td_oncpu == NOCPU) kp->ki_oncpu_old = NOCPU_OLD; else if (td->td_oncpu > MAXCPU_OLD) kp->ki_oncpu_old = MAXCPU_OLD; else kp->ki_oncpu_old = td->td_oncpu; kp->ki_lastcpu = td->td_lastcpu; kp->ki_oncpu = td->td_oncpu; kp->ki_tdflags = td->td_flags; kp->ki_tid = td->td_tid; kp->ki_numthreads = p->p_numthreads; kp->ki_pcb = td->td_pcb; kp->ki_kstack = (void *)td->td_kstack; kp->ki_slptime = (ticks - td->td_slptick) / hz; kp->ki_pri.pri_class = td->td_pri_class; kp->ki_pri.pri_user = td->td_user_pri; if (preferthread) { rufetchtd(td, &kp->ki_rusage); kp->ki_runtime = cputick2usec(td->td_rux.rux_runtime); kp->ki_pctcpu = sched_pctcpu(td); kp->ki_estcpu = td->td_estcpu; kp->ki_cow = td->td_cow; } /* We can't get this anymore but ps etc never used it anyway. */ kp->ki_rqindex = 0; if (preferthread) kp->ki_siglist = td->td_siglist; kp->ki_sigmask = td->td_sigmask; thread_unlock(td); if (preferthread) PROC_STATUNLOCK(p); } /* * Fill in a kinfo_proc structure for the specified process. * Must be called with the target process locked. */ void fill_kinfo_proc(struct proc *p, struct kinfo_proc *kp) { MPASS(FIRST_THREAD_IN_PROC(p) != NULL); fill_kinfo_proc_only(p, kp); fill_kinfo_thread(FIRST_THREAD_IN_PROC(p), kp, 0); fill_kinfo_aggregate(p, kp); } struct pstats * pstats_alloc(void) { return (malloc(sizeof(struct pstats), M_SUBPROC, M_ZERO|M_WAITOK)); } /* * Copy parts of p_stats; zero the rest of p_stats (statistics). */ void pstats_fork(struct pstats *src, struct pstats *dst) { bzero(&dst->pstat_startzero, __rangeof(struct pstats, pstat_startzero, pstat_endzero)); bcopy(&src->pstat_startcopy, &dst->pstat_startcopy, __rangeof(struct pstats, pstat_startcopy, pstat_endcopy)); } void pstats_free(struct pstats *ps) { free(ps, M_SUBPROC); } static struct proc * zpfind_locked(pid_t pid) { struct proc *p; sx_assert(&allproc_lock, SX_LOCKED); LIST_FOREACH(p, &zombproc, p_list) { if (p->p_pid == pid) { PROC_LOCK(p); break; } } return (p); } /* * Locate a zombie process by number */ struct proc * zpfind(pid_t pid) { struct proc *p; sx_slock(&allproc_lock); p = zpfind_locked(pid); sx_sunlock(&allproc_lock); return (p); } #ifdef COMPAT_FREEBSD32 /* * This function is typically used to copy out the kernel address, so * it can be replaced by assignment of zero. */ static inline uint32_t ptr32_trim(void *ptr) { uintptr_t uptr; uptr = (uintptr_t)ptr; return ((uptr > UINT_MAX) ? 0 : uptr); } #define PTRTRIM_CP(src,dst,fld) \ do { (dst).fld = ptr32_trim((src).fld); } while (0) static void freebsd32_kinfo_proc_out(const struct kinfo_proc *ki, struct kinfo_proc32 *ki32) { int i; bzero(ki32, sizeof(struct kinfo_proc32)); ki32->ki_structsize = sizeof(struct kinfo_proc32); CP(*ki, *ki32, ki_layout); PTRTRIM_CP(*ki, *ki32, ki_args); PTRTRIM_CP(*ki, *ki32, ki_paddr); PTRTRIM_CP(*ki, *ki32, ki_addr); PTRTRIM_CP(*ki, *ki32, ki_tracep); PTRTRIM_CP(*ki, *ki32, ki_textvp); PTRTRIM_CP(*ki, *ki32, ki_fd); PTRTRIM_CP(*ki, *ki32, ki_vmspace); PTRTRIM_CP(*ki, *ki32, ki_wchan); CP(*ki, *ki32, ki_pid); CP(*ki, *ki32, ki_ppid); CP(*ki, *ki32, ki_pgid); CP(*ki, *ki32, ki_tpgid); CP(*ki, *ki32, ki_sid); CP(*ki, *ki32, ki_tsid); CP(*ki, *ki32, ki_jobc); CP(*ki, *ki32, ki_tdev); CP(*ki, *ki32, ki_siglist); CP(*ki, *ki32, ki_sigmask); CP(*ki, *ki32, ki_sigignore); CP(*ki, *ki32, ki_sigcatch); CP(*ki, *ki32, ki_uid); CP(*ki, *ki32, ki_ruid); CP(*ki, *ki32, ki_svuid); CP(*ki, *ki32, ki_rgid); CP(*ki, *ki32, ki_svgid); CP(*ki, *ki32, ki_ngroups); for (i = 0; i < KI_NGROUPS; i++) CP(*ki, *ki32, ki_groups[i]); CP(*ki, *ki32, ki_size); CP(*ki, *ki32, ki_rssize); CP(*ki, *ki32, ki_swrss); CP(*ki, *ki32, ki_tsize); CP(*ki, *ki32, ki_dsize); CP(*ki, *ki32, ki_ssize); CP(*ki, *ki32, ki_xstat); CP(*ki, *ki32, ki_acflag); CP(*ki, *ki32, ki_pctcpu); CP(*ki, *ki32, ki_estcpu); CP(*ki, *ki32, ki_slptime); CP(*ki, *ki32, ki_swtime); CP(*ki, *ki32, ki_cow); CP(*ki, *ki32, ki_runtime); TV_CP(*ki, *ki32, ki_start); TV_CP(*ki, *ki32, ki_childtime); CP(*ki, *ki32, ki_flag); CP(*ki, *ki32, ki_kiflag); CP(*ki, *ki32, ki_traceflag); CP(*ki, *ki32, ki_stat); CP(*ki, *ki32, ki_nice); CP(*ki, *ki32, ki_lock); CP(*ki, *ki32, ki_rqindex); CP(*ki, *ki32, ki_oncpu); CP(*ki, *ki32, ki_lastcpu); /* XXX TODO: wrap cpu value as appropriate */ CP(*ki, *ki32, ki_oncpu_old); CP(*ki, *ki32, ki_lastcpu_old); bcopy(ki->ki_tdname, ki32->ki_tdname, TDNAMLEN + 1); bcopy(ki->ki_wmesg, ki32->ki_wmesg, WMESGLEN + 1); bcopy(ki->ki_login, ki32->ki_login, LOGNAMELEN + 1); bcopy(ki->ki_lockname, ki32->ki_lockname, LOCKNAMELEN + 1); bcopy(ki->ki_comm, ki32->ki_comm, COMMLEN + 1); bcopy(ki->ki_emul, ki32->ki_emul, KI_EMULNAMELEN + 1); bcopy(ki->ki_loginclass, ki32->ki_loginclass, LOGINCLASSLEN + 1); CP(*ki, *ki32, ki_tracer); CP(*ki, *ki32, ki_flag2); CP(*ki, *ki32, ki_fibnum); CP(*ki, *ki32, ki_cr_flags); CP(*ki, *ki32, ki_jid); CP(*ki, *ki32, ki_numthreads); CP(*ki, *ki32, ki_tid); CP(*ki, *ki32, ki_pri); freebsd32_rusage_out(&ki->ki_rusage, &ki32->ki_rusage); freebsd32_rusage_out(&ki->ki_rusage_ch, &ki32->ki_rusage_ch); PTRTRIM_CP(*ki, *ki32, ki_pcb); PTRTRIM_CP(*ki, *ki32, ki_kstack); PTRTRIM_CP(*ki, *ki32, ki_udata); CP(*ki, *ki32, ki_sflag); CP(*ki, *ki32, ki_tdflags); } #endif int kern_proc_out(struct proc *p, struct sbuf *sb, int flags) { struct thread *td; struct kinfo_proc ki; #ifdef COMPAT_FREEBSD32 struct kinfo_proc32 ki32; #endif int error; PROC_LOCK_ASSERT(p, MA_OWNED); MPASS(FIRST_THREAD_IN_PROC(p) != NULL); error = 0; fill_kinfo_proc(p, &ki); if ((flags & KERN_PROC_NOTHREADS) != 0) { #ifdef COMPAT_FREEBSD32 if ((flags & KERN_PROC_MASK32) != 0) { freebsd32_kinfo_proc_out(&ki, &ki32); if (sbuf_bcat(sb, &ki32, sizeof(ki32)) != 0) error = ENOMEM; } else #endif if (sbuf_bcat(sb, &ki, sizeof(ki)) != 0) error = ENOMEM; } else { FOREACH_THREAD_IN_PROC(p, td) { fill_kinfo_thread(td, &ki, 1); #ifdef COMPAT_FREEBSD32 if ((flags & KERN_PROC_MASK32) != 0) { freebsd32_kinfo_proc_out(&ki, &ki32); if (sbuf_bcat(sb, &ki32, sizeof(ki32)) != 0) error = ENOMEM; } else #endif if (sbuf_bcat(sb, &ki, sizeof(ki)) != 0) error = ENOMEM; if (error != 0) break; } } PROC_UNLOCK(p); return (error); } static int sysctl_out_proc(struct proc *p, struct sysctl_req *req, int flags, int doingzomb) { struct sbuf sb; struct kinfo_proc ki; struct proc *np; int error, error2; pid_t pid; pid = p->p_pid; sbuf_new_for_sysctl(&sb, (char *)&ki, sizeof(ki), req); sbuf_clear_flags(&sb, SBUF_INCLUDENUL); error = kern_proc_out(p, &sb, flags); error2 = sbuf_finish(&sb); sbuf_delete(&sb); if (error != 0) return (error); else if (error2 != 0) return (error2); if (doingzomb) np = zpfind(pid); else { if (pid == 0) return (0); np = pfind(pid); } if (np == NULL) return (ESRCH); if (np != p) { PROC_UNLOCK(np); return (ESRCH); } PROC_UNLOCK(np); return (0); } static int sysctl_kern_proc(SYSCTL_HANDLER_ARGS) { int *name = (int *)arg1; u_int namelen = arg2; struct proc *p; int flags, doingzomb, oid_number; int error = 0; oid_number = oidp->oid_number; if (oid_number != KERN_PROC_ALL && (oid_number & KERN_PROC_INC_THREAD) == 0) flags = KERN_PROC_NOTHREADS; else { flags = 0; oid_number &= ~KERN_PROC_INC_THREAD; } #ifdef COMPAT_FREEBSD32 if (req->flags & SCTL_MASK32) flags |= KERN_PROC_MASK32; #endif if (oid_number == KERN_PROC_PID) { if (namelen != 1) return (EINVAL); error = sysctl_wire_old_buffer(req, 0); if (error) return (error); sx_slock(&proctree_lock); error = pget((pid_t)name[0], PGET_CANSEE, &p); if (error == 0) error = sysctl_out_proc(p, req, flags, 0); sx_sunlock(&proctree_lock); return (error); } switch (oid_number) { case KERN_PROC_ALL: if (namelen != 0) return (EINVAL); break; case KERN_PROC_PROC: if (namelen != 0 && namelen != 1) return (EINVAL); break; default: if (namelen != 1) return (EINVAL); break; } if (!req->oldptr) { /* overestimate by 5 procs */ error = SYSCTL_OUT(req, 0, sizeof (struct kinfo_proc) * 5); if (error) return (error); } error = sysctl_wire_old_buffer(req, 0); if (error != 0) return (error); sx_slock(&proctree_lock); sx_slock(&allproc_lock); for (doingzomb=0 ; doingzomb < 2 ; doingzomb++) { if (!doingzomb) p = LIST_FIRST(&allproc); else p = LIST_FIRST(&zombproc); for (; p != 0; p = LIST_NEXT(p, p_list)) { /* * Skip embryonic processes. */ PROC_LOCK(p); if (p->p_state == PRS_NEW) { PROC_UNLOCK(p); continue; } KASSERT(p->p_ucred != NULL, ("process credential is NULL for non-NEW proc")); /* * Show a user only appropriate processes. */ if (p_cansee(curthread, p)) { PROC_UNLOCK(p); continue; } /* * TODO - make more efficient (see notes below). * do by session. */ switch (oid_number) { case KERN_PROC_GID: if (p->p_ucred->cr_gid != (gid_t)name[0]) { PROC_UNLOCK(p); continue; } break; case KERN_PROC_PGRP: /* could do this by traversing pgrp */ if (p->p_pgrp == NULL || p->p_pgrp->pg_id != (pid_t)name[0]) { PROC_UNLOCK(p); continue; } break; case KERN_PROC_RGID: if (p->p_ucred->cr_rgid != (gid_t)name[0]) { PROC_UNLOCK(p); continue; } break; case KERN_PROC_SESSION: if (p->p_session == NULL || p->p_session->s_sid != (pid_t)name[0]) { PROC_UNLOCK(p); continue; } break; case KERN_PROC_TTY: if ((p->p_flag & P_CONTROLT) == 0 || p->p_session == NULL) { PROC_UNLOCK(p); continue; } /* XXX proctree_lock */ SESS_LOCK(p->p_session); if (p->p_session->s_ttyp == NULL || tty_udev(p->p_session->s_ttyp) != (dev_t)name[0]) { SESS_UNLOCK(p->p_session); PROC_UNLOCK(p); continue; } SESS_UNLOCK(p->p_session); break; case KERN_PROC_UID: if (p->p_ucred->cr_uid != (uid_t)name[0]) { PROC_UNLOCK(p); continue; } break; case KERN_PROC_RUID: if (p->p_ucred->cr_ruid != (uid_t)name[0]) { PROC_UNLOCK(p); continue; } break; case KERN_PROC_PROC: break; default: break; } error = sysctl_out_proc(p, req, flags, doingzomb); if (error) { sx_sunlock(&allproc_lock); sx_sunlock(&proctree_lock); return (error); } } } sx_sunlock(&allproc_lock); sx_sunlock(&proctree_lock); return (0); } struct pargs * pargs_alloc(int len) { struct pargs *pa; pa = malloc(sizeof(struct pargs) + len, M_PARGS, M_WAITOK); refcount_init(&pa->ar_ref, 1); pa->ar_length = len; return (pa); } static void pargs_free(struct pargs *pa) { free(pa, M_PARGS); } void pargs_hold(struct pargs *pa) { if (pa == NULL) return; refcount_acquire(&pa->ar_ref); } void pargs_drop(struct pargs *pa) { if (pa == NULL) return; if (refcount_release(&pa->ar_ref)) pargs_free(pa); } static int proc_read_string(struct thread *td, struct proc *p, const char *sptr, char *buf, size_t len) { ssize_t n; /* * This may return a short read if the string is shorter than the chunk * and is aligned at the end of the page, and the following page is not * mapped. */ n = proc_readmem(td, p, (vm_offset_t)sptr, buf, len); if (n <= 0) return (ENOMEM); return (0); } #define PROC_AUXV_MAX 256 /* Safety limit on auxv size. */ enum proc_vector_type { PROC_ARG, PROC_ENV, PROC_AUX, }; #ifdef COMPAT_FREEBSD32 static int get_proc_vector32(struct thread *td, struct proc *p, char ***proc_vectorp, size_t *vsizep, enum proc_vector_type type) { struct freebsd32_ps_strings pss; Elf32_Auxinfo aux; vm_offset_t vptr, ptr; uint32_t *proc_vector32; char **proc_vector; size_t vsize, size; int i, error; error = 0; if (proc_readmem(td, p, (vm_offset_t)p->p_sysent->sv_psstrings, &pss, sizeof(pss)) != sizeof(pss)) return (ENOMEM); switch (type) { case PROC_ARG: vptr = (vm_offset_t)PTRIN(pss.ps_argvstr); vsize = pss.ps_nargvstr; if (vsize > ARG_MAX) return (ENOEXEC); size = vsize * sizeof(int32_t); break; case PROC_ENV: vptr = (vm_offset_t)PTRIN(pss.ps_envstr); vsize = pss.ps_nenvstr; if (vsize > ARG_MAX) return (ENOEXEC); size = vsize * sizeof(int32_t); break; case PROC_AUX: vptr = (vm_offset_t)PTRIN(pss.ps_envstr) + (pss.ps_nenvstr + 1) * sizeof(int32_t); if (vptr % 4 != 0) return (ENOEXEC); for (ptr = vptr, i = 0; i < PROC_AUXV_MAX; i++) { if (proc_readmem(td, p, ptr, &aux, sizeof(aux)) != sizeof(aux)) return (ENOMEM); if (aux.a_type == AT_NULL) break; ptr += sizeof(aux); } if (aux.a_type != AT_NULL) return (ENOEXEC); vsize = i + 1; size = vsize * sizeof(aux); break; default: KASSERT(0, ("Wrong proc vector type: %d", type)); return (EINVAL); } proc_vector32 = malloc(size, M_TEMP, M_WAITOK); if (proc_readmem(td, p, vptr, proc_vector32, size) != size) { error = ENOMEM; goto done; } if (type == PROC_AUX) { *proc_vectorp = (char **)proc_vector32; *vsizep = vsize; return (0); } proc_vector = malloc(vsize * sizeof(char *), M_TEMP, M_WAITOK); for (i = 0; i < (int)vsize; i++) proc_vector[i] = PTRIN(proc_vector32[i]); *proc_vectorp = proc_vector; *vsizep = vsize; done: free(proc_vector32, M_TEMP); return (error); } #endif static int get_proc_vector(struct thread *td, struct proc *p, char ***proc_vectorp, size_t *vsizep, enum proc_vector_type type) { struct ps_strings pss; Elf_Auxinfo aux; vm_offset_t vptr, ptr; char **proc_vector; size_t vsize, size; int i; #ifdef COMPAT_FREEBSD32 if (SV_PROC_FLAG(p, SV_ILP32) != 0) return (get_proc_vector32(td, p, proc_vectorp, vsizep, type)); #endif if (proc_readmem(td, p, (vm_offset_t)p->p_sysent->sv_psstrings, &pss, sizeof(pss)) != sizeof(pss)) return (ENOMEM); switch (type) { case PROC_ARG: vptr = (vm_offset_t)pss.ps_argvstr; vsize = pss.ps_nargvstr; if (vsize > ARG_MAX) return (ENOEXEC); size = vsize * sizeof(char *); break; case PROC_ENV: vptr = (vm_offset_t)pss.ps_envstr; vsize = pss.ps_nenvstr; if (vsize > ARG_MAX) return (ENOEXEC); size = vsize * sizeof(char *); break; case PROC_AUX: /* * The aux array is just above env array on the stack. Check * that the address is naturally aligned. */ vptr = (vm_offset_t)pss.ps_envstr + (pss.ps_nenvstr + 1) * sizeof(char *); #if __ELF_WORD_SIZE == 64 if (vptr % sizeof(uint64_t) != 0) #else if (vptr % sizeof(uint32_t) != 0) #endif return (ENOEXEC); /* * We count the array size reading the aux vectors from the * stack until AT_NULL vector is returned. So (to keep the code * simple) we read the process stack twice: the first time here * to find the size and the second time when copying the vectors * to the allocated proc_vector. */ for (ptr = vptr, i = 0; i < PROC_AUXV_MAX; i++) { if (proc_readmem(td, p, ptr, &aux, sizeof(aux)) != sizeof(aux)) return (ENOMEM); if (aux.a_type == AT_NULL) break; ptr += sizeof(aux); } /* * If the PROC_AUXV_MAX entries are iterated over, and we have * not reached AT_NULL, it is most likely we are reading wrong * data: either the process doesn't have auxv array or data has * been modified. Return the error in this case. */ if (aux.a_type != AT_NULL) return (ENOEXEC); vsize = i + 1; size = vsize * sizeof(aux); break; default: KASSERT(0, ("Wrong proc vector type: %d", type)); return (EINVAL); /* In case we are built without INVARIANTS. */ } proc_vector = malloc(size, M_TEMP, M_WAITOK); if (proc_readmem(td, p, vptr, proc_vector, size) != size) { free(proc_vector, M_TEMP); return (ENOMEM); } *proc_vectorp = proc_vector; *vsizep = vsize; return (0); } #define GET_PS_STRINGS_CHUNK_SZ 256 /* Chunk size (bytes) for ps_strings operations. */ static int get_ps_strings(struct thread *td, struct proc *p, struct sbuf *sb, enum proc_vector_type type) { size_t done, len, nchr, vsize; int error, i; char **proc_vector, *sptr; char pss_string[GET_PS_STRINGS_CHUNK_SZ]; PROC_ASSERT_HELD(p); /* * We are not going to read more than 2 * (PATH_MAX + ARG_MAX) bytes. */ nchr = 2 * (PATH_MAX + ARG_MAX); error = get_proc_vector(td, p, &proc_vector, &vsize, type); if (error != 0) return (error); for (done = 0, i = 0; i < (int)vsize && done < nchr; i++) { /* * The program may have scribbled into its argv array, e.g. to * remove some arguments. If that has happened, break out * before trying to read from NULL. */ if (proc_vector[i] == NULL) break; for (sptr = proc_vector[i]; ; sptr += GET_PS_STRINGS_CHUNK_SZ) { error = proc_read_string(td, p, sptr, pss_string, sizeof(pss_string)); if (error != 0) goto done; len = strnlen(pss_string, GET_PS_STRINGS_CHUNK_SZ); if (done + len >= nchr) len = nchr - done - 1; sbuf_bcat(sb, pss_string, len); if (len != GET_PS_STRINGS_CHUNK_SZ) break; done += GET_PS_STRINGS_CHUNK_SZ; } sbuf_bcat(sb, "", 1); done += len + 1; } done: free(proc_vector, M_TEMP); return (error); } int proc_getargv(struct thread *td, struct proc *p, struct sbuf *sb) { return (get_ps_strings(curthread, p, sb, PROC_ARG)); } int proc_getenvv(struct thread *td, struct proc *p, struct sbuf *sb) { return (get_ps_strings(curthread, p, sb, PROC_ENV)); } int proc_getauxv(struct thread *td, struct proc *p, struct sbuf *sb) { size_t vsize, size; char **auxv; int error; error = get_proc_vector(td, p, &auxv, &vsize, PROC_AUX); if (error == 0) { #ifdef COMPAT_FREEBSD32 if (SV_PROC_FLAG(p, SV_ILP32) != 0) size = vsize * sizeof(Elf32_Auxinfo); else #endif size = vsize * sizeof(Elf_Auxinfo); if (sbuf_bcat(sb, auxv, size) != 0) error = ENOMEM; free(auxv, M_TEMP); } return (error); } /* * This sysctl allows a process to retrieve the argument list or process * title for another process without groping around in the address space * of the other process. It also allow a process to set its own "process * title to a string of its own choice. */ static int sysctl_kern_proc_args(SYSCTL_HANDLER_ARGS) { int *name = (int *)arg1; u_int namelen = arg2; struct pargs *newpa, *pa; struct proc *p; struct sbuf sb; int flags, error = 0, error2; if (namelen != 1) return (EINVAL); flags = PGET_CANSEE; if (req->newptr != NULL) flags |= PGET_ISCURRENT; error = pget((pid_t)name[0], flags, &p); if (error) return (error); pa = p->p_args; if (pa != NULL) { pargs_hold(pa); PROC_UNLOCK(p); error = SYSCTL_OUT(req, pa->ar_args, pa->ar_length); pargs_drop(pa); } else if ((p->p_flag & (P_WEXIT | P_SYSTEM)) == 0) { _PHOLD(p); PROC_UNLOCK(p); sbuf_new_for_sysctl(&sb, NULL, GET_PS_STRINGS_CHUNK_SZ, req); sbuf_clear_flags(&sb, SBUF_INCLUDENUL); error = proc_getargv(curthread, p, &sb); error2 = sbuf_finish(&sb); PRELE(p); sbuf_delete(&sb); if (error == 0 && error2 != 0) error = error2; } else { PROC_UNLOCK(p); } if (error != 0 || req->newptr == NULL) return (error); if (req->newlen + sizeof(struct pargs) > ps_arg_cache_limit) return (ENOMEM); newpa = pargs_alloc(req->newlen); error = SYSCTL_IN(req, newpa->ar_args, req->newlen); if (error != 0) { pargs_free(newpa); return (error); } PROC_LOCK(p); pa = p->p_args; p->p_args = newpa; PROC_UNLOCK(p); pargs_drop(pa); return (0); } /* * This sysctl allows a process to retrieve environment of another process. */ static int sysctl_kern_proc_env(SYSCTL_HANDLER_ARGS) { int *name = (int *)arg1; u_int namelen = arg2; struct proc *p; struct sbuf sb; int error, error2; if (namelen != 1) return (EINVAL); error = pget((pid_t)name[0], PGET_WANTREAD, &p); if (error != 0) return (error); if ((p->p_flag & P_SYSTEM) != 0) { PRELE(p); return (0); } sbuf_new_for_sysctl(&sb, NULL, GET_PS_STRINGS_CHUNK_SZ, req); sbuf_clear_flags(&sb, SBUF_INCLUDENUL); error = proc_getenvv(curthread, p, &sb); error2 = sbuf_finish(&sb); PRELE(p); sbuf_delete(&sb); return (error != 0 ? error : error2); } /* * This sysctl allows a process to retrieve ELF auxiliary vector of * another process. */ static int sysctl_kern_proc_auxv(SYSCTL_HANDLER_ARGS) { int *name = (int *)arg1; u_int namelen = arg2; struct proc *p; struct sbuf sb; int error, error2; if (namelen != 1) return (EINVAL); error = pget((pid_t)name[0], PGET_WANTREAD, &p); if (error != 0) return (error); if ((p->p_flag & P_SYSTEM) != 0) { PRELE(p); return (0); } sbuf_new_for_sysctl(&sb, NULL, GET_PS_STRINGS_CHUNK_SZ, req); sbuf_clear_flags(&sb, SBUF_INCLUDENUL); error = proc_getauxv(curthread, p, &sb); error2 = sbuf_finish(&sb); PRELE(p); sbuf_delete(&sb); return (error != 0 ? error : error2); } /* * This sysctl allows a process to retrieve the path of the executable for * itself or another process. */ static int sysctl_kern_proc_pathname(SYSCTL_HANDLER_ARGS) { pid_t *pidp = (pid_t *)arg1; unsigned int arglen = arg2; struct proc *p; struct vnode *vp; char *retbuf, *freebuf; int error; if (arglen != 1) return (EINVAL); if (*pidp == -1) { /* -1 means this process */ p = req->td->td_proc; } else { error = pget(*pidp, PGET_CANSEE, &p); if (error != 0) return (error); } vp = p->p_textvp; if (vp == NULL) { if (*pidp != -1) PROC_UNLOCK(p); return (0); } vref(vp); if (*pidp != -1) PROC_UNLOCK(p); error = vn_fullpath(req->td, vp, &retbuf, &freebuf); vrele(vp); if (error) return (error); error = SYSCTL_OUT(req, retbuf, strlen(retbuf) + 1); free(freebuf, M_TEMP); return (error); } static int sysctl_kern_proc_sv_name(SYSCTL_HANDLER_ARGS) { struct proc *p; char *sv_name; int *name; int namelen; int error; namelen = arg2; if (namelen != 1) return (EINVAL); name = (int *)arg1; error = pget((pid_t)name[0], PGET_CANSEE, &p); if (error != 0) return (error); sv_name = p->p_sysent->sv_name; PROC_UNLOCK(p); return (sysctl_handle_string(oidp, sv_name, 0, req)); } #ifdef KINFO_OVMENTRY_SIZE CTASSERT(sizeof(struct kinfo_ovmentry) == KINFO_OVMENTRY_SIZE); #endif #ifdef COMPAT_FREEBSD7 static int sysctl_kern_proc_ovmmap(SYSCTL_HANDLER_ARGS) { vm_map_entry_t entry, tmp_entry; unsigned int last_timestamp; char *fullpath, *freepath; struct kinfo_ovmentry *kve; struct vattr va; struct ucred *cred; int error, *name; struct vnode *vp; struct proc *p; vm_map_t map; struct vmspace *vm; name = (int *)arg1; error = pget((pid_t)name[0], PGET_WANTREAD, &p); if (error != 0) return (error); vm = vmspace_acquire_ref(p); if (vm == NULL) { PRELE(p); return (ESRCH); } kve = malloc(sizeof(*kve), M_TEMP, M_WAITOK); map = &vm->vm_map; vm_map_lock_read(map); for (entry = map->header.next; entry != &map->header; entry = entry->next) { vm_object_t obj, tobj, lobj; vm_offset_t addr; if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) continue; bzero(kve, sizeof(*kve)); kve->kve_structsize = sizeof(*kve); kve->kve_private_resident = 0; obj = entry->object.vm_object; if (obj != NULL) { VM_OBJECT_RLOCK(obj); if (obj->shadow_count == 1) kve->kve_private_resident = obj->resident_page_count; } kve->kve_resident = 0; addr = entry->start; while (addr < entry->end) { if (pmap_extract(map->pmap, addr)) kve->kve_resident++; addr += PAGE_SIZE; } for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) { if (tobj != obj) VM_OBJECT_RLOCK(tobj); if (lobj != obj) VM_OBJECT_RUNLOCK(lobj); lobj = tobj; } kve->kve_start = (void*)entry->start; kve->kve_end = (void*)entry->end; kve->kve_offset = (off_t)entry->offset; if (entry->protection & VM_PROT_READ) kve->kve_protection |= KVME_PROT_READ; if (entry->protection & VM_PROT_WRITE) kve->kve_protection |= KVME_PROT_WRITE; if (entry->protection & VM_PROT_EXECUTE) kve->kve_protection |= KVME_PROT_EXEC; if (entry->eflags & MAP_ENTRY_COW) kve->kve_flags |= KVME_FLAG_COW; if (entry->eflags & MAP_ENTRY_NEEDS_COPY) kve->kve_flags |= KVME_FLAG_NEEDS_COPY; if (entry->eflags & MAP_ENTRY_NOCOREDUMP) kve->kve_flags |= KVME_FLAG_NOCOREDUMP; last_timestamp = map->timestamp; vm_map_unlock_read(map); kve->kve_fileid = 0; kve->kve_fsid = 0; freepath = NULL; fullpath = ""; if (lobj) { vp = NULL; switch (lobj->type) { case OBJT_DEFAULT: kve->kve_type = KVME_TYPE_DEFAULT; break; case OBJT_VNODE: kve->kve_type = KVME_TYPE_VNODE; vp = lobj->handle; vref(vp); break; case OBJT_SWAP: if ((lobj->flags & OBJ_TMPFS_NODE) != 0) { kve->kve_type = KVME_TYPE_VNODE; if ((lobj->flags & OBJ_TMPFS) != 0) { vp = lobj->un_pager.swp.swp_tmpfs; vref(vp); } } else { kve->kve_type = KVME_TYPE_SWAP; } break; case OBJT_DEVICE: kve->kve_type = KVME_TYPE_DEVICE; break; case OBJT_PHYS: kve->kve_type = KVME_TYPE_PHYS; break; case OBJT_DEAD: kve->kve_type = KVME_TYPE_DEAD; break; case OBJT_SG: kve->kve_type = KVME_TYPE_SG; break; default: kve->kve_type = KVME_TYPE_UNKNOWN; break; } if (lobj != obj) VM_OBJECT_RUNLOCK(lobj); kve->kve_ref_count = obj->ref_count; kve->kve_shadow_count = obj->shadow_count; VM_OBJECT_RUNLOCK(obj); if (vp != NULL) { vn_fullpath(curthread, vp, &fullpath, &freepath); cred = curthread->td_ucred; vn_lock(vp, LK_SHARED | LK_RETRY); if (VOP_GETATTR(vp, &va, cred) == 0) { kve->kve_fileid = va.va_fileid; kve->kve_fsid = va.va_fsid; } vput(vp); } } else { kve->kve_type = KVME_TYPE_NONE; kve->kve_ref_count = 0; kve->kve_shadow_count = 0; } strlcpy(kve->kve_path, fullpath, sizeof(kve->kve_path)); if (freepath != NULL) free(freepath, M_TEMP); error = SYSCTL_OUT(req, kve, sizeof(*kve)); vm_map_lock_read(map); if (error) break; if (last_timestamp != map->timestamp) { vm_map_lookup_entry(map, addr - 1, &tmp_entry); entry = tmp_entry; } } vm_map_unlock_read(map); vmspace_free(vm); PRELE(p); free(kve, M_TEMP); return (error); } #endif /* COMPAT_FREEBSD7 */ #ifdef KINFO_VMENTRY_SIZE CTASSERT(sizeof(struct kinfo_vmentry) == KINFO_VMENTRY_SIZE); #endif static void kern_proc_vmmap_resident(vm_map_t map, vm_map_entry_t entry, struct kinfo_vmentry *kve) { vm_object_t obj, tobj; vm_page_t m, m_adv; vm_offset_t addr; vm_paddr_t locked_pa; vm_pindex_t pi, pi_adv, pindex; locked_pa = 0; obj = entry->object.vm_object; addr = entry->start; m_adv = NULL; pi = OFF_TO_IDX(entry->offset); for (; addr < entry->end; addr += IDX_TO_OFF(pi_adv), pi += pi_adv) { if (m_adv != NULL) { m = m_adv; } else { pi_adv = OFF_TO_IDX(entry->end - addr); pindex = pi; for (tobj = obj;; tobj = tobj->backing_object) { m = vm_page_find_least(tobj, pindex); if (m != NULL) { if (m->pindex == pindex) break; if (pi_adv > m->pindex - pindex) { pi_adv = m->pindex - pindex; m_adv = m; } } if (tobj->backing_object == NULL) goto next; pindex += OFF_TO_IDX(tobj-> backing_object_offset); } } m_adv = NULL; if (m->psind != 0 && addr + pagesizes[1] <= entry->end && (addr & (pagesizes[1] - 1)) == 0 && (pmap_mincore(map->pmap, addr, &locked_pa) & MINCORE_SUPER) != 0) { kve->kve_flags |= KVME_FLAG_SUPER; pi_adv = OFF_TO_IDX(pagesizes[1]); } else { /* * We do not test the found page on validity. * Either the page is busy and being paged in, * or it was invalidated. The first case * should be counted as resident, the second * is not so clear; we do account both. */ pi_adv = 1; } kve->kve_resident += pi_adv; next:; } PA_UNLOCK_COND(locked_pa); } /* * Must be called with the process locked and will return unlocked. */ int kern_proc_vmmap_out(struct proc *p, struct sbuf *sb, ssize_t maxlen, int flags) { vm_map_entry_t entry, tmp_entry; struct vattr va; vm_map_t map; vm_object_t obj, tobj, lobj; char *fullpath, *freepath; struct kinfo_vmentry *kve; struct ucred *cred; struct vnode *vp; struct vmspace *vm; vm_offset_t addr; unsigned int last_timestamp; int error; PROC_LOCK_ASSERT(p, MA_OWNED); _PHOLD(p); PROC_UNLOCK(p); vm = vmspace_acquire_ref(p); if (vm == NULL) { PRELE(p); return (ESRCH); } kve = malloc(sizeof(*kve), M_TEMP, M_WAITOK | M_ZERO); error = 0; map = &vm->vm_map; vm_map_lock_read(map); for (entry = map->header.next; entry != &map->header; entry = entry->next) { if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) continue; addr = entry->end; bzero(kve, sizeof(*kve)); obj = entry->object.vm_object; if (obj != NULL) { for (tobj = obj; tobj != NULL; tobj = tobj->backing_object) { VM_OBJECT_RLOCK(tobj); lobj = tobj; } if (obj->backing_object == NULL) kve->kve_private_resident = obj->resident_page_count; if (!vmmap_skip_res_cnt) kern_proc_vmmap_resident(map, entry, kve); for (tobj = obj; tobj != NULL; tobj = tobj->backing_object) { if (tobj != obj && tobj != lobj) VM_OBJECT_RUNLOCK(tobj); } } else { lobj = NULL; } kve->kve_start = entry->start; kve->kve_end = entry->end; kve->kve_offset = entry->offset; if (entry->protection & VM_PROT_READ) kve->kve_protection |= KVME_PROT_READ; if (entry->protection & VM_PROT_WRITE) kve->kve_protection |= KVME_PROT_WRITE; if (entry->protection & VM_PROT_EXECUTE) kve->kve_protection |= KVME_PROT_EXEC; if (entry->eflags & MAP_ENTRY_COW) kve->kve_flags |= KVME_FLAG_COW; if (entry->eflags & MAP_ENTRY_NEEDS_COPY) kve->kve_flags |= KVME_FLAG_NEEDS_COPY; if (entry->eflags & MAP_ENTRY_NOCOREDUMP) kve->kve_flags |= KVME_FLAG_NOCOREDUMP; if (entry->eflags & MAP_ENTRY_GROWS_UP) kve->kve_flags |= KVME_FLAG_GROWS_UP; if (entry->eflags & MAP_ENTRY_GROWS_DOWN) kve->kve_flags |= KVME_FLAG_GROWS_DOWN; last_timestamp = map->timestamp; vm_map_unlock_read(map); freepath = NULL; fullpath = ""; if (lobj != NULL) { vp = NULL; switch (lobj->type) { case OBJT_DEFAULT: kve->kve_type = KVME_TYPE_DEFAULT; break; case OBJT_VNODE: kve->kve_type = KVME_TYPE_VNODE; vp = lobj->handle; vref(vp); break; case OBJT_SWAP: if ((lobj->flags & OBJ_TMPFS_NODE) != 0) { kve->kve_type = KVME_TYPE_VNODE; if ((lobj->flags & OBJ_TMPFS) != 0) { vp = lobj->un_pager.swp.swp_tmpfs; vref(vp); } } else { kve->kve_type = KVME_TYPE_SWAP; } break; case OBJT_DEVICE: kve->kve_type = KVME_TYPE_DEVICE; break; case OBJT_PHYS: kve->kve_type = KVME_TYPE_PHYS; break; case OBJT_DEAD: kve->kve_type = KVME_TYPE_DEAD; break; case OBJT_SG: kve->kve_type = KVME_TYPE_SG; break; case OBJT_MGTDEVICE: kve->kve_type = KVME_TYPE_MGTDEVICE; break; default: kve->kve_type = KVME_TYPE_UNKNOWN; break; } if (lobj != obj) VM_OBJECT_RUNLOCK(lobj); kve->kve_ref_count = obj->ref_count; kve->kve_shadow_count = obj->shadow_count; VM_OBJECT_RUNLOCK(obj); if (vp != NULL) { vn_fullpath(curthread, vp, &fullpath, &freepath); kve->kve_vn_type = vntype_to_kinfo(vp->v_type); cred = curthread->td_ucred; vn_lock(vp, LK_SHARED | LK_RETRY); if (VOP_GETATTR(vp, &va, cred) == 0) { kve->kve_vn_fileid = va.va_fileid; kve->kve_vn_fsid = va.va_fsid; kve->kve_vn_mode = MAKEIMODE(va.va_type, va.va_mode); kve->kve_vn_size = va.va_size; kve->kve_vn_rdev = va.va_rdev; kve->kve_status = KF_ATTR_VALID; } vput(vp); } } else { kve->kve_type = KVME_TYPE_NONE; kve->kve_ref_count = 0; kve->kve_shadow_count = 0; } strlcpy(kve->kve_path, fullpath, sizeof(kve->kve_path)); if (freepath != NULL) free(freepath, M_TEMP); /* Pack record size down */ if ((flags & KERN_VMMAP_PACK_KINFO) != 0) kve->kve_structsize = offsetof(struct kinfo_vmentry, kve_path) + strlen(kve->kve_path) + 1; else kve->kve_structsize = sizeof(*kve); kve->kve_structsize = roundup(kve->kve_structsize, sizeof(uint64_t)); /* Halt filling and truncate rather than exceeding maxlen */ if (maxlen != -1 && maxlen < kve->kve_structsize) { error = 0; vm_map_lock_read(map); break; } else if (maxlen != -1) maxlen -= kve->kve_structsize; if (sbuf_bcat(sb, kve, kve->kve_structsize) != 0) error = ENOMEM; vm_map_lock_read(map); if (error != 0) break; if (last_timestamp != map->timestamp) { vm_map_lookup_entry(map, addr - 1, &tmp_entry); entry = tmp_entry; } } vm_map_unlock_read(map); vmspace_free(vm); PRELE(p); free(kve, M_TEMP); return (error); } static int sysctl_kern_proc_vmmap(SYSCTL_HANDLER_ARGS) { struct proc *p; struct sbuf sb; int error, error2, *name; name = (int *)arg1; sbuf_new_for_sysctl(&sb, NULL, sizeof(struct kinfo_vmentry), req); sbuf_clear_flags(&sb, SBUF_INCLUDENUL); error = pget((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p); if (error != 0) { sbuf_delete(&sb); return (error); } error = kern_proc_vmmap_out(p, &sb, -1, KERN_VMMAP_PACK_KINFO); error2 = sbuf_finish(&sb); sbuf_delete(&sb); return (error != 0 ? error : error2); } #if defined(STACK) || defined(DDB) static int sysctl_kern_proc_kstack(SYSCTL_HANDLER_ARGS) { struct kinfo_kstack *kkstp; int error, i, *name, numthreads; lwpid_t *lwpidarray; struct thread *td; struct stack *st; struct sbuf sb; struct proc *p; name = (int *)arg1; error = pget((pid_t)name[0], PGET_NOTINEXEC | PGET_WANTREAD, &p); if (error != 0) return (error); kkstp = malloc(sizeof(*kkstp), M_TEMP, M_WAITOK); st = stack_create(); lwpidarray = NULL; numthreads = 0; PROC_LOCK(p); repeat: if (numthreads < p->p_numthreads) { if (lwpidarray != NULL) { free(lwpidarray, M_TEMP); lwpidarray = NULL; } numthreads = p->p_numthreads; PROC_UNLOCK(p); lwpidarray = malloc(sizeof(*lwpidarray) * numthreads, M_TEMP, M_WAITOK | M_ZERO); PROC_LOCK(p); goto repeat; } i = 0; /* * XXXRW: During the below loop, execve(2) and countless other sorts * of changes could have taken place. Should we check to see if the * vmspace has been replaced, or the like, in order to prevent * giving a snapshot that spans, say, execve(2), with some threads * before and some after? Among other things, the credentials could * have changed, in which case the right to extract debug info might * no longer be assured. */ FOREACH_THREAD_IN_PROC(p, td) { KASSERT(i < numthreads, ("sysctl_kern_proc_kstack: numthreads")); lwpidarray[i] = td->td_tid; i++; } numthreads = i; for (i = 0; i < numthreads; i++) { td = thread_find(p, lwpidarray[i]); if (td == NULL) { continue; } bzero(kkstp, sizeof(*kkstp)); (void)sbuf_new(&sb, kkstp->kkst_trace, sizeof(kkstp->kkst_trace), SBUF_FIXEDLEN); thread_lock(td); kkstp->kkst_tid = td->td_tid; if (TD_IS_SWAPPED(td)) { kkstp->kkst_state = KKST_STATE_SWAPPED; } else if (TD_IS_RUNNING(td)) { if (stack_save_td_running(st, td) == 0) kkstp->kkst_state = KKST_STATE_STACKOK; else kkstp->kkst_state = KKST_STATE_RUNNING; } else { kkstp->kkst_state = KKST_STATE_STACKOK; stack_save_td(st, td); } thread_unlock(td); PROC_UNLOCK(p); stack_sbuf_print(&sb, st); sbuf_finish(&sb); sbuf_delete(&sb); error = SYSCTL_OUT(req, kkstp, sizeof(*kkstp)); PROC_LOCK(p); if (error) break; } _PRELE(p); PROC_UNLOCK(p); if (lwpidarray != NULL) free(lwpidarray, M_TEMP); stack_destroy(st); free(kkstp, M_TEMP); return (error); } #endif /* * This sysctl allows a process to retrieve the full list of groups from * itself or another process. */ static int sysctl_kern_proc_groups(SYSCTL_HANDLER_ARGS) { pid_t *pidp = (pid_t *)arg1; unsigned int arglen = arg2; struct proc *p; struct ucred *cred; int error; if (arglen != 1) return (EINVAL); if (*pidp == -1) { /* -1 means this process */ p = req->td->td_proc; PROC_LOCK(p); } else { error = pget(*pidp, PGET_CANSEE, &p); if (error != 0) return (error); } cred = crhold(p->p_ucred); PROC_UNLOCK(p); error = SYSCTL_OUT(req, cred->cr_groups, cred->cr_ngroups * sizeof(gid_t)); crfree(cred); return (error); } /* * This sysctl allows a process to retrieve or/and set the resource limit for * another process. */ static int sysctl_kern_proc_rlimit(SYSCTL_HANDLER_ARGS) { int *name = (int *)arg1; u_int namelen = arg2; struct rlimit rlim; struct proc *p; u_int which; int flags, error; if (namelen != 2) return (EINVAL); which = (u_int)name[1]; if (which >= RLIM_NLIMITS) return (EINVAL); if (req->newptr != NULL && req->newlen != sizeof(rlim)) return (EINVAL); flags = PGET_HOLD | PGET_NOTWEXIT; if (req->newptr != NULL) flags |= PGET_CANDEBUG; else flags |= PGET_CANSEE; error = pget((pid_t)name[0], flags, &p); if (error != 0) return (error); /* * Retrieve limit. */ if (req->oldptr != NULL) { PROC_LOCK(p); lim_rlimit_proc(p, which, &rlim); PROC_UNLOCK(p); } error = SYSCTL_OUT(req, &rlim, sizeof(rlim)); if (error != 0) goto errout; /* * Set limit. */ if (req->newptr != NULL) { error = SYSCTL_IN(req, &rlim, sizeof(rlim)); if (error == 0) error = kern_proc_setrlimit(curthread, p, which, &rlim); } errout: PRELE(p); return (error); } /* * This sysctl allows a process to retrieve ps_strings structure location of * another process. */ static int sysctl_kern_proc_ps_strings(SYSCTL_HANDLER_ARGS) { int *name = (int *)arg1; u_int namelen = arg2; struct proc *p; vm_offset_t ps_strings; int error; #ifdef COMPAT_FREEBSD32 uint32_t ps_strings32; #endif if (namelen != 1) return (EINVAL); error = pget((pid_t)name[0], PGET_CANDEBUG, &p); if (error != 0) return (error); #ifdef COMPAT_FREEBSD32 if ((req->flags & SCTL_MASK32) != 0) { /* * We return 0 if the 32 bit emulation request is for a 64 bit * process. */ ps_strings32 = SV_PROC_FLAG(p, SV_ILP32) != 0 ? PTROUT(p->p_sysent->sv_psstrings) : 0; PROC_UNLOCK(p); error = SYSCTL_OUT(req, &ps_strings32, sizeof(ps_strings32)); return (error); } #endif ps_strings = p->p_sysent->sv_psstrings; PROC_UNLOCK(p); error = SYSCTL_OUT(req, &ps_strings, sizeof(ps_strings)); return (error); } /* * This sysctl allows a process to retrieve umask of another process. */ static int sysctl_kern_proc_umask(SYSCTL_HANDLER_ARGS) { int *name = (int *)arg1; u_int namelen = arg2; struct proc *p; int error; u_short fd_cmask; if (namelen != 1) return (EINVAL); error = pget((pid_t)name[0], PGET_WANTREAD, &p); if (error != 0) return (error); FILEDESC_SLOCK(p->p_fd); fd_cmask = p->p_fd->fd_cmask; FILEDESC_SUNLOCK(p->p_fd); PRELE(p); error = SYSCTL_OUT(req, &fd_cmask, sizeof(fd_cmask)); return (error); } /* * This sysctl allows a process to set and retrieve binary osreldate of * another process. */ static int sysctl_kern_proc_osrel(SYSCTL_HANDLER_ARGS) { int *name = (int *)arg1; u_int namelen = arg2; struct proc *p; int flags, error, osrel; if (namelen != 1) return (EINVAL); if (req->newptr != NULL && req->newlen != sizeof(osrel)) return (EINVAL); flags = PGET_HOLD | PGET_NOTWEXIT; if (req->newptr != NULL) flags |= PGET_CANDEBUG; else flags |= PGET_CANSEE; error = pget((pid_t)name[0], flags, &p); if (error != 0) return (error); error = SYSCTL_OUT(req, &p->p_osrel, sizeof(p->p_osrel)); if (error != 0) goto errout; if (req->newptr != NULL) { error = SYSCTL_IN(req, &osrel, sizeof(osrel)); if (error != 0) goto errout; if (osrel < 0) { error = EINVAL; goto errout; } p->p_osrel = osrel; } errout: PRELE(p); return (error); } static int sysctl_kern_proc_sigtramp(SYSCTL_HANDLER_ARGS) { int *name = (int *)arg1; u_int namelen = arg2; struct proc *p; struct kinfo_sigtramp kst; const struct sysentvec *sv; int error; #ifdef COMPAT_FREEBSD32 struct kinfo_sigtramp32 kst32; #endif if (namelen != 1) return (EINVAL); error = pget((pid_t)name[0], PGET_CANDEBUG, &p); if (error != 0) return (error); sv = p->p_sysent; #ifdef COMPAT_FREEBSD32 if ((req->flags & SCTL_MASK32) != 0) { bzero(&kst32, sizeof(kst32)); if (SV_PROC_FLAG(p, SV_ILP32)) { if (sv->sv_sigcode_base != 0) { kst32.ksigtramp_start = sv->sv_sigcode_base; kst32.ksigtramp_end = sv->sv_sigcode_base + *sv->sv_szsigcode; } else { kst32.ksigtramp_start = sv->sv_psstrings - *sv->sv_szsigcode; kst32.ksigtramp_end = sv->sv_psstrings; } } PROC_UNLOCK(p); error = SYSCTL_OUT(req, &kst32, sizeof(kst32)); return (error); } #endif bzero(&kst, sizeof(kst)); if (sv->sv_sigcode_base != 0) { kst.ksigtramp_start = (char *)sv->sv_sigcode_base; kst.ksigtramp_end = (char *)sv->sv_sigcode_base + *sv->sv_szsigcode; } else { kst.ksigtramp_start = (char *)sv->sv_psstrings - *sv->sv_szsigcode; kst.ksigtramp_end = (char *)sv->sv_psstrings; } PROC_UNLOCK(p); error = SYSCTL_OUT(req, &kst, sizeof(kst)); return (error); } SYSCTL_NODE(_kern, KERN_PROC, proc, CTLFLAG_RD, 0, "Process table"); SYSCTL_PROC(_kern_proc, KERN_PROC_ALL, all, CTLFLAG_RD|CTLTYPE_STRUCT| CTLFLAG_MPSAFE, 0, 0, sysctl_kern_proc, "S,proc", "Return entire process table"); static SYSCTL_NODE(_kern_proc, KERN_PROC_GID, gid, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Process table"); static SYSCTL_NODE(_kern_proc, KERN_PROC_PGRP, pgrp, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Process table"); static SYSCTL_NODE(_kern_proc, KERN_PROC_RGID, rgid, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Process table"); static SYSCTL_NODE(_kern_proc, KERN_PROC_SESSION, sid, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Process table"); static SYSCTL_NODE(_kern_proc, KERN_PROC_TTY, tty, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Process table"); static SYSCTL_NODE(_kern_proc, KERN_PROC_UID, uid, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Process table"); static SYSCTL_NODE(_kern_proc, KERN_PROC_RUID, ruid, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Process table"); static SYSCTL_NODE(_kern_proc, KERN_PROC_PID, pid, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Process table"); static SYSCTL_NODE(_kern_proc, KERN_PROC_PROC, proc, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Return process table, no threads"); static SYSCTL_NODE(_kern_proc, KERN_PROC_ARGS, args, CTLFLAG_RW | CTLFLAG_CAPWR | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, sysctl_kern_proc_args, "Process argument list"); static SYSCTL_NODE(_kern_proc, KERN_PROC_ENV, env, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc_env, "Process environment"); static SYSCTL_NODE(_kern_proc, KERN_PROC_AUXV, auxv, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc_auxv, "Process ELF auxiliary vector"); static SYSCTL_NODE(_kern_proc, KERN_PROC_PATHNAME, pathname, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc_pathname, "Process executable path"); static SYSCTL_NODE(_kern_proc, KERN_PROC_SV_NAME, sv_name, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc_sv_name, "Process syscall vector name (ABI type)"); static SYSCTL_NODE(_kern_proc, (KERN_PROC_GID | KERN_PROC_INC_THREAD), gid_td, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Process table"); static SYSCTL_NODE(_kern_proc, (KERN_PROC_PGRP | KERN_PROC_INC_THREAD), pgrp_td, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Process table"); static SYSCTL_NODE(_kern_proc, (KERN_PROC_RGID | KERN_PROC_INC_THREAD), rgid_td, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Process table"); static SYSCTL_NODE(_kern_proc, (KERN_PROC_SESSION | KERN_PROC_INC_THREAD), sid_td, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Process table"); static SYSCTL_NODE(_kern_proc, (KERN_PROC_TTY | KERN_PROC_INC_THREAD), tty_td, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Process table"); static SYSCTL_NODE(_kern_proc, (KERN_PROC_UID | KERN_PROC_INC_THREAD), uid_td, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Process table"); static SYSCTL_NODE(_kern_proc, (KERN_PROC_RUID | KERN_PROC_INC_THREAD), ruid_td, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Process table"); static SYSCTL_NODE(_kern_proc, (KERN_PROC_PID | KERN_PROC_INC_THREAD), pid_td, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Process table"); static SYSCTL_NODE(_kern_proc, (KERN_PROC_PROC | KERN_PROC_INC_THREAD), proc_td, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc, "Return process table, no threads"); #ifdef COMPAT_FREEBSD7 static SYSCTL_NODE(_kern_proc, KERN_PROC_OVMMAP, ovmmap, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc_ovmmap, "Old Process vm map entries"); #endif static SYSCTL_NODE(_kern_proc, KERN_PROC_VMMAP, vmmap, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc_vmmap, "Process vm map entries"); #if defined(STACK) || defined(DDB) static SYSCTL_NODE(_kern_proc, KERN_PROC_KSTACK, kstack, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc_kstack, "Process kernel stacks"); #endif static SYSCTL_NODE(_kern_proc, KERN_PROC_GROUPS, groups, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc_groups, "Process groups"); static SYSCTL_NODE(_kern_proc, KERN_PROC_RLIMIT, rlimit, CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, sysctl_kern_proc_rlimit, "Process resource limits"); static SYSCTL_NODE(_kern_proc, KERN_PROC_PS_STRINGS, ps_strings, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc_ps_strings, "Process ps_strings location"); static SYSCTL_NODE(_kern_proc, KERN_PROC_UMASK, umask, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc_umask, "Process umask"); static SYSCTL_NODE(_kern_proc, KERN_PROC_OSREL, osrel, CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, sysctl_kern_proc_osrel, "Process binary osreldate"); static SYSCTL_NODE(_kern_proc, KERN_PROC_SIGTRAMP, sigtramp, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc_sigtramp, "Process signal trampoline location"); int allproc_gen; void stop_all_proc(void) { struct proc *cp, *p; int r, gen; bool restart, seen_stopped, seen_exiting, stopped_some; cp = curproc; /* * stop_all_proc() assumes that all process which have * usermode must be stopped, except current process, for * obvious reasons. Since other threads in the process * establishing global stop could unstop something, disable * calls from multithreaded processes as precaution. The * service must not be user-callable anyway. */ KASSERT((cp->p_flag & P_HADTHREADS) == 0 || (cp->p_flag & P_KTHREAD) != 0, ("mt stop_all_proc")); allproc_loop: sx_xlock(&allproc_lock); gen = allproc_gen; seen_exiting = seen_stopped = stopped_some = restart = false; LIST_REMOVE(cp, p_list); LIST_INSERT_HEAD(&allproc, cp, p_list); for (;;) { p = LIST_NEXT(cp, p_list); if (p == NULL) break; LIST_REMOVE(cp, p_list); LIST_INSERT_AFTER(p, cp, p_list); PROC_LOCK(p); if ((p->p_flag & (P_KTHREAD | P_SYSTEM | P_TOTAL_STOP)) != 0) { PROC_UNLOCK(p); continue; } if ((p->p_flag & P_WEXIT) != 0) { seen_exiting = true; PROC_UNLOCK(p); continue; } if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) { /* * Stopped processes are tolerated when there * are no other processes which might continue * them. P_STOPPED_SINGLE but not * P_TOTAL_STOP process still has at least one * thread running. */ seen_stopped = true; PROC_UNLOCK(p); continue; } _PHOLD(p); sx_xunlock(&allproc_lock); r = thread_single(p, SINGLE_ALLPROC); if (r != 0) restart = true; else stopped_some = true; _PRELE(p); PROC_UNLOCK(p); sx_xlock(&allproc_lock); } /* Catch forked children we did not see in iteration. */ if (gen != allproc_gen) restart = true; sx_xunlock(&allproc_lock); if (restart || stopped_some || seen_exiting || seen_stopped) { kern_yield(PRI_USER); goto allproc_loop; } } void resume_all_proc(void) { struct proc *cp, *p; cp = curproc; sx_xlock(&allproc_lock); LIST_REMOVE(cp, p_list); LIST_INSERT_HEAD(&allproc, cp, p_list); for (;;) { p = LIST_NEXT(cp, p_list); if (p == NULL) break; LIST_REMOVE(cp, p_list); LIST_INSERT_AFTER(p, cp, p_list); PROC_LOCK(p); if ((p->p_flag & P_TOTAL_STOP) != 0) { sx_xunlock(&allproc_lock); _PHOLD(p); thread_single_end(p, SINGLE_ALLPROC); _PRELE(p); PROC_UNLOCK(p); sx_xlock(&allproc_lock); } else { PROC_UNLOCK(p); } } sx_xunlock(&allproc_lock); } #define TOTAL_STOP_DEBUG 1 #ifdef TOTAL_STOP_DEBUG volatile static int ap_resume; #include static int sysctl_debug_stop_all_proc(SYSCTL_HANDLER_ARGS) { int error, val; val = 0; ap_resume = 0; error = sysctl_handle_int(oidp, &val, 0, req); if (error != 0 || req->newptr == NULL) return (error); if (val != 0) { stop_all_proc(); syncer_suspend(); while (ap_resume == 0) ; syncer_resume(); resume_all_proc(); } return (0); } SYSCTL_PROC(_debug, OID_AUTO, stop_all_proc, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, __DEVOLATILE(int *, &ap_resume), 0, sysctl_debug_stop_all_proc, "I", ""); #endif Index: user/alc/PQ_LAUNDRY/sys/kern/pic_if.m =================================================================== --- user/alc/PQ_LAUNDRY/sys/kern/pic_if.m (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/kern/pic_if.m (revision 292449) @@ -0,0 +1,124 @@ +#- +# Copyright (c) 2012 Jakub Wojciech Klama +# Copyright (c) 2015 Svatopluk Kraus +# Copyright (c) 2015 Michal Meloun +# 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 AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +#include +#include +#include +#include + +INTERFACE pic; + +CODE { + static int null_pic_bind(device_t dev, struct intr_irqsrc *isrc) + { + return (EOPNOTSUPP); + } + + static void null_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc) + { + return; + } + + static void null_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc) + { + return; + } + + static void null_pic_init_secondary(device_t dev) + { + return; + } + + static void null_pic_ipi_send(device_t dev, cpuset_t cpus, u_int ipi) + { + return; + } +}; + +METHOD int register { + device_t dev; + struct intr_irqsrc *isrc; + boolean_t *is_percpu; +}; + +METHOD int unregister { + device_t dev; + struct intr_irqsrc *isrc; +}; + +METHOD void disable_intr { + device_t dev; + struct intr_irqsrc *isrc; +} DEFAULT null_pic_disable_intr; + +METHOD void disable_source { + device_t dev; + struct intr_irqsrc *isrc; +}; + +METHOD void enable_source { + device_t dev; + struct intr_irqsrc *isrc; +}; + +METHOD void enable_intr { + device_t dev; + struct intr_irqsrc *isrc; +} DEFAULT null_pic_enable_intr; + +METHOD void pre_ithread { + device_t dev; + struct intr_irqsrc *isrc; +}; + +METHOD void post_ithread { + device_t dev; + struct intr_irqsrc *isrc; +}; + +METHOD void post_filter { + device_t dev; + struct intr_irqsrc *isrc; +}; + +METHOD int bind { + device_t dev; + struct intr_irqsrc *isrc; +} DEFAULT null_pic_bind; + +METHOD void init_secondary { + device_t dev; +} DEFAULT null_pic_init_secondary; + +METHOD void ipi_send { + device_t dev; + struct intr_irqsrc *isrc; + cpuset_t cpus; +} DEFAULT null_pic_ipi_send; Property changes on: user/alc/PQ_LAUNDRY/sys/kern/pic_if.m ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/kern/subr_intr.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/kern/subr_intr.c (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/kern/subr_intr.c (revision 292449) @@ -0,0 +1,1395 @@ +/*- + * Copyright (c) 2012-2014 Jakub Wojciech Klama . + * Copyright (c) 2015 Svatopluk Kraus + * Copyright (c) 2015 Michal Meloun + * 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 AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * New-style Interrupt Framework + * + * TODO: - to support IPI (PPI) enabling on other CPUs if already started + * - to complete things for removable PICs + */ + +#include "opt_ddb.h" +#include "opt_platform.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#ifdef DDB +#include +#endif + +#include "pic_if.h" + +#define INTRNAME_LEN (2*MAXCOMLEN + 1) + +#ifdef DEBUG +#define debugf(fmt, args...) do { printf("%s(): ", __func__); \ + printf(fmt,##args); } while (0) +#else +#define debugf(fmt, args...) +#endif + +MALLOC_DECLARE(M_INTRNG); +MALLOC_DEFINE(M_INTRNG, "intr", "intr interrupt handling"); + +/* Main interrupt handler called from assembler -> 'hidden' for C code. */ +void intr_irq_handler(struct trapframe *tf); + +/* Root interrupt controller stuff. */ +static struct intr_irqsrc *irq_root_isrc; +static device_t irq_root_dev; +static intr_irq_filter_t *irq_root_filter; +static void *irq_root_arg; +static u_int irq_root_ipicount; + +/* Interrupt controller definition. */ +struct intr_pic { + SLIST_ENTRY(intr_pic) pic_next; + intptr_t pic_xref; /* hardware identification */ + device_t pic_dev; +}; + +static struct mtx pic_list_lock; +static SLIST_HEAD(, intr_pic) pic_list; + +static struct intr_pic *pic_lookup(device_t dev, intptr_t xref); + +/* Interrupt source definition. */ +static struct mtx isrc_table_lock; +static struct intr_irqsrc *irq_sources[NIRQ]; +u_int irq_next_free; + +#define IRQ_INVALID nitems(irq_sources) + +#ifdef SMP +static boolean_t irq_assign_cpu = FALSE; + +static struct intr_irqsrc ipi_sources[INTR_IPI_COUNT]; +static u_int ipi_next_num; +#endif + +/* + * - 2 counters for each I/O interrupt. + * - MAXCPU counters for each IPI counters for SMP. + */ +#ifdef SMP +#define INTRCNT_COUNT (NIRQ * 2 + INTR_IPI_COUNT * MAXCPU) +#else +#define INTRCNT_COUNT (NIRQ * 2) +#endif + +/* Data for MI statistics reporting. */ +u_long intrcnt[INTRCNT_COUNT]; +char intrnames[INTRCNT_COUNT * INTRNAME_LEN]; +size_t sintrcnt = sizeof(intrcnt); +size_t sintrnames = sizeof(intrnames); +static u_int intrcnt_index; + +/* + * Interrupt framework initialization routine. + */ +static void +intr_irq_init(void *dummy __unused) +{ + + SLIST_INIT(&pic_list); + mtx_init(&pic_list_lock, "intr pic list", NULL, MTX_DEF); + mtx_init(&isrc_table_lock, "intr isrc table", NULL, MTX_DEF); +} +SYSINIT(intr_irq_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_irq_init, NULL); + +static void +intrcnt_setname(const char *name, int index) +{ + + snprintf(intrnames + INTRNAME_LEN * index, INTRNAME_LEN, "%-*s", + INTRNAME_LEN - 1, name); +} + +/* + * Update name for interrupt source with interrupt event. + */ +static void +intrcnt_updatename(struct intr_irqsrc *isrc) +{ + + /* QQQ: What about stray counter name? */ + mtx_assert(&isrc_table_lock, MA_OWNED); + intrcnt_setname(isrc->isrc_event->ie_fullname, isrc->isrc_index); +} + +/* + * Virtualization for interrupt source interrupt counter increment. + */ +static inline void +isrc_increment_count(struct intr_irqsrc *isrc) +{ + + /* + * XXX - It should be atomic for PPI interrupts. It was proven that + * the lost is measurable easily for timer PPI interrupts. + */ + isrc->isrc_count[0]++; + /*atomic_add_long(&isrc->isrc_count[0], 1);*/ +} + +/* + * Virtualization for interrupt source interrupt stray counter increment. + */ +static inline void +isrc_increment_straycount(struct intr_irqsrc *isrc) +{ + + isrc->isrc_count[1]++; +} + +/* + * Virtualization for interrupt source interrupt name update. + */ +static void +isrc_update_name(struct intr_irqsrc *isrc, const char *name) +{ + char str[INTRNAME_LEN]; + + mtx_assert(&isrc_table_lock, MA_OWNED); + + if (name != NULL) { + snprintf(str, INTRNAME_LEN, "%s: %s", isrc->isrc_name, name); + intrcnt_setname(str, isrc->isrc_index); + snprintf(str, INTRNAME_LEN, "stray %s: %s", isrc->isrc_name, + name); + intrcnt_setname(str, isrc->isrc_index + 1); + } else { + snprintf(str, INTRNAME_LEN, "%s:", isrc->isrc_name); + intrcnt_setname(str, isrc->isrc_index); + snprintf(str, INTRNAME_LEN, "stray %s:", isrc->isrc_name); + intrcnt_setname(str, isrc->isrc_index + 1); + } +} + +/* + * Virtualization for interrupt source interrupt counters setup. + */ +static void +isrc_setup_counters(struct intr_irqsrc *isrc) +{ + u_int index; + + /* + * XXX - it does not work well with removable controllers and + * interrupt sources !!! + */ + index = atomic_fetchadd_int(&intrcnt_index, 2); + isrc->isrc_index = index; + isrc->isrc_count = &intrcnt[index]; + isrc_update_name(isrc, NULL); +} + +#ifdef SMP +/* + * Virtualization for interrupt source IPI counter increment. + */ +static inline void +isrc_increment_ipi_count(struct intr_irqsrc *isrc, u_int cpu) +{ + + isrc->isrc_count[cpu]++; +} + +/* + * Virtualization for interrupt source IPI counters setup. + */ +static void +isrc_setup_ipi_counters(struct intr_irqsrc *isrc, const char *name) +{ + u_int index, i; + char str[INTRNAME_LEN]; + + index = atomic_fetchadd_int(&intrcnt_index, MAXCPU); + isrc->isrc_index = index; + isrc->isrc_count = &intrcnt[index]; + + for (i = 0; i < MAXCPU; i++) { + /* + * We do not expect any race in IPI case here, + * so locking is not needed. + */ + snprintf(str, INTRNAME_LEN, "cpu%d:%s", i, name); + intrcnt_setname(str, index + i); + } +} +#endif + +/* + * Main interrupt dispatch handler. It's called straight + * from the assembler, where CPU interrupt is served. + */ +void +intr_irq_handler(struct trapframe *tf) +{ + struct trapframe * oldframe; + struct thread * td; + + KASSERT(irq_root_filter != NULL, ("%s: no filter", __func__)); + + PCPU_INC(cnt.v_intr); + critical_enter(); + td = curthread; + oldframe = td->td_intr_frame; + td->td_intr_frame = tf; + irq_root_filter(irq_root_arg); + td->td_intr_frame = oldframe; + critical_exit(); +} + +/* + * interrupt controller dispatch function for interrupts. It should + * be called straight from the interrupt controller, when associated interrupt + * source is learned. + */ +void +intr_irq_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf) +{ + + KASSERT(isrc != NULL, ("%s: no source", __func__)); + + isrc_increment_count(isrc); + +#ifdef INTR_SOLO + if (isrc->isrc_filter != NULL) { + int error; + error = isrc->isrc_filter(isrc->isrc_arg, tf); + PIC_POST_FILTER(isrc->isrc_dev, isrc); + if (error == FILTER_HANDLED) + return; + } else +#endif + if (isrc->isrc_event != NULL) { + if (intr_event_handle(isrc->isrc_event, tf) == 0) + return; + } + + isrc_increment_straycount(isrc); + PIC_DISABLE_SOURCE(isrc->isrc_dev, isrc); + + device_printf(isrc->isrc_dev, "stray irq <%s> disabled", + isrc->isrc_name); +} + +/* + * Allocate interrupt source. + */ +static struct intr_irqsrc * +isrc_alloc(u_int type, u_int extsize) +{ + struct intr_irqsrc *isrc; + + isrc = malloc(sizeof(*isrc) + extsize, M_INTRNG, M_WAITOK | M_ZERO); + isrc->isrc_irq = IRQ_INVALID; /* just to be safe */ + isrc->isrc_type = type; + isrc->isrc_nspc_type = INTR_IRQ_NSPC_NONE; + isrc->isrc_trig = INTR_TRIGGER_CONFORM; + isrc->isrc_pol = INTR_POLARITY_CONFORM; + CPU_ZERO(&isrc->isrc_cpu); + return (isrc); +} + +/* + * Free interrupt source. + */ +static void +isrc_free(struct intr_irqsrc *isrc) +{ + + free(isrc, M_INTRNG); +} + +void +intr_irq_set_name(struct intr_irqsrc *isrc, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsnprintf(isrc->isrc_name, INTR_ISRC_NAMELEN, fmt, ap); + va_end(ap); +} + +/* + * Alloc unique interrupt number (resource handle) for interrupt source. + * + * There could be various strategies how to allocate free interrupt number + * (resource handle) for new interrupt source. + * + * 1. Handles are always allocated forward, so handles are not recycled + * immediately. However, if only one free handle left which is reused + * constantly... + */ +static int +isrc_alloc_irq_locked(struct intr_irqsrc *isrc) +{ + u_int maxirqs, irq; + + mtx_assert(&isrc_table_lock, MA_OWNED); + + maxirqs = nitems(irq_sources); + if (irq_next_free >= maxirqs) + return (ENOSPC); + + for (irq = irq_next_free; irq < maxirqs; irq++) { + if (irq_sources[irq] == NULL) + goto found; + } + for (irq = 0; irq < irq_next_free; irq++) { + if (irq_sources[irq] == NULL) + goto found; + } + + irq_next_free = maxirqs; + return (ENOSPC); + +found: + isrc->isrc_irq = irq; + irq_sources[irq] = isrc; + + intr_irq_set_name(isrc, "irq%u", irq); + isrc_setup_counters(isrc); + + irq_next_free = irq + 1; + if (irq_next_free >= maxirqs) + irq_next_free = 0; + return (0); +} +#ifdef notyet +/* + * Free unique interrupt number (resource handle) from interrupt source. + */ +static int +isrc_free_irq(struct intr_irqsrc *isrc) +{ + u_int maxirqs; + + mtx_assert(&isrc_table_lock, MA_NOTOWNED); + + maxirqs = nitems(irq_sources); + if (isrc->isrc_irq >= maxirqs) + return (EINVAL); + + mtx_lock(&isrc_table_lock); + if (irq_sources[isrc->isrc_irq] != isrc) { + mtx_unlock(&isrc_table_lock); + return (EINVAL); + } + + irq_sources[isrc->isrc_irq] = NULL; + isrc->isrc_irq = IRQ_INVALID; /* just to be safe */ + mtx_unlock(&isrc_table_lock); + + return (0); +} +#endif +/* + * Lookup interrupt source by interrupt number (resource handle). + */ +static struct intr_irqsrc * +isrc_lookup(u_int irq) +{ + + if (irq < nitems(irq_sources)) + return (irq_sources[irq]); + return (NULL); +} + +/* + * Lookup interrupt source by namespace description. + */ +static struct intr_irqsrc * +isrc_namespace_lookup(device_t dev, uint16_t type, uint16_t num) +{ + u_int irq; + struct intr_irqsrc *isrc; + + mtx_assert(&isrc_table_lock, MA_OWNED); + + for (irq = 0; irq < nitems(irq_sources); irq++) { + isrc = irq_sources[irq]; + if (isrc != NULL && isrc->isrc_dev == dev && + isrc->isrc_nspc_type == type && isrc->isrc_nspc_num == num) + return (isrc); + } + return (NULL); +} + +/* + * Map interrupt source according to namespace into framework. If such mapping + * does not exist, create it. Return unique interrupt number (resource handle) + * associated with mapped interrupt source. + */ +u_int +intr_namespace_map_irq(device_t dev, uint16_t type, uint16_t num) +{ + struct intr_irqsrc *isrc, *new_isrc; + int error; + + new_isrc = isrc_alloc(INTR_ISRCT_NAMESPACE, 0); + + mtx_lock(&isrc_table_lock); + isrc = isrc_namespace_lookup(dev, type, num); + if (isrc != NULL) { + mtx_unlock(&isrc_table_lock); + isrc_free(new_isrc); + return (isrc->isrc_irq); /* already mapped */ + } + + error = isrc_alloc_irq_locked(new_isrc); + if (error != 0) { + mtx_unlock(&isrc_table_lock); + isrc_free(new_isrc); + return (IRQ_INVALID); /* no space left */ + } + + new_isrc->isrc_dev = dev; + new_isrc->isrc_nspc_type = type; + new_isrc->isrc_nspc_num = num; + mtx_unlock(&isrc_table_lock); + + return (new_isrc->isrc_irq); +} + +#ifdef FDT +/* + * Lookup interrupt source by FDT description. + */ +static struct intr_irqsrc * +isrc_fdt_lookup(intptr_t xref, pcell_t *cells, u_int ncells) +{ + u_int irq, cellsize; + struct intr_irqsrc *isrc; + + mtx_assert(&isrc_table_lock, MA_OWNED); + + cellsize = ncells * sizeof(*cells); + for (irq = 0; irq < nitems(irq_sources); irq++) { + isrc = irq_sources[irq]; + if (isrc != NULL && isrc->isrc_type == INTR_ISRCT_FDT && + isrc->isrc_xref == xref && isrc->isrc_ncells == ncells && + memcmp(isrc->isrc_cells, cells, cellsize) == 0) + return (isrc); + } + return (NULL); +} + +/* + * Map interrupt source according to FDT data into framework. If such mapping + * does not exist, create it. Return unique interrupt number (resource handle) + * associated with mapped interrupt source. + */ +u_int +intr_fdt_map_irq(phandle_t node, pcell_t *cells, u_int ncells) +{ + struct intr_irqsrc *isrc, *new_isrc; + u_int cellsize; + intptr_t xref; + int error; + + xref = (intptr_t)node; /* It's so simple for now. */ + + cellsize = ncells * sizeof(*cells); + new_isrc = isrc_alloc(INTR_ISRCT_FDT, cellsize); + + mtx_lock(&isrc_table_lock); + isrc = isrc_fdt_lookup(xref, cells, ncells); + if (isrc != NULL) { + mtx_unlock(&isrc_table_lock); + isrc_free(new_isrc); + return (isrc->isrc_irq); /* already mapped */ + } + + error = isrc_alloc_irq_locked(new_isrc); + if (error != 0) { + mtx_unlock(&isrc_table_lock); + isrc_free(new_isrc); + return (IRQ_INVALID); /* no space left */ + } + + new_isrc->isrc_xref = xref; + new_isrc->isrc_ncells = ncells; + memcpy(new_isrc->isrc_cells, cells, cellsize); + mtx_unlock(&isrc_table_lock); + + return (new_isrc->isrc_irq); +} +#endif + +/* + * Register interrupt source into interrupt controller. + */ +static int +isrc_register(struct intr_irqsrc *isrc) +{ + struct intr_pic *pic; + boolean_t is_percpu; + int error; + + if (isrc->isrc_flags & INTR_ISRCF_REGISTERED) + return (0); + + if (isrc->isrc_dev == NULL) { + pic = pic_lookup(NULL, isrc->isrc_xref); + if (pic == NULL || pic->pic_dev == NULL) + return (ESRCH); + isrc->isrc_dev = pic->pic_dev; + } + + error = PIC_REGISTER(isrc->isrc_dev, isrc, &is_percpu); + if (error != 0) + return (error); + + mtx_lock(&isrc_table_lock); + isrc->isrc_flags |= INTR_ISRCF_REGISTERED; + if (is_percpu) + isrc->isrc_flags |= INTR_ISRCF_PERCPU; + isrc_update_name(isrc, NULL); + mtx_unlock(&isrc_table_lock); + return (0); +} + +#ifdef INTR_SOLO +/* + * Setup filter into interrupt source. + */ +static int +iscr_setup_filter(struct intr_irqsrc *isrc, const char *name, + intr_irq_filter_t *filter, void *arg, void **cookiep) +{ + + if (filter == NULL) + return (EINVAL); + + mtx_lock(&isrc_table_lock); + /* + * Make sure that we do not mix the two ways + * how we handle interrupt sources. + */ + if (isrc->isrc_filter != NULL || isrc->isrc_event != NULL) { + mtx_unlock(&isrc_table_lock); + return (EBUSY); + } + isrc->isrc_filter = filter; + isrc->isrc_arg = arg; + isrc_update_name(isrc, name); + mtx_unlock(&isrc_table_lock); + + *cookiep = isrc; + return (0); +} +#endif + +/* + * Interrupt source pre_ithread method for MI interrupt framework. + */ +static void +intr_isrc_pre_ithread(void *arg) +{ + struct intr_irqsrc *isrc = arg; + + PIC_PRE_ITHREAD(isrc->isrc_dev, isrc); +} + +/* + * Interrupt source post_ithread method for MI interrupt framework. + */ +static void +intr_isrc_post_ithread(void *arg) +{ + struct intr_irqsrc *isrc = arg; + + PIC_POST_ITHREAD(isrc->isrc_dev, isrc); +} + +/* + * Interrupt source post_filter method for MI interrupt framework. + */ +static void +intr_isrc_post_filter(void *arg) +{ + struct intr_irqsrc *isrc = arg; + + PIC_POST_FILTER(isrc->isrc_dev, isrc); +} + +/* + * Interrupt source assign_cpu method for MI interrupt framework. + */ +static int +intr_isrc_assign_cpu(void *arg, int cpu) +{ +#ifdef SMP + struct intr_irqsrc *isrc = arg; + int error; + + if (isrc->isrc_dev != irq_root_dev) + return (EINVAL); + + mtx_lock(&isrc_table_lock); + if (cpu == NOCPU) { + CPU_ZERO(&isrc->isrc_cpu); + isrc->isrc_flags &= ~INTR_ISRCF_BOUND; + } else { + CPU_SETOF(cpu, &isrc->isrc_cpu); + isrc->isrc_flags |= INTR_ISRCF_BOUND; + } + + /* + * In NOCPU case, it's up to PIC to either leave ISRC on same CPU or + * re-balance it to another CPU or enable it on more CPUs. However, + * PIC is expected to change isrc_cpu appropriately to keep us well + * informed if the call is successfull. + */ + if (irq_assign_cpu) { + error = PIC_BIND(isrc->isrc_dev, isrc); + if (error) { + CPU_ZERO(&isrc->isrc_cpu); + mtx_unlock(&isrc_table_lock); + return (error); + } + } + mtx_unlock(&isrc_table_lock); + return (0); +#else + return (EOPNOTSUPP); +#endif +} + +/* + * Create interrupt event for interrupt source. + */ +static int +isrc_event_create(struct intr_irqsrc *isrc) +{ + struct intr_event *ie; + int error; + + error = intr_event_create(&ie, isrc, 0, isrc->isrc_irq, + intr_isrc_pre_ithread, intr_isrc_post_ithread, intr_isrc_post_filter, + intr_isrc_assign_cpu, "%s:", isrc->isrc_name); + if (error) + return (error); + + mtx_lock(&isrc_table_lock); + /* + * Make sure that we do not mix the two ways + * how we handle interrupt sources. Let contested event wins. + */ + if (isrc->isrc_filter != NULL || isrc->isrc_event != NULL) { + mtx_unlock(&isrc_table_lock); + intr_event_destroy(ie); + return (isrc->isrc_event != NULL ? EBUSY : 0); + } + isrc->isrc_event = ie; + mtx_unlock(&isrc_table_lock); + + return (0); +} +#ifdef notyet +/* + * Destroy interrupt event for interrupt source. + */ +static void +isrc_event_destroy(struct intr_irqsrc *isrc) +{ + struct intr_event *ie; + + mtx_lock(&isrc_table_lock); + ie = isrc->isrc_event; + isrc->isrc_event = NULL; + mtx_unlock(&isrc_table_lock); + + if (ie != NULL) + intr_event_destroy(ie); +} +#endif +/* + * Add handler to interrupt source. + */ +static int +isrc_add_handler(struct intr_irqsrc *isrc, const char *name, + driver_filter_t filter, driver_intr_t handler, void *arg, + enum intr_type flags, void **cookiep) +{ + int error; + + if (isrc->isrc_event == NULL) { + error = isrc_event_create(isrc); + if (error) + return (error); + } + + error = intr_event_add_handler(isrc->isrc_event, name, filter, handler, + arg, intr_priority(flags), flags, cookiep); + if (error == 0) { + mtx_lock(&isrc_table_lock); + intrcnt_updatename(isrc); + mtx_unlock(&isrc_table_lock); + } + + return (error); +} + +/* + * Lookup interrupt controller locked. + */ +static struct intr_pic * +pic_lookup_locked(device_t dev, intptr_t xref) +{ + struct intr_pic *pic; + + mtx_assert(&pic_list_lock, MA_OWNED); + + SLIST_FOREACH(pic, &pic_list, pic_next) { + if (pic->pic_xref != xref) + continue; + if (pic->pic_xref != 0 || pic->pic_dev == dev) + return (pic); + } + return (NULL); +} + +/* + * Lookup interrupt controller. + */ +static struct intr_pic * +pic_lookup(device_t dev, intptr_t xref) +{ + struct intr_pic *pic; + + mtx_lock(&pic_list_lock); + pic = pic_lookup_locked(dev, xref); + mtx_unlock(&pic_list_lock); + + return (pic); +} + +/* + * Create interrupt controller. + */ +static struct intr_pic * +pic_create(device_t dev, intptr_t xref) +{ + struct intr_pic *pic; + + mtx_lock(&pic_list_lock); + pic = pic_lookup_locked(dev, xref); + if (pic != NULL) { + mtx_unlock(&pic_list_lock); + return (pic); + } + pic = malloc(sizeof(*pic), M_INTRNG, M_NOWAIT | M_ZERO); + pic->pic_xref = xref; + pic->pic_dev = dev; + SLIST_INSERT_HEAD(&pic_list, pic, pic_next); + mtx_unlock(&pic_list_lock); + + return (pic); +} +#ifdef notyet +/* + * Destroy interrupt controller. + */ +static void +pic_destroy(device_t dev, intptr_t xref) +{ + struct intr_pic *pic; + + mtx_lock(&pic_list_lock); + pic = pic_lookup_locked(dev, xref); + if (pic == NULL) { + mtx_unlock(&pic_list_lock); + return; + } + SLIST_REMOVE(&pic_list, pic, intr_pic, pic_next); + mtx_unlock(&pic_list_lock); + + free(pic, M_INTRNG); +} +#endif +/* + * Register interrupt controller. + */ +int +intr_pic_register(device_t dev, intptr_t xref) +{ + struct intr_pic *pic; + + pic = pic_create(dev, xref); + if (pic == NULL) + return (ENOMEM); + if (pic->pic_dev != dev) + return (EINVAL); /* XXX it could be many things. */ + + debugf("PIC %p registered for %s \n", pic, + device_get_nameunit(dev), xref); + return (0); +} + +/* + * Unregister interrupt controller. + */ +int +intr_pic_unregister(device_t dev, intptr_t xref) +{ + + panic("%s: not implemented", __func__); +} + +/* + * Mark interrupt controller (itself) as a root one. + * + * Note that only an interrupt controller can really know its position + * in interrupt controller's tree. So root PIC must claim itself as a root. + * + * In FDT case, according to ePAPR approved version 1.1 from 08 April 2011, + * page 30: + * "The root of the interrupt tree is determined when traversal + * of the interrupt tree reaches an interrupt controller node without + * an interrupts property and thus no explicit interrupt parent." + */ +int +intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter, + void *arg, u_int ipicount) +{ + int error; + u_int rootirq; + + if (pic_lookup(dev, xref) == NULL) { + device_printf(dev, "not registered\n"); + return (EINVAL); + } + if (filter == NULL) { + device_printf(dev, "filter missing\n"); + return (EINVAL); + } + + /* + * Only one interrupt controllers could be on the root for now. + * Note that we further suppose that there is not threaded interrupt + * routine (handler) on the root. See intr_irq_handler(). + */ + if (irq_root_dev != NULL) { + device_printf(dev, "another root already set\n"); + return (EBUSY); + } + + rootirq = intr_namespace_map_irq(device_get_parent(dev), 0, 0); + if (rootirq == IRQ_INVALID) { + device_printf(dev, "failed to map an irq for the root pic\n"); + return (ENOMEM); + } + + /* Create the isrc. */ + irq_root_isrc = isrc_lookup(rootirq); + + /* XXX "register" with the PIC. We are the "pic" here, so fake it. */ + irq_root_isrc->isrc_flags |= INTR_ISRCF_REGISTERED; + + error = intr_irq_add_handler(device_get_parent(dev), + (void*)filter, NULL, arg, rootirq, INTR_TYPE_CLK, NULL); + if (error != 0) { + device_printf(dev, "failed to install root pic handler\n"); + return (error); + } + irq_root_dev = dev; + irq_root_filter = filter; + irq_root_arg = arg; + irq_root_ipicount = ipicount; + + debugf("irq root set to %s\n", device_get_nameunit(dev)); + return (0); +} + +int +intr_irq_add_handler(device_t dev, driver_filter_t filt, driver_intr_t hand, + void *arg, u_int irq, int flags, void **cookiep) +{ + const char *name; + struct intr_irqsrc *isrc; + int error; + + name = device_get_nameunit(dev); + +#ifdef INTR_SOLO + /* + * Standard handling is done thru MI interrupt framework. However, + * some interrupts could request solely own special handling. This + * non standard handling can be used for interrupt controllers without + * handler (filter only), so in case that interrupt controllers are + * chained, MI interrupt framework is called only in leaf controller. + * + * Note that root interrupt controller routine is served as well, + * however in intr_irq_handler(), i.e. main system dispatch routine. + */ + if (flags & INTR_SOLO && hand != NULL) { + debugf("irq %u cannot solo on %s\n", irq, name); + return (EINVAL); + } +#endif + + isrc = isrc_lookup(irq); + if (isrc == NULL) { + debugf("irq %u without source on %s\n", irq, name); + return (EINVAL); + } + + error = isrc_register(isrc); + if (error != 0) { + debugf("irq %u map error %d on %s\n", irq, error, name); + return (error); + } + +#ifdef INTR_SOLO + if (flags & INTR_SOLO) { + error = iscr_setup_filter(isrc, name, (intr_irq_filter_t *)filt, + arg, cookiep); + debugf("irq %u setup filter error %d on %s\n", irq, error, + name); + } else +#endif + { + error = isrc_add_handler(isrc, name, filt, hand, arg, flags, + cookiep); + debugf("irq %u add handler error %d on %s\n", irq, error, name); + } + if (error != 0) + return (error); + + mtx_lock(&isrc_table_lock); + isrc->isrc_handlers++; + if (isrc->isrc_handlers == 1) { + PIC_ENABLE_INTR(isrc->isrc_dev, isrc); + PIC_ENABLE_SOURCE(isrc->isrc_dev, isrc); + } + mtx_unlock(&isrc_table_lock); + return (0); +} + +int +intr_irq_remove_handler(device_t dev, u_int irq, void *cookie) +{ + struct intr_irqsrc *isrc; + int error; + + isrc = isrc_lookup(irq); + if (isrc == NULL || isrc->isrc_handlers == 0) + return (EINVAL); + + if (isrc->isrc_filter != NULL) { + if (isrc != cookie) + return (EINVAL); + + mtx_lock(&isrc_table_lock); + isrc->isrc_filter = NULL; + isrc->isrc_arg = NULL; + isrc->isrc_handlers = 0; + PIC_DISABLE_SOURCE(isrc->isrc_dev, isrc); + PIC_DISABLE_INTR(isrc->isrc_dev, isrc); + isrc_update_name(isrc, NULL); + mtx_unlock(&isrc_table_lock); + return (0); + } + + if (isrc != intr_handler_source(cookie)) + return (EINVAL); + + error = intr_event_remove_handler(cookie); + if (error == 0) { + mtx_lock(&isrc_table_lock); + isrc->isrc_handlers--; + if (isrc->isrc_handlers == 0) { + PIC_DISABLE_SOURCE(isrc->isrc_dev, isrc); + PIC_DISABLE_INTR(isrc->isrc_dev, isrc); + } + intrcnt_updatename(isrc); + mtx_unlock(&isrc_table_lock); + } + return (error); +} + +int +intr_irq_config(u_int irq, enum intr_trigger trig, enum intr_polarity pol) +{ + struct intr_irqsrc *isrc; + + isrc = isrc_lookup(irq); + if (isrc == NULL) + return (EINVAL); + + if (isrc->isrc_handlers != 0) + return (EBUSY); /* interrrupt is enabled (active) */ + + /* + * Once an interrupt is enabled, we do not change its configuration. + * A controller PIC_ENABLE_INTR() method is called when an interrupt + * is going to be enabled. In this method, a controller should setup + * the interrupt according to saved configuration parameters. + */ + isrc->isrc_trig = trig; + isrc->isrc_pol = pol; + + return (0); +} + +int +intr_irq_describe(u_int irq, void *cookie, const char *descr) +{ + struct intr_irqsrc *isrc; + int error; + + isrc = isrc_lookup(irq); + if (isrc == NULL || isrc->isrc_handlers == 0) + return (EINVAL); + + if (isrc->isrc_filter != NULL) { + if (isrc != cookie) + return (EINVAL); + + mtx_lock(&isrc_table_lock); + isrc_update_name(isrc, descr); + mtx_unlock(&isrc_table_lock); + return (0); + } + + error = intr_event_describe_handler(isrc->isrc_event, cookie, descr); + if (error == 0) { + mtx_lock(&isrc_table_lock); + intrcnt_updatename(isrc); + mtx_unlock(&isrc_table_lock); + } + return (error); +} + +#ifdef SMP +int +intr_irq_bind(u_int irq, int cpu) +{ + struct intr_irqsrc *isrc; + + isrc = isrc_lookup(irq); + if (isrc == NULL || isrc->isrc_handlers == 0) + return (EINVAL); + + if (isrc->isrc_filter != NULL) + return (intr_isrc_assign_cpu(isrc, cpu)); + + return (intr_event_bind(isrc->isrc_event, cpu)); +} + +/* + * Return the CPU that the next interrupt source should use. + * For now just returns the next CPU according to round-robin. + */ +u_int +intr_irq_next_cpu(u_int last_cpu, cpuset_t *cpumask) +{ + + if (!irq_assign_cpu || mp_ncpus == 1) + return (PCPU_GET(cpuid)); + + do { + last_cpu++; + if (last_cpu > mp_maxid) + last_cpu = 0; + } while (!CPU_ISSET(last_cpu, cpumask)); + return (last_cpu); +} + +/* + * Distribute all the interrupt sources among the available + * CPUs once the AP's have been launched. + */ +static void +intr_irq_shuffle(void *arg __unused) +{ + struct intr_irqsrc *isrc; + u_int i; + + if (mp_ncpus == 1) + return; + + mtx_lock(&isrc_table_lock); + irq_assign_cpu = TRUE; + for (i = 0; i < NIRQ; i++) { + isrc = irq_sources[i]; + if (isrc == NULL || isrc->isrc_handlers == 0 || + isrc->isrc_flags & INTR_ISRCF_PERCPU) + continue; + + if (isrc->isrc_event != NULL && + isrc->isrc_flags & INTR_ISRCF_BOUND && + isrc->isrc_event->ie_cpu != CPU_FFS(&isrc->isrc_cpu) - 1) + panic("%s: CPU inconsistency", __func__); + + if ((isrc->isrc_flags & INTR_ISRCF_BOUND) == 0) + CPU_ZERO(&isrc->isrc_cpu); /* start again */ + + /* + * We are in wicked position here if the following call fails + * for bound ISRC. The best thing we can do is to clear + * isrc_cpu so inconsistency with ie_cpu will be detectable. + */ + if (PIC_BIND(isrc->isrc_dev, isrc) != 0) + CPU_ZERO(&isrc->isrc_cpu); + } + mtx_unlock(&isrc_table_lock); +} +SYSINIT(intr_irq_shuffle, SI_SUB_SMP, SI_ORDER_SECOND, intr_irq_shuffle, NULL); + +#else +u_int +intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask) +{ + + return (PCPU_GET(cpuid)); +} +#endif + +void dosoftints(void); +void +dosoftints(void) +{ +} + +#ifdef SMP +/* + * Lookup IPI source. + */ +static struct intr_irqsrc * +intr_ipi_lookup(u_int ipi) +{ + + if (ipi >= INTR_IPI_COUNT) + panic("%s: no such IPI %u", __func__, ipi); + + return (&ipi_sources[ipi]); +} + +/* + * interrupt controller dispatch function for IPIs. It should + * be called straight from the interrupt controller, when associated + * interrupt source is learned. Or from anybody who has an interrupt + * source mapped. + */ +void +intr_ipi_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf) +{ + void *arg; + + KASSERT(isrc != NULL, ("%s: no source", __func__)); + + isrc_increment_ipi_count(isrc, PCPU_GET(cpuid)); + + /* + * Supply ipi filter with trapframe argument + * if none is registered. + */ + arg = isrc->isrc_arg != NULL ? isrc->isrc_arg : tf; + isrc->isrc_ipifilter(arg); +} + +/* + * Map IPI into interrupt controller. + * + * Not SMP coherent. + */ +static int +ipi_map(struct intr_irqsrc *isrc, u_int ipi) +{ + boolean_t is_percpu; + int error; + + if (ipi >= INTR_IPI_COUNT) + panic("%s: no such IPI %u", __func__, ipi); + + KASSERT(irq_root_dev != NULL, ("%s: no root attached", __func__)); + + isrc->isrc_type = INTR_ISRCT_NAMESPACE; + isrc->isrc_nspc_type = INTR_IRQ_NSPC_IPI; + isrc->isrc_nspc_num = ipi_next_num; + + error = PIC_REGISTER(irq_root_dev, isrc, &is_percpu); + + debugf("ipi %u mapped to %u on %s - error %d\n", ipi, ipi_next_num, + device_get_nameunit(irq_root_dev), error); + + if (error == 0) { + isrc->isrc_dev = irq_root_dev; + ipi_next_num++; + } + return (error); +} + +/* + * Setup IPI handler to interrupt source. + * + * Note that there could be more ways how to send and receive IPIs + * on a platform like fast interrupts for example. In that case, + * one can call this function with ASIF_NOALLOC flag set and then + * call intr_ipi_dispatch() when appropriate. + * + * Not SMP coherent. + */ +int +intr_ipi_set_handler(u_int ipi, const char *name, intr_ipi_filter_t *filter, + void *arg, u_int flags) +{ + struct intr_irqsrc *isrc; + int error; + + if (filter == NULL) + return(EINVAL); + + isrc = intr_ipi_lookup(ipi); + if (isrc->isrc_ipifilter != NULL) + return (EEXIST); + + if ((flags & AISHF_NOALLOC) == 0) { + error = ipi_map(isrc, ipi); + if (error != 0) + return (error); + } + + isrc->isrc_ipifilter = filter; + isrc->isrc_arg = arg; + isrc->isrc_handlers = 1; + isrc_setup_ipi_counters(isrc, name); + + if (isrc->isrc_dev != NULL) { + mtx_lock(&isrc_table_lock); + PIC_ENABLE_INTR(isrc->isrc_dev, isrc); + PIC_ENABLE_SOURCE(isrc->isrc_dev, isrc); + mtx_unlock(&isrc_table_lock); + } + return (0); +} + +/* + * Send IPI thru interrupt controller. + */ +void +pic_ipi_send(cpuset_t cpus, u_int ipi) +{ + struct intr_irqsrc *isrc; + + isrc = intr_ipi_lookup(ipi); + + KASSERT(irq_root_dev != NULL, ("%s: no root attached", __func__)); + PIC_IPI_SEND(irq_root_dev, isrc, cpus); +} + +/* + * Init interrupt controller on another CPU. + */ +void +intr_pic_init_secondary(void) +{ + + /* + * QQQ: Only root PIC is aware of other CPUs ??? + */ + KASSERT(irq_root_dev != NULL, ("%s: no root attached", __func__)); + + //mtx_lock(&isrc_table_lock); + PIC_INIT_SECONDARY(irq_root_dev); + //mtx_unlock(&isrc_table_lock); +} +#endif + +#ifdef DDB +DB_SHOW_COMMAND(irqs, db_show_irqs) +{ + u_int i, irqsum; + struct intr_irqsrc *isrc; + +#ifdef SMP + for (i = 0; i <= mp_maxid; i++) { + struct pcpu *pc; + u_int ipi, ipisum; + + pc = pcpu_find(i); + if (pc != NULL) { + for (ipisum = 0, ipi = 0; ipi < INTR_IPI_COUNT; ipi++) { + isrc = intr_ipi_lookup(ipi); + if (isrc->isrc_count != NULL) + ipisum += isrc->isrc_count[i]; + } + printf ("cpu%u: total %u ipis %u\n", i, + pc->pc_cnt.v_intr, ipisum); + } + } + db_printf("\n"); +#endif + + for (irqsum = 0, i = 0; i < NIRQ; i++) { + isrc = irq_sources[i]; + if (isrc == NULL) + continue; + + db_printf("irq%-3u <%s>: cpu %02lx%s cnt %lu\n", i, + isrc->isrc_name, isrc->isrc_cpu.__bits[0], + isrc->isrc_flags & INTR_ISRCF_BOUND ? " (bound)" : "", + isrc->isrc_count[0]); + irqsum += isrc->isrc_count[0]; + } + db_printf("irq total %u\n", irqsum); +} +#endif Property changes on: user/alc/PQ_LAUNDRY/sys/kern/subr_intr.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/modules/geom/geom_sched/Makefile =================================================================== --- user/alc/PQ_LAUNDRY/sys/modules/geom/geom_sched/Makefile (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/modules/geom/geom_sched/Makefile (revision 292449) @@ -1,5 +1,5 @@ # $FreeBSD$ -SUBDIR= gs_sched gsched_rr +SUBDIR= gs_sched gsched_rr gsched_delay .include Index: user/alc/PQ_LAUNDRY/sys/modules/geom/geom_sched/gsched_delay/Makefile =================================================================== --- user/alc/PQ_LAUNDRY/sys/modules/geom/geom_sched/gsched_delay/Makefile (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/modules/geom/geom_sched/gsched_delay/Makefile (revision 292449) @@ -0,0 +1,7 @@ +# $FreeBSD$ + +KMOD= gsched_delay +SRCS= gs_delay.c + +# ../Makefile.inc automatically included +.include Property changes on: user/alc/PQ_LAUNDRY/sys/modules/geom/geom_sched/gsched_delay/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/net/if.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/net/if.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/net/if.c (revision 292449) @@ -1,3955 +1,3941 @@ /*- * Copyright (c) 1980, 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. * 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. * * @(#)if.c 8.5 (Berkeley) 1/9/95 * $FreeBSD$ */ #include "opt_compat.h" #include "opt_inet6.h" #include "opt_inet.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(INET) || defined(INET6) #include #include #include #include #include #ifdef INET #include #endif /* INET */ #ifdef INET6 #include #include #endif /* INET6 */ #endif /* INET || INET6 */ #include #ifdef COMPAT_FREEBSD32 #include #include #endif SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers"); SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management"); SYSCTL_INT(_net_link, OID_AUTO, ifqmaxlen, CTLFLAG_RDTUN, &ifqmaxlen, 0, "max send queue size"); /* Log link state change events */ static int log_link_state_change = 1; SYSCTL_INT(_net_link, OID_AUTO, log_link_state_change, CTLFLAG_RW, &log_link_state_change, 0, "log interface link state change events"); /* Interface description */ static unsigned int ifdescr_maxlen = 1024; SYSCTL_UINT(_net, OID_AUTO, ifdescr_maxlen, CTLFLAG_RW, &ifdescr_maxlen, 0, "administrative maximum length for interface description"); static MALLOC_DEFINE(M_IFDESCR, "ifdescr", "ifnet descriptions"); /* global sx for non-critical path ifdescr */ static struct sx ifdescr_sx; SX_SYSINIT(ifdescr_sx, &ifdescr_sx, "ifnet descr"); void (*bridge_linkstate_p)(struct ifnet *ifp); void (*ng_ether_link_state_p)(struct ifnet *ifp, int state); -void (*lagg_linkstate_p)(struct ifnet *ifp); +void (*lagg_linkstate_p)(struct ifnet *ifp, int state); /* These are external hooks for CARP. */ void (*carp_linkstate_p)(struct ifnet *ifp); void (*carp_demote_adj_p)(int, char *); int (*carp_master_p)(struct ifaddr *); #if defined(INET) || defined(INET6) int (*carp_forus_p)(struct ifnet *ifp, u_char *dhost); int (*carp_output_p)(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa); int (*carp_ioctl_p)(struct ifreq *, u_long, struct thread *); int (*carp_attach_p)(struct ifaddr *, int); void (*carp_detach_p)(struct ifaddr *); #endif #ifdef INET int (*carp_iamatch_p)(struct ifaddr *, uint8_t **); #endif #ifdef INET6 struct ifaddr *(*carp_iamatch6_p)(struct ifnet *ifp, struct in6_addr *taddr6); caddr_t (*carp_macmatch6_p)(struct ifnet *ifp, struct mbuf *m, const struct in6_addr *taddr); #endif struct mbuf *(*tbr_dequeue_ptr)(struct ifaltq *, int) = NULL; /* * XXX: Style; these should be sorted alphabetically, and unprototyped * static functions should be prototyped. Currently they are sorted by * declaration order. */ static void if_attachdomain(void *); static void if_attachdomain1(struct ifnet *); static int ifconf(u_long, caddr_t); static void if_freemulti(struct ifmultiaddr *); static void if_grow(void); static void if_input_default(struct ifnet *, struct mbuf *); static void if_route(struct ifnet *, int flag, int fam); static int if_setflag(struct ifnet *, int, int, int *, int); static int if_transmit(struct ifnet *ifp, struct mbuf *m); static void if_unroute(struct ifnet *, int flag, int fam); static void link_rtrequest(int, struct rtentry *, struct rt_addrinfo *); static int ifhwioctl(u_long, struct ifnet *, caddr_t, struct thread *); static int if_delmulti_locked(struct ifnet *, struct ifmultiaddr *, int); static void do_link_state_change(void *, int); static int if_getgroup(struct ifgroupreq *, struct ifnet *); static int if_getgroupmembers(struct ifgroupreq *); static void if_delgroups(struct ifnet *); static void if_attach_internal(struct ifnet *, int, struct if_clone *); static void if_detach_internal(struct ifnet *, int, struct if_clone **); #ifdef INET6 /* * XXX: declare here to avoid to include many inet6 related files.. * should be more generalized? */ extern void nd6_setmtu(struct ifnet *); #endif /* ipsec helper hooks */ VNET_DEFINE(struct hhook_head *, ipsec_hhh_in[HHOOK_IPSEC_COUNT]); VNET_DEFINE(struct hhook_head *, ipsec_hhh_out[HHOOK_IPSEC_COUNT]); VNET_DEFINE(int, if_index); int ifqmaxlen = IFQ_MAXLEN; VNET_DEFINE(struct ifnethead, ifnet); /* depend on static init XXX */ VNET_DEFINE(struct ifgrouphead, ifg_head); static VNET_DEFINE(int, if_indexlim) = 8; /* Table of ifnet by index. */ VNET_DEFINE(struct ifnet **, ifindex_table); #define V_if_indexlim VNET(if_indexlim) #define V_ifindex_table VNET(ifindex_table) /* * The global network interface list (V_ifnet) and related state (such as * if_index, if_indexlim, and ifindex_table) are protected by an sxlock and * an rwlock. Either may be acquired shared to stablize the list, but both * must be acquired writable to modify the list. This model allows us to * both stablize the interface list during interrupt thread processing, but * also to stablize it over long-running ioctls, without introducing priority * inversions and deadlocks. */ struct rwlock ifnet_rwlock; RW_SYSINIT_FLAGS(ifnet_rw, &ifnet_rwlock, "ifnet_rw", RW_RECURSE); struct sx ifnet_sxlock; SX_SYSINIT_FLAGS(ifnet_sx, &ifnet_sxlock, "ifnet_sx", SX_RECURSE); /* * The allocation of network interfaces is a rather non-atomic affair; we * need to select an index before we are ready to expose the interface for * use, so will use this pointer value to indicate reservation. */ #define IFNET_HOLD (void *)(uintptr_t)(-1) static if_com_alloc_t *if_com_alloc[256]; static if_com_free_t *if_com_free[256]; static MALLOC_DEFINE(M_IFNET, "ifnet", "interface internals"); MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address"); MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address"); struct ifnet * ifnet_byindex_locked(u_short idx) { if (idx > V_if_index) return (NULL); if (V_ifindex_table[idx] == IFNET_HOLD) return (NULL); return (V_ifindex_table[idx]); } struct ifnet * ifnet_byindex(u_short idx) { struct ifnet *ifp; IFNET_RLOCK_NOSLEEP(); ifp = ifnet_byindex_locked(idx); IFNET_RUNLOCK_NOSLEEP(); return (ifp); } struct ifnet * ifnet_byindex_ref(u_short idx) { struct ifnet *ifp; IFNET_RLOCK_NOSLEEP(); ifp = ifnet_byindex_locked(idx); if (ifp == NULL || (ifp->if_flags & IFF_DYING)) { IFNET_RUNLOCK_NOSLEEP(); return (NULL); } if_ref(ifp); IFNET_RUNLOCK_NOSLEEP(); return (ifp); } /* * Allocate an ifindex array entry; return 0 on success or an error on * failure. */ static u_short ifindex_alloc(void) { u_short idx; IFNET_WLOCK_ASSERT(); retry: /* * Try to find an empty slot below V_if_index. If we fail, take the * next slot. */ for (idx = 1; idx <= V_if_index; idx++) { if (V_ifindex_table[idx] == NULL) break; } /* Catch if_index overflow. */ if (idx >= V_if_indexlim) { if_grow(); goto retry; } if (idx > V_if_index) V_if_index = idx; return (idx); } static void ifindex_free_locked(u_short idx) { IFNET_WLOCK_ASSERT(); V_ifindex_table[idx] = NULL; while (V_if_index > 0 && V_ifindex_table[V_if_index] == NULL) V_if_index--; } static void ifindex_free(u_short idx) { IFNET_WLOCK(); ifindex_free_locked(idx); IFNET_WUNLOCK(); } static void ifnet_setbyindex_locked(u_short idx, struct ifnet *ifp) { IFNET_WLOCK_ASSERT(); V_ifindex_table[idx] = ifp; } static void ifnet_setbyindex(u_short idx, struct ifnet *ifp) { IFNET_WLOCK(); ifnet_setbyindex_locked(idx, ifp); IFNET_WUNLOCK(); } struct ifaddr * ifaddr_byindex(u_short idx) { struct ifnet *ifp; struct ifaddr *ifa = NULL; IFNET_RLOCK_NOSLEEP(); ifp = ifnet_byindex_locked(idx); if (ifp != NULL && (ifa = ifp->if_addr) != NULL) ifa_ref(ifa); IFNET_RUNLOCK_NOSLEEP(); return (ifa); } /* * Network interface utility routines. * * Routines with ifa_ifwith* names take sockaddr *'s as * parameters. */ static void vnet_if_init(const void *unused __unused) { TAILQ_INIT(&V_ifnet); TAILQ_INIT(&V_ifg_head); IFNET_WLOCK(); if_grow(); /* create initial table */ IFNET_WUNLOCK(); vnet_if_clone_init(); } VNET_SYSINIT(vnet_if_init, SI_SUB_INIT_IF, SI_ORDER_SECOND, vnet_if_init, NULL); #ifdef VIMAGE static void vnet_if_uninit(const void *unused __unused) { VNET_ASSERT(TAILQ_EMPTY(&V_ifnet), ("%s:%d tailq &V_ifnet=%p " "not empty", __func__, __LINE__, &V_ifnet)); VNET_ASSERT(TAILQ_EMPTY(&V_ifg_head), ("%s:%d tailq &V_ifg_head=%p " "not empty", __func__, __LINE__, &V_ifg_head)); free((caddr_t)V_ifindex_table, M_IFNET); } VNET_SYSUNINIT(vnet_if_uninit, SI_SUB_INIT_IF, SI_ORDER_FIRST, vnet_if_uninit, NULL); #endif static void if_grow(void) { int oldlim; u_int n; struct ifnet **e; IFNET_WLOCK_ASSERT(); oldlim = V_if_indexlim; IFNET_WUNLOCK(); n = (oldlim << 1) * sizeof(*e); e = malloc(n, M_IFNET, M_WAITOK | M_ZERO); IFNET_WLOCK(); if (V_if_indexlim != oldlim) { free(e, M_IFNET); return; } if (V_ifindex_table != NULL) { memcpy((caddr_t)e, (caddr_t)V_ifindex_table, n/2); free((caddr_t)V_ifindex_table, M_IFNET); } V_if_indexlim <<= 1; V_ifindex_table = e; } /* * Allocate a struct ifnet and an index for an interface. A layer 2 * common structure will also be allocated if an allocation routine is * registered for the passed type. */ struct ifnet * if_alloc(u_char type) { struct ifnet *ifp; u_short idx; ifp = malloc(sizeof(struct ifnet), M_IFNET, M_WAITOK|M_ZERO); IFNET_WLOCK(); idx = ifindex_alloc(); ifnet_setbyindex_locked(idx, IFNET_HOLD); IFNET_WUNLOCK(); ifp->if_index = idx; ifp->if_type = type; ifp->if_alloctype = type; if (if_com_alloc[type] != NULL) { ifp->if_l2com = if_com_alloc[type](type, ifp); if (ifp->if_l2com == NULL) { free(ifp, M_IFNET); ifindex_free(idx); return (NULL); } } IF_ADDR_LOCK_INIT(ifp); TASK_INIT(&ifp->if_linktask, 0, do_link_state_change, ifp); ifp->if_afdata_initialized = 0; IF_AFDATA_LOCK_INIT(ifp); TAILQ_INIT(&ifp->if_addrhead); TAILQ_INIT(&ifp->if_multiaddrs); TAILQ_INIT(&ifp->if_groups); #ifdef MAC mac_ifnet_init(ifp); #endif ifq_init(&ifp->if_snd, ifp); refcount_init(&ifp->if_refcount, 1); /* Index reference. */ for (int i = 0; i < IFCOUNTERS; i++) ifp->if_counters[i] = counter_u64_alloc(M_WAITOK); ifp->if_get_counter = if_get_counter_default; ifnet_setbyindex(ifp->if_index, ifp); return (ifp); } /* * Do the actual work of freeing a struct ifnet, and layer 2 common * structure. This call is made when the last reference to an * interface is released. */ static void if_free_internal(struct ifnet *ifp) { KASSERT((ifp->if_flags & IFF_DYING), ("if_free_internal: interface not dying")); if (if_com_free[ifp->if_alloctype] != NULL) if_com_free[ifp->if_alloctype](ifp->if_l2com, ifp->if_alloctype); #ifdef MAC mac_ifnet_destroy(ifp); #endif /* MAC */ if (ifp->if_description != NULL) free(ifp->if_description, M_IFDESCR); IF_AFDATA_DESTROY(ifp); IF_ADDR_LOCK_DESTROY(ifp); ifq_delete(&ifp->if_snd); for (int i = 0; i < IFCOUNTERS; i++) counter_u64_free(ifp->if_counters[i]); free(ifp, M_IFNET); } /* * Deregister an interface and free the associated storage. */ void if_free(struct ifnet *ifp) { ifp->if_flags |= IFF_DYING; /* XXX: Locking */ CURVNET_SET_QUIET(ifp->if_vnet); IFNET_WLOCK(); KASSERT(ifp == ifnet_byindex_locked(ifp->if_index), ("%s: freeing unallocated ifnet", ifp->if_xname)); ifindex_free_locked(ifp->if_index); IFNET_WUNLOCK(); if (refcount_release(&ifp->if_refcount)) if_free_internal(ifp); CURVNET_RESTORE(); } /* * Interfaces to keep an ifnet type-stable despite the possibility of the * driver calling if_free(). If there are additional references, we defer * freeing the underlying data structure. */ void if_ref(struct ifnet *ifp) { /* We don't assert the ifnet list lock here, but arguably should. */ refcount_acquire(&ifp->if_refcount); } void if_rele(struct ifnet *ifp) { if (!refcount_release(&ifp->if_refcount)) return; if_free_internal(ifp); } void ifq_init(struct ifaltq *ifq, struct ifnet *ifp) { mtx_init(&ifq->ifq_mtx, ifp->if_xname, "if send queue", MTX_DEF); if (ifq->ifq_maxlen == 0) ifq->ifq_maxlen = ifqmaxlen; ifq->altq_type = 0; ifq->altq_disc = NULL; ifq->altq_flags &= ALTQF_CANTCHANGE; ifq->altq_tbr = NULL; ifq->altq_ifp = ifp; } void ifq_delete(struct ifaltq *ifq) { mtx_destroy(&ifq->ifq_mtx); } /* * Perform generic interface initalization tasks and attach the interface * to the list of "active" interfaces. If vmove flag is set on entry * to if_attach_internal(), perform only a limited subset of initialization * tasks, given that we are moving from one vnet to another an ifnet which * has already been fully initialized. * * Note that if_detach_internal() removes group membership unconditionally * even when vmove flag is set, and if_attach_internal() adds only IFG_ALL. * Thus, when if_vmove() is applied to a cloned interface, group membership * is lost while a cloned one always joins a group whose name is * ifc->ifc_name. To recover this after if_detach_internal() and * if_attach_internal(), the cloner should be specified to * if_attach_internal() via ifc. If it is non-NULL, if_attach_internal() * attempts to join a group whose name is ifc->ifc_name. * * XXX: * - The decision to return void and thus require this function to * succeed is questionable. * - We should probably do more sanity checking. For instance we don't * do anything to insure if_xname is unique or non-empty. */ void if_attach(struct ifnet *ifp) { if_attach_internal(ifp, 0, NULL); } /* * Compute the least common TSO limit. */ void if_hw_tsomax_common(if_t ifp, struct ifnet_hw_tsomax *pmax) { /* * 1) If there is no limit currently, take the limit from * the network adapter. * * 2) If the network adapter has a limit below the current * limit, apply it. */ if (pmax->tsomaxbytes == 0 || (ifp->if_hw_tsomax != 0 && ifp->if_hw_tsomax < pmax->tsomaxbytes)) { pmax->tsomaxbytes = ifp->if_hw_tsomax; } if (pmax->tsomaxsegcount == 0 || (ifp->if_hw_tsomaxsegcount != 0 && ifp->if_hw_tsomaxsegcount < pmax->tsomaxsegcount)) { pmax->tsomaxsegcount = ifp->if_hw_tsomaxsegcount; } if (pmax->tsomaxsegsize == 0 || (ifp->if_hw_tsomaxsegsize != 0 && ifp->if_hw_tsomaxsegsize < pmax->tsomaxsegsize)) { pmax->tsomaxsegsize = ifp->if_hw_tsomaxsegsize; } } /* * Update TSO limit of a network adapter. * * Returns zero if no change. Else non-zero. */ int if_hw_tsomax_update(if_t ifp, struct ifnet_hw_tsomax *pmax) { int retval = 0; if (ifp->if_hw_tsomax != pmax->tsomaxbytes) { ifp->if_hw_tsomax = pmax->tsomaxbytes; retval++; } if (ifp->if_hw_tsomaxsegsize != pmax->tsomaxsegsize) { ifp->if_hw_tsomaxsegsize = pmax->tsomaxsegsize; retval++; } if (ifp->if_hw_tsomaxsegcount != pmax->tsomaxsegcount) { ifp->if_hw_tsomaxsegcount = pmax->tsomaxsegcount; retval++; } return (retval); } static void if_attach_internal(struct ifnet *ifp, int vmove, struct if_clone *ifc) { unsigned socksize, ifasize; int namelen, masklen; struct sockaddr_dl *sdl; struct ifaddr *ifa; if (ifp->if_index == 0 || ifp != ifnet_byindex(ifp->if_index)) panic ("%s: BUG: if_attach called without if_alloc'd input()\n", ifp->if_xname); #ifdef VIMAGE ifp->if_vnet = curvnet; if (ifp->if_home_vnet == NULL) ifp->if_home_vnet = curvnet; #endif if_addgroup(ifp, IFG_ALL); /* Restore group membership for cloned interfaces. */ if (vmove && ifc != NULL) if_clone_addgroup(ifp, ifc); getmicrotime(&ifp->if_lastchange); ifp->if_epoch = time_uptime; KASSERT((ifp->if_transmit == NULL && ifp->if_qflush == NULL) || (ifp->if_transmit != NULL && ifp->if_qflush != NULL), ("transmit and qflush must both either be set or both be NULL")); if (ifp->if_transmit == NULL) { ifp->if_transmit = if_transmit; ifp->if_qflush = if_qflush; } if (ifp->if_input == NULL) ifp->if_input = if_input_default; if (!vmove) { #ifdef MAC mac_ifnet_create(ifp); #endif /* * Create a Link Level name for this device. */ namelen = strlen(ifp->if_xname); /* * Always save enough space for any possiable name so we * can do a rename in place later. */ masklen = offsetof(struct sockaddr_dl, sdl_data[0]) + IFNAMSIZ; socksize = masklen + ifp->if_addrlen; if (socksize < sizeof(*sdl)) socksize = sizeof(*sdl); socksize = roundup2(socksize, sizeof(long)); ifasize = sizeof(*ifa) + 2 * socksize; ifa = ifa_alloc(ifasize, M_WAITOK); sdl = (struct sockaddr_dl *)(ifa + 1); sdl->sdl_len = socksize; sdl->sdl_family = AF_LINK; bcopy(ifp->if_xname, sdl->sdl_data, namelen); sdl->sdl_nlen = namelen; sdl->sdl_index = ifp->if_index; sdl->sdl_type = ifp->if_type; ifp->if_addr = ifa; ifa->ifa_ifp = ifp; ifa->ifa_rtrequest = link_rtrequest; ifa->ifa_addr = (struct sockaddr *)sdl; sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); ifa->ifa_netmask = (struct sockaddr *)sdl; sdl->sdl_len = masklen; while (namelen != 0) sdl->sdl_data[--namelen] = 0xff; TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link); /* Reliably crash if used uninitialized. */ ifp->if_broadcastaddr = NULL; #if defined(INET) || defined(INET6) /* Use defaults for TSO, if nothing is set */ if (ifp->if_hw_tsomax == 0 && ifp->if_hw_tsomaxsegcount == 0 && ifp->if_hw_tsomaxsegsize == 0) { /* * The TSO defaults needs to be such that an * NFS mbuf list of 35 mbufs totalling just * below 64K works and that a chain of mbufs * can be defragged into at most 32 segments: */ ifp->if_hw_tsomax = min(IP_MAXPACKET, (32 * MCLBYTES) - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN)); ifp->if_hw_tsomaxsegcount = 35; ifp->if_hw_tsomaxsegsize = 2048; /* 2K */ /* XXX some drivers set IFCAP_TSO after ethernet attach */ if (ifp->if_capabilities & IFCAP_TSO) { if_printf(ifp, "Using defaults for TSO: %u/%u/%u\n", ifp->if_hw_tsomax, ifp->if_hw_tsomaxsegcount, ifp->if_hw_tsomaxsegsize); } } #endif } #ifdef VIMAGE else { /* * Update the interface index in the link layer address * of the interface. */ for (ifa = ifp->if_addr; ifa != NULL; ifa = TAILQ_NEXT(ifa, ifa_link)) { if (ifa->ifa_addr->sa_family == AF_LINK) { sdl = (struct sockaddr_dl *)ifa->ifa_addr; sdl->sdl_index = ifp->if_index; } } } #endif IFNET_WLOCK(); TAILQ_INSERT_TAIL(&V_ifnet, ifp, if_link); #ifdef VIMAGE curvnet->vnet_ifcnt++; #endif IFNET_WUNLOCK(); if (domain_init_status >= 2) if_attachdomain1(ifp); EVENTHANDLER_INVOKE(ifnet_arrival_event, ifp); if (IS_DEFAULT_VNET(curvnet)) devctl_notify("IFNET", ifp->if_xname, "ATTACH", NULL); /* Announce the interface. */ rt_ifannouncemsg(ifp, IFAN_ARRIVAL); } static void if_attachdomain(void *dummy) { struct ifnet *ifp; TAILQ_FOREACH(ifp, &V_ifnet, if_link) if_attachdomain1(ifp); } SYSINIT(domainifattach, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_SECOND, if_attachdomain, NULL); static void if_attachdomain1(struct ifnet *ifp) { struct domain *dp; /* * Since dp->dom_ifattach calls malloc() with M_WAITOK, we * cannot lock ifp->if_afdata initialization, entirely. */ if (IF_AFDATA_TRYLOCK(ifp) == 0) return; if (ifp->if_afdata_initialized >= domain_init_status) { IF_AFDATA_UNLOCK(ifp); log(LOG_WARNING, "%s called more than once on %s\n", __func__, ifp->if_xname); return; } ifp->if_afdata_initialized = domain_init_status; IF_AFDATA_UNLOCK(ifp); /* address family dependent data region */ bzero(ifp->if_afdata, sizeof(ifp->if_afdata)); for (dp = domains; dp; dp = dp->dom_next) { if (dp->dom_ifattach) ifp->if_afdata[dp->dom_family] = (*dp->dom_ifattach)(ifp); } } /* * Remove any unicast or broadcast network addresses from an interface. */ void if_purgeaddrs(struct ifnet *ifp) { struct ifaddr *ifa, *next; TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) { if (ifa->ifa_addr->sa_family == AF_LINK) continue; #ifdef INET /* XXX: Ugly!! ad hoc just for INET */ if (ifa->ifa_addr->sa_family == AF_INET) { struct ifaliasreq ifr; bzero(&ifr, sizeof(ifr)); ifr.ifra_addr = *ifa->ifa_addr; if (ifa->ifa_dstaddr) ifr.ifra_broadaddr = *ifa->ifa_dstaddr; if (in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr, ifp, NULL) == 0) continue; } #endif /* INET */ #ifdef INET6 if (ifa->ifa_addr->sa_family == AF_INET6) { in6_purgeaddr(ifa); /* ifp_addrhead is already updated */ continue; } #endif /* INET6 */ TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link); ifa_free(ifa); } } /* * Remove any multicast network addresses from an interface when an ifnet * is going away. */ static void if_purgemaddrs(struct ifnet *ifp) { struct ifmultiaddr *ifma; struct ifmultiaddr *next; IF_ADDR_WLOCK(ifp); TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next) if_delmulti_locked(ifp, ifma, 1); IF_ADDR_WUNLOCK(ifp); } /* * Detach an interface, removing it from the list of "active" interfaces. * If vmove flag is set on entry to if_detach_internal(), perform only a * limited subset of cleanup tasks, given that we are moving an ifnet from * one vnet to another, where it must be fully operational. * * XXXRW: There are some significant questions about event ordering, and * how to prevent things from starting to use the interface during detach. */ void if_detach(struct ifnet *ifp) { CURVNET_SET_QUIET(ifp->if_vnet); if_detach_internal(ifp, 0, NULL); CURVNET_RESTORE(); } static void if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp) { struct ifaddr *ifa; int i; struct domain *dp; struct ifnet *iter; int found = 0; IFNET_WLOCK(); TAILQ_FOREACH(iter, &V_ifnet, if_link) if (iter == ifp) { TAILQ_REMOVE(&V_ifnet, ifp, if_link); found = 1; break; } #ifdef VIMAGE if (found) curvnet->vnet_ifcnt--; #endif IFNET_WUNLOCK(); if (!found) { if (vmove) panic("%s: ifp=%p not on the ifnet tailq %p", __func__, ifp, &V_ifnet); else return; /* XXX this should panic as well? */ } /* Check if this is a cloned interface or not. */ if (vmove && ifcp != NULL) *ifcp = if_clone_findifc(ifp); /* * Remove/wait for pending events. */ taskqueue_drain(taskqueue_swi, &ifp->if_linktask); /* * Remove routes and flush queues. */ if_down(ifp); #ifdef ALTQ if (ALTQ_IS_ENABLED(&ifp->if_snd)) altq_disable(&ifp->if_snd); if (ALTQ_IS_ATTACHED(&ifp->if_snd)) altq_detach(&ifp->if_snd); #endif if_purgeaddrs(ifp); #ifdef INET in_ifdetach(ifp); #endif #ifdef INET6 /* * Remove all IPv6 kernel structs related to ifp. This should be done * before removing routing entries below, since IPv6 interface direct * routes are expected to be removed by the IPv6-specific kernel API. * Otherwise, the kernel will detect some inconsistency and bark it. */ in6_ifdetach(ifp); #endif if_purgemaddrs(ifp); /* Announce that the interface is gone. */ rt_ifannouncemsg(ifp, IFAN_DEPARTURE); EVENTHANDLER_INVOKE(ifnet_departure_event, ifp); if (IS_DEFAULT_VNET(curvnet)) devctl_notify("IFNET", ifp->if_xname, "DETACH", NULL); if (!vmove) { /* * Prevent further calls into the device driver via ifnet. */ if_dead(ifp); /* * Remove link ifaddr pointer and maybe decrement if_index. * Clean up all addresses. */ ifp->if_addr = NULL; /* We can now free link ifaddr. */ if (!TAILQ_EMPTY(&ifp->if_addrhead)) { ifa = TAILQ_FIRST(&ifp->if_addrhead); TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link); ifa_free(ifa); } } rt_flushifroutes(ifp); if_delgroups(ifp); /* * We cannot hold the lock over dom_ifdetach calls as they might * sleep, for example trying to drain a callout, thus open up the * theoretical race with re-attaching. */ IF_AFDATA_LOCK(ifp); i = ifp->if_afdata_initialized; ifp->if_afdata_initialized = 0; IF_AFDATA_UNLOCK(ifp); for (dp = domains; i > 0 && dp; dp = dp->dom_next) { if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family]) (*dp->dom_ifdetach)(ifp, ifp->if_afdata[dp->dom_family]); } } #ifdef VIMAGE /* * if_vmove() performs a limited version of if_detach() in current * vnet and if_attach()es the ifnet to the vnet specified as 2nd arg. * An attempt is made to shrink if_index in current vnet, find an * unused if_index in target vnet and calls if_grow() if necessary, * and finally find an unused if_xname for the target vnet. */ void if_vmove(struct ifnet *ifp, struct vnet *new_vnet) { struct if_clone *ifc; /* * Detach from current vnet, but preserve LLADDR info, do not * mark as dead etc. so that the ifnet can be reattached later. */ if_detach_internal(ifp, 1, &ifc); /* * Unlink the ifnet from ifindex_table[] in current vnet, and shrink * the if_index for that vnet if possible. * * NOTE: IFNET_WLOCK/IFNET_WUNLOCK() are assumed to be unvirtualized, * or we'd lock on one vnet and unlock on another. */ IFNET_WLOCK(); ifindex_free_locked(ifp->if_index); IFNET_WUNLOCK(); /* * Perform interface-specific reassignment tasks, if provided by * the driver. */ if (ifp->if_reassign != NULL) ifp->if_reassign(ifp, new_vnet, NULL); /* * Switch to the context of the target vnet. */ CURVNET_SET_QUIET(new_vnet); IFNET_WLOCK(); ifp->if_index = ifindex_alloc(); ifnet_setbyindex_locked(ifp->if_index, ifp); IFNET_WUNLOCK(); if_attach_internal(ifp, 1, ifc); CURVNET_RESTORE(); } /* * Move an ifnet to or from another child prison/vnet, specified by the jail id. */ static int if_vmove_loan(struct thread *td, struct ifnet *ifp, char *ifname, int jid) { struct prison *pr; struct ifnet *difp; /* Try to find the prison within our visibility. */ sx_slock(&allprison_lock); pr = prison_find_child(td->td_ucred->cr_prison, jid); sx_sunlock(&allprison_lock); if (pr == NULL) return (ENXIO); prison_hold_locked(pr); mtx_unlock(&pr->pr_mtx); /* Do not try to move the iface from and to the same prison. */ if (pr->pr_vnet == ifp->if_vnet) { prison_free(pr); return (EEXIST); } /* Make sure the named iface does not exists in the dst. prison/vnet. */ /* XXX Lock interfaces to avoid races. */ CURVNET_SET_QUIET(pr->pr_vnet); difp = ifunit(ifname); CURVNET_RESTORE(); if (difp != NULL) { prison_free(pr); return (EEXIST); } /* Move the interface into the child jail/vnet. */ if_vmove(ifp, pr->pr_vnet); /* Report the new if_xname back to the userland. */ sprintf(ifname, "%s", ifp->if_xname); prison_free(pr); return (0); } static int if_vmove_reclaim(struct thread *td, char *ifname, int jid) { struct prison *pr; struct vnet *vnet_dst; struct ifnet *ifp; /* Try to find the prison within our visibility. */ sx_slock(&allprison_lock); pr = prison_find_child(td->td_ucred->cr_prison, jid); sx_sunlock(&allprison_lock); if (pr == NULL) return (ENXIO); prison_hold_locked(pr); mtx_unlock(&pr->pr_mtx); /* Make sure the named iface exists in the source prison/vnet. */ CURVNET_SET(pr->pr_vnet); ifp = ifunit(ifname); /* XXX Lock to avoid races. */ if (ifp == NULL) { CURVNET_RESTORE(); prison_free(pr); return (ENXIO); } /* Do not try to move the iface from and to the same prison. */ vnet_dst = TD_TO_VNET(td); if (vnet_dst == ifp->if_vnet) { CURVNET_RESTORE(); prison_free(pr); return (EEXIST); } /* Get interface back from child jail/vnet. */ if_vmove(ifp, vnet_dst); CURVNET_RESTORE(); /* Report the new if_xname back to the userland. */ sprintf(ifname, "%s", ifp->if_xname); prison_free(pr); return (0); } #endif /* VIMAGE */ /* * Add a group to an interface */ int if_addgroup(struct ifnet *ifp, const char *groupname) { struct ifg_list *ifgl; struct ifg_group *ifg = NULL; struct ifg_member *ifgm; int new = 0; if (groupname[0] && groupname[strlen(groupname) - 1] >= '0' && groupname[strlen(groupname) - 1] <= '9') return (EINVAL); IFNET_WLOCK(); TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) if (!strcmp(ifgl->ifgl_group->ifg_group, groupname)) { IFNET_WUNLOCK(); return (EEXIST); } if ((ifgl = (struct ifg_list *)malloc(sizeof(struct ifg_list), M_TEMP, M_NOWAIT)) == NULL) { IFNET_WUNLOCK(); return (ENOMEM); } if ((ifgm = (struct ifg_member *)malloc(sizeof(struct ifg_member), M_TEMP, M_NOWAIT)) == NULL) { free(ifgl, M_TEMP); IFNET_WUNLOCK(); return (ENOMEM); } TAILQ_FOREACH(ifg, &V_ifg_head, ifg_next) if (!strcmp(ifg->ifg_group, groupname)) break; if (ifg == NULL) { if ((ifg = (struct ifg_group *)malloc(sizeof(struct ifg_group), M_TEMP, M_NOWAIT)) == NULL) { free(ifgl, M_TEMP); free(ifgm, M_TEMP); IFNET_WUNLOCK(); return (ENOMEM); } strlcpy(ifg->ifg_group, groupname, sizeof(ifg->ifg_group)); ifg->ifg_refcnt = 0; TAILQ_INIT(&ifg->ifg_members); TAILQ_INSERT_TAIL(&V_ifg_head, ifg, ifg_next); new = 1; } ifg->ifg_refcnt++; ifgl->ifgl_group = ifg; ifgm->ifgm_ifp = ifp; IF_ADDR_WLOCK(ifp); TAILQ_INSERT_TAIL(&ifg->ifg_members, ifgm, ifgm_next); TAILQ_INSERT_TAIL(&ifp->if_groups, ifgl, ifgl_next); IF_ADDR_WUNLOCK(ifp); IFNET_WUNLOCK(); if (new) EVENTHANDLER_INVOKE(group_attach_event, ifg); EVENTHANDLER_INVOKE(group_change_event, groupname); return (0); } /* * Remove a group from an interface */ int if_delgroup(struct ifnet *ifp, const char *groupname) { struct ifg_list *ifgl; struct ifg_member *ifgm; IFNET_WLOCK(); TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) if (!strcmp(ifgl->ifgl_group->ifg_group, groupname)) break; if (ifgl == NULL) { IFNET_WUNLOCK(); return (ENOENT); } IF_ADDR_WLOCK(ifp); TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next); IF_ADDR_WUNLOCK(ifp); TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next) if (ifgm->ifgm_ifp == ifp) break; if (ifgm != NULL) { TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifgm_next); free(ifgm, M_TEMP); } if (--ifgl->ifgl_group->ifg_refcnt == 0) { TAILQ_REMOVE(&V_ifg_head, ifgl->ifgl_group, ifg_next); IFNET_WUNLOCK(); EVENTHANDLER_INVOKE(group_detach_event, ifgl->ifgl_group); free(ifgl->ifgl_group, M_TEMP); } else IFNET_WUNLOCK(); free(ifgl, M_TEMP); EVENTHANDLER_INVOKE(group_change_event, groupname); return (0); } /* * Remove an interface from all groups */ static void if_delgroups(struct ifnet *ifp) { struct ifg_list *ifgl; struct ifg_member *ifgm; char groupname[IFNAMSIZ]; IFNET_WLOCK(); while (!TAILQ_EMPTY(&ifp->if_groups)) { ifgl = TAILQ_FIRST(&ifp->if_groups); strlcpy(groupname, ifgl->ifgl_group->ifg_group, IFNAMSIZ); IF_ADDR_WLOCK(ifp); TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next); IF_ADDR_WUNLOCK(ifp); TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next) if (ifgm->ifgm_ifp == ifp) break; if (ifgm != NULL) { TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifgm_next); free(ifgm, M_TEMP); } if (--ifgl->ifgl_group->ifg_refcnt == 0) { TAILQ_REMOVE(&V_ifg_head, ifgl->ifgl_group, ifg_next); IFNET_WUNLOCK(); EVENTHANDLER_INVOKE(group_detach_event, ifgl->ifgl_group); free(ifgl->ifgl_group, M_TEMP); } else IFNET_WUNLOCK(); free(ifgl, M_TEMP); EVENTHANDLER_INVOKE(group_change_event, groupname); IFNET_WLOCK(); } IFNET_WUNLOCK(); } /* * Stores all groups from an interface in memory pointed * to by data */ static int if_getgroup(struct ifgroupreq *data, struct ifnet *ifp) { int len, error; struct ifg_list *ifgl; struct ifg_req ifgrq, *ifgp; struct ifgroupreq *ifgr = data; if (ifgr->ifgr_len == 0) { IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) ifgr->ifgr_len += sizeof(struct ifg_req); IF_ADDR_RUNLOCK(ifp); return (0); } len = ifgr->ifgr_len; ifgp = ifgr->ifgr_groups; /* XXX: wire */ IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) { if (len < sizeof(ifgrq)) { IF_ADDR_RUNLOCK(ifp); return (EINVAL); } bzero(&ifgrq, sizeof ifgrq); strlcpy(ifgrq.ifgrq_group, ifgl->ifgl_group->ifg_group, sizeof(ifgrq.ifgrq_group)); if ((error = copyout(&ifgrq, ifgp, sizeof(struct ifg_req)))) { IF_ADDR_RUNLOCK(ifp); return (error); } len -= sizeof(ifgrq); ifgp++; } IF_ADDR_RUNLOCK(ifp); return (0); } /* * Stores all members of a group in memory pointed to by data */ static int if_getgroupmembers(struct ifgroupreq *data) { struct ifgroupreq *ifgr = data; struct ifg_group *ifg; struct ifg_member *ifgm; struct ifg_req ifgrq, *ifgp; int len, error; IFNET_RLOCK(); TAILQ_FOREACH(ifg, &V_ifg_head, ifg_next) if (!strcmp(ifg->ifg_group, ifgr->ifgr_name)) break; if (ifg == NULL) { IFNET_RUNLOCK(); return (ENOENT); } if (ifgr->ifgr_len == 0) { TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) ifgr->ifgr_len += sizeof(ifgrq); IFNET_RUNLOCK(); return (0); } len = ifgr->ifgr_len; ifgp = ifgr->ifgr_groups; TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) { if (len < sizeof(ifgrq)) { IFNET_RUNLOCK(); return (EINVAL); } bzero(&ifgrq, sizeof ifgrq); strlcpy(ifgrq.ifgrq_member, ifgm->ifgm_ifp->if_xname, sizeof(ifgrq.ifgrq_member)); if ((error = copyout(&ifgrq, ifgp, sizeof(struct ifg_req)))) { IFNET_RUNLOCK(); return (error); } len -= sizeof(ifgrq); ifgp++; } IFNET_RUNLOCK(); return (0); } /* * Return counter values from counter(9)s stored in ifnet. */ uint64_t if_get_counter_default(struct ifnet *ifp, ift_counter cnt) { KASSERT(cnt < IFCOUNTERS, ("%s: invalid cnt %d", __func__, cnt)); return (counter_u64_fetch(ifp->if_counters[cnt])); } /* * Increase an ifnet counter. Usually used for counters shared * between the stack and a driver, but function supports them all. */ void if_inc_counter(struct ifnet *ifp, ift_counter cnt, int64_t inc) { KASSERT(cnt < IFCOUNTERS, ("%s: invalid cnt %d", __func__, cnt)); counter_u64_add(ifp->if_counters[cnt], inc); } /* * Copy data from ifnet to userland API structure if_data. */ void if_data_copy(struct ifnet *ifp, struct if_data *ifd) { ifd->ifi_type = ifp->if_type; ifd->ifi_physical = 0; ifd->ifi_addrlen = ifp->if_addrlen; ifd->ifi_hdrlen = ifp->if_hdrlen; ifd->ifi_link_state = ifp->if_link_state; ifd->ifi_vhid = 0; ifd->ifi_datalen = sizeof(struct if_data); ifd->ifi_mtu = ifp->if_mtu; ifd->ifi_metric = ifp->if_metric; ifd->ifi_baudrate = ifp->if_baudrate; ifd->ifi_hwassist = ifp->if_hwassist; ifd->ifi_epoch = ifp->if_epoch; ifd->ifi_lastchange = ifp->if_lastchange; ifd->ifi_ipackets = ifp->if_get_counter(ifp, IFCOUNTER_IPACKETS); ifd->ifi_ierrors = ifp->if_get_counter(ifp, IFCOUNTER_IERRORS); ifd->ifi_opackets = ifp->if_get_counter(ifp, IFCOUNTER_OPACKETS); ifd->ifi_oerrors = ifp->if_get_counter(ifp, IFCOUNTER_OERRORS); ifd->ifi_collisions = ifp->if_get_counter(ifp, IFCOUNTER_COLLISIONS); ifd->ifi_ibytes = ifp->if_get_counter(ifp, IFCOUNTER_IBYTES); ifd->ifi_obytes = ifp->if_get_counter(ifp, IFCOUNTER_OBYTES); ifd->ifi_imcasts = ifp->if_get_counter(ifp, IFCOUNTER_IMCASTS); ifd->ifi_omcasts = ifp->if_get_counter(ifp, IFCOUNTER_OMCASTS); ifd->ifi_iqdrops = ifp->if_get_counter(ifp, IFCOUNTER_IQDROPS); ifd->ifi_oqdrops = ifp->if_get_counter(ifp, IFCOUNTER_OQDROPS); ifd->ifi_noproto = ifp->if_get_counter(ifp, IFCOUNTER_NOPROTO); } /* * Wrapper functions for struct ifnet address list locking macros. These are * used by kernel modules to avoid encoding programming interface or binary * interface assumptions that may be violated when kernel-internal locking * approaches change. */ void if_addr_rlock(struct ifnet *ifp) { IF_ADDR_RLOCK(ifp); } void if_addr_runlock(struct ifnet *ifp) { IF_ADDR_RUNLOCK(ifp); } void if_maddr_rlock(if_t ifp) { IF_ADDR_RLOCK((struct ifnet *)ifp); } void if_maddr_runlock(if_t ifp) { IF_ADDR_RUNLOCK((struct ifnet *)ifp); } /* * Initialization, destruction and refcounting functions for ifaddrs. */ struct ifaddr * ifa_alloc(size_t size, int flags) { struct ifaddr *ifa; KASSERT(size >= sizeof(struct ifaddr), ("%s: invalid size %zu", __func__, size)); ifa = malloc(size, M_IFADDR, M_ZERO | flags); if (ifa == NULL) return (NULL); if ((ifa->ifa_opackets = counter_u64_alloc(flags)) == NULL) goto fail; if ((ifa->ifa_ipackets = counter_u64_alloc(flags)) == NULL) goto fail; if ((ifa->ifa_obytes = counter_u64_alloc(flags)) == NULL) goto fail; if ((ifa->ifa_ibytes = counter_u64_alloc(flags)) == NULL) goto fail; refcount_init(&ifa->ifa_refcnt, 1); return (ifa); fail: /* free(NULL) is okay */ counter_u64_free(ifa->ifa_opackets); counter_u64_free(ifa->ifa_ipackets); counter_u64_free(ifa->ifa_obytes); counter_u64_free(ifa->ifa_ibytes); free(ifa, M_IFADDR); return (NULL); } void ifa_ref(struct ifaddr *ifa) { refcount_acquire(&ifa->ifa_refcnt); } void ifa_free(struct ifaddr *ifa) { if (refcount_release(&ifa->ifa_refcnt)) { counter_u64_free(ifa->ifa_opackets); counter_u64_free(ifa->ifa_ipackets); counter_u64_free(ifa->ifa_obytes); counter_u64_free(ifa->ifa_ibytes); free(ifa, M_IFADDR); } } static int ifa_maintain_loopback_route(int cmd, const char *otype, struct ifaddr *ifa, struct sockaddr *ia) { int error; struct rt_addrinfo info; struct sockaddr_dl null_sdl; struct ifnet *ifp; ifp = ifa->ifa_ifp; bzero(&info, sizeof(info)); if (cmd != RTM_DELETE) info.rti_ifp = V_loif; info.rti_flags = ifa->ifa_flags | RTF_HOST | RTF_STATIC; info.rti_info[RTAX_DST] = ia; info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&null_sdl; link_init_sdl(ifp, (struct sockaddr *)&null_sdl, ifp->if_type); error = rtrequest1_fib(cmd, &info, NULL, ifp->if_fib); if (error != 0) log(LOG_DEBUG, "%s: %s failed for interface %s: %u\n", __func__, otype, if_name(ifp), error); return (error); } int ifa_add_loopback_route(struct ifaddr *ifa, struct sockaddr *ia) { return (ifa_maintain_loopback_route(RTM_ADD, "insertion", ifa, ia)); } int ifa_del_loopback_route(struct ifaddr *ifa, struct sockaddr *ia) { return (ifa_maintain_loopback_route(RTM_DELETE, "deletion", ifa, ia)); } int ifa_switch_loopback_route(struct ifaddr *ifa, struct sockaddr *ia) { return (ifa_maintain_loopback_route(RTM_CHANGE, "switch", ifa, ia)); } /* * XXX: Because sockaddr_dl has deeper structure than the sockaddr * structs used to represent other address families, it is necessary * to perform a different comparison. */ #define sa_dl_equal(a1, a2) \ ((((const struct sockaddr_dl *)(a1))->sdl_len == \ ((const struct sockaddr_dl *)(a2))->sdl_len) && \ (bcmp(CLLADDR((const struct sockaddr_dl *)(a1)), \ CLLADDR((const struct sockaddr_dl *)(a2)), \ ((const struct sockaddr_dl *)(a1))->sdl_alen) == 0)) /* * Locate an interface based on a complete address. */ /*ARGSUSED*/ static struct ifaddr * ifa_ifwithaddr_internal(const struct sockaddr *addr, int getref) { struct ifnet *ifp; struct ifaddr *ifa; IFNET_RLOCK_NOSLEEP(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != addr->sa_family) continue; if (sa_equal(addr, ifa->ifa_addr)) { if (getref) ifa_ref(ifa); IF_ADDR_RUNLOCK(ifp); goto done; } /* IP6 doesn't have broadcast */ if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && ifa->ifa_broadaddr->sa_len != 0 && sa_equal(ifa->ifa_broadaddr, addr)) { if (getref) ifa_ref(ifa); IF_ADDR_RUNLOCK(ifp); goto done; } } IF_ADDR_RUNLOCK(ifp); } ifa = NULL; done: IFNET_RUNLOCK_NOSLEEP(); return (ifa); } struct ifaddr * ifa_ifwithaddr(const struct sockaddr *addr) { return (ifa_ifwithaddr_internal(addr, 1)); } int ifa_ifwithaddr_check(const struct sockaddr *addr) { return (ifa_ifwithaddr_internal(addr, 0) != NULL); } /* * Locate an interface based on the broadcast address. */ /* ARGSUSED */ struct ifaddr * ifa_ifwithbroadaddr(const struct sockaddr *addr, int fibnum) { struct ifnet *ifp; struct ifaddr *ifa; IFNET_RLOCK_NOSLEEP(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { if ((fibnum != RT_ALL_FIBS) && (ifp->if_fib != fibnum)) continue; IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != addr->sa_family) continue; if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && ifa->ifa_broadaddr->sa_len != 0 && sa_equal(ifa->ifa_broadaddr, addr)) { ifa_ref(ifa); IF_ADDR_RUNLOCK(ifp); goto done; } } IF_ADDR_RUNLOCK(ifp); } ifa = NULL; done: IFNET_RUNLOCK_NOSLEEP(); return (ifa); } /* * Locate the point to point interface with a given destination address. */ /*ARGSUSED*/ struct ifaddr * ifa_ifwithdstaddr(const struct sockaddr *addr, int fibnum) { struct ifnet *ifp; struct ifaddr *ifa; IFNET_RLOCK_NOSLEEP(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { if ((ifp->if_flags & IFF_POINTOPOINT) == 0) continue; if ((fibnum != RT_ALL_FIBS) && (ifp->if_fib != fibnum)) continue; IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != addr->sa_family) continue; if (ifa->ifa_dstaddr != NULL && sa_equal(addr, ifa->ifa_dstaddr)) { ifa_ref(ifa); IF_ADDR_RUNLOCK(ifp); goto done; } } IF_ADDR_RUNLOCK(ifp); } ifa = NULL; done: IFNET_RUNLOCK_NOSLEEP(); return (ifa); } /* * Find an interface on a specific network. If many, choice * is most specific found. */ struct ifaddr * ifa_ifwithnet(const struct sockaddr *addr, int ignore_ptp, int fibnum) { struct ifnet *ifp; struct ifaddr *ifa; struct ifaddr *ifa_maybe = NULL; u_int af = addr->sa_family; const char *addr_data = addr->sa_data, *cplim; /* * AF_LINK addresses can be looked up directly by their index number, * so do that if we can. */ if (af == AF_LINK) { const struct sockaddr_dl *sdl = (const struct sockaddr_dl *)addr; if (sdl->sdl_index && sdl->sdl_index <= V_if_index) return (ifaddr_byindex(sdl->sdl_index)); } /* * Scan though each interface, looking for ones that have addresses * in this address family and the requested fib. Maintain a reference * on ifa_maybe once we find one, as we release the IF_ADDR_RLOCK() that * kept it stable when we move onto the next interface. */ IFNET_RLOCK_NOSLEEP(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { if ((fibnum != RT_ALL_FIBS) && (ifp->if_fib != fibnum)) continue; IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { const char *cp, *cp2, *cp3; if (ifa->ifa_addr->sa_family != af) next: continue; if (af == AF_INET && ifp->if_flags & IFF_POINTOPOINT && !ignore_ptp) { /* * This is a bit broken as it doesn't * take into account that the remote end may * be a single node in the network we are * looking for. * The trouble is that we don't know the * netmask for the remote end. */ if (ifa->ifa_dstaddr != NULL && sa_equal(addr, ifa->ifa_dstaddr)) { ifa_ref(ifa); IF_ADDR_RUNLOCK(ifp); goto done; } } else { /* * Scan all the bits in the ifa's address. * If a bit dissagrees with what we are * looking for, mask it with the netmask * to see if it really matters. * (A byte at a time) */ if (ifa->ifa_netmask == 0) continue; cp = addr_data; cp2 = ifa->ifa_addr->sa_data; cp3 = ifa->ifa_netmask->sa_data; cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; while (cp3 < cplim) if ((*cp++ ^ *cp2++) & *cp3++) goto next; /* next address! */ /* * If the netmask of what we just found * is more specific than what we had before * (if we had one), or if the virtual status * of new prefix is better than of the old one, * then remember the new one before continuing * to search for an even better one. */ if (ifa_maybe == NULL || ifa_preferred(ifa_maybe, ifa) || rn_refines((caddr_t)ifa->ifa_netmask, (caddr_t)ifa_maybe->ifa_netmask)) { if (ifa_maybe != NULL) ifa_free(ifa_maybe); ifa_maybe = ifa; ifa_ref(ifa_maybe); } } } IF_ADDR_RUNLOCK(ifp); } ifa = ifa_maybe; ifa_maybe = NULL; done: IFNET_RUNLOCK_NOSLEEP(); if (ifa_maybe != NULL) ifa_free(ifa_maybe); return (ifa); } /* * Find an interface address specific to an interface best matching * a given address. */ struct ifaddr * ifaof_ifpforaddr(const struct sockaddr *addr, struct ifnet *ifp) { struct ifaddr *ifa; const char *cp, *cp2, *cp3; char *cplim; struct ifaddr *ifa_maybe = NULL; u_int af = addr->sa_family; if (af >= AF_MAX) return (NULL); IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != af) continue; if (ifa_maybe == NULL) ifa_maybe = ifa; if (ifa->ifa_netmask == 0) { if (sa_equal(addr, ifa->ifa_addr) || (ifa->ifa_dstaddr && sa_equal(addr, ifa->ifa_dstaddr))) goto done; continue; } if (ifp->if_flags & IFF_POINTOPOINT) { if (sa_equal(addr, ifa->ifa_dstaddr)) goto done; } else { cp = addr->sa_data; cp2 = ifa->ifa_addr->sa_data; cp3 = ifa->ifa_netmask->sa_data; cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; for (; cp3 < cplim; cp3++) if ((*cp++ ^ *cp2++) & *cp3) break; if (cp3 == cplim) goto done; } } ifa = ifa_maybe; done: if (ifa != NULL) ifa_ref(ifa); IF_ADDR_RUNLOCK(ifp); return (ifa); } /* * See whether new ifa is better than current one: * 1) A non-virtual one is preferred over virtual. * 2) A virtual in master state preferred over any other state. * * Used in several address selecting functions. */ int ifa_preferred(struct ifaddr *cur, struct ifaddr *next) { return (cur->ifa_carp && (!next->ifa_carp || ((*carp_master_p)(next) && !(*carp_master_p)(cur)))); } #include /* * Default action when installing a route with a Link Level gateway. * Lookup an appropriate real ifa to point to. * This should be moved to /sys/net/link.c eventually. */ static void link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info) { struct ifaddr *ifa, *oifa; struct sockaddr *dst; struct ifnet *ifp; if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) return; ifa = ifaof_ifpforaddr(dst, ifp); if (ifa) { oifa = rt->rt_ifa; rt->rt_ifa = ifa; ifa_free(oifa); if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) ifa->ifa_rtrequest(cmd, rt, info); } } struct sockaddr_dl * link_alloc_sdl(size_t size, int flags) { return (malloc(size, M_TEMP, flags)); } void link_free_sdl(struct sockaddr *sa) { free(sa, M_TEMP); } /* * Fills in given sdl with interface basic info. * Returns pointer to filled sdl. */ struct sockaddr_dl * link_init_sdl(struct ifnet *ifp, struct sockaddr *paddr, u_char iftype) { struct sockaddr_dl *sdl; sdl = (struct sockaddr_dl *)paddr; memset(sdl, 0, sizeof(struct sockaddr_dl)); sdl->sdl_len = sizeof(struct sockaddr_dl); sdl->sdl_family = AF_LINK; sdl->sdl_index = ifp->if_index; sdl->sdl_type = iftype; return (sdl); } /* * Mark an interface down and notify protocols of * the transition. */ static void if_unroute(struct ifnet *ifp, int flag, int fam) { struct ifaddr *ifa; KASSERT(flag == IFF_UP, ("if_unroute: flag != IFF_UP")); ifp->if_flags &= ~flag; getmicrotime(&ifp->if_lastchange); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family)) pfctlinput(PRC_IFDOWN, ifa->ifa_addr); ifp->if_qflush(ifp); if (ifp->if_carp) (*carp_linkstate_p)(ifp); - if (ifp->if_lagg) - (*lagg_linkstate_p)(ifp); rt_ifmsg(ifp); } /* * Mark an interface up and notify protocols of * the transition. */ static void if_route(struct ifnet *ifp, int flag, int fam) { struct ifaddr *ifa; KASSERT(flag == IFF_UP, ("if_route: flag != IFF_UP")); ifp->if_flags |= flag; getmicrotime(&ifp->if_lastchange); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family)) pfctlinput(PRC_IFUP, ifa->ifa_addr); if (ifp->if_carp) (*carp_linkstate_p)(ifp); - if (ifp->if_lagg) - (*lagg_linkstate_p)(ifp); rt_ifmsg(ifp); #ifdef INET6 in6_if_up(ifp); #endif } void (*vlan_link_state_p)(struct ifnet *); /* XXX: private from if_vlan */ void (*vlan_trunk_cap_p)(struct ifnet *); /* XXX: private from if_vlan */ struct ifnet *(*vlan_trunkdev_p)(struct ifnet *); struct ifnet *(*vlan_devat_p)(struct ifnet *, uint16_t); int (*vlan_tag_p)(struct ifnet *, uint16_t *); int (*vlan_setcookie_p)(struct ifnet *, void *); void *(*vlan_cookie_p)(struct ifnet *); -void -if_link_state_change(struct ifnet *ifp, int link_state) -{ - - return if_link_state_change_cond(ifp, link_state, 0); -} - /* * Handle a change in the interface link state. To avoid LORs * between driver lock and upper layer locks, as well as possible * recursions, we post event to taskqueue, and all job * is done in static do_link_state_change(). - * - * If the current link state matches link_state and force isn't - * specified no action is taken. */ void -if_link_state_change_cond(struct ifnet *ifp, int link_state, int force) +if_link_state_change(struct ifnet *ifp, int link_state) { - - if (ifp->if_link_state == link_state && !force) + /* Return if state hasn't changed. */ + if (ifp->if_link_state == link_state) return; ifp->if_link_state = link_state; taskqueue_enqueue(taskqueue_swi, &ifp->if_linktask); } static void do_link_state_change(void *arg, int pending) { struct ifnet *ifp = (struct ifnet *)arg; int link_state = ifp->if_link_state; CURVNET_SET(ifp->if_vnet); /* Notify that the link state has changed. */ rt_ifmsg(ifp); if (ifp->if_vlantrunk != NULL) (*vlan_link_state_p)(ifp); if ((ifp->if_type == IFT_ETHER || ifp->if_type == IFT_L2VLAN) && ifp->if_l2com != NULL) (*ng_ether_link_state_p)(ifp, link_state); if (ifp->if_carp) (*carp_linkstate_p)(ifp); if (ifp->if_bridge) (*bridge_linkstate_p)(ifp); if (ifp->if_lagg) - (*lagg_linkstate_p)(ifp); + (*lagg_linkstate_p)(ifp, link_state); if (IS_DEFAULT_VNET(curvnet)) devctl_notify("IFNET", ifp->if_xname, (link_state == LINK_STATE_UP) ? "LINK_UP" : "LINK_DOWN", NULL); if (pending > 1) if_printf(ifp, "%d link states coalesced\n", pending); if (log_link_state_change) log(LOG_NOTICE, "%s: link state changed to %s\n", ifp->if_xname, (link_state == LINK_STATE_UP) ? "UP" : "DOWN" ); EVENTHANDLER_INVOKE(ifnet_link_event, ifp, ifp->if_link_state); CURVNET_RESTORE(); } /* * Mark an interface down and notify protocols of * the transition. */ void if_down(struct ifnet *ifp) { if_unroute(ifp, IFF_UP, AF_UNSPEC); } /* * Mark an interface up and notify protocols of * the transition. */ void if_up(struct ifnet *ifp) { if_route(ifp, IFF_UP, AF_UNSPEC); } /* * Flush an interface queue. */ void if_qflush(struct ifnet *ifp) { struct mbuf *m, *n; struct ifaltq *ifq; ifq = &ifp->if_snd; IFQ_LOCK(ifq); #ifdef ALTQ if (ALTQ_IS_ENABLED(ifq)) ALTQ_PURGE(ifq); #endif n = ifq->ifq_head; while ((m = n) != 0) { n = m->m_nextpkt; m_freem(m); } ifq->ifq_head = 0; ifq->ifq_tail = 0; ifq->ifq_len = 0; IFQ_UNLOCK(ifq); } /* * Map interface name to interface structure pointer, with or without * returning a reference. */ struct ifnet * ifunit_ref(const char *name) { struct ifnet *ifp; IFNET_RLOCK_NOSLEEP(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { if (strncmp(name, ifp->if_xname, IFNAMSIZ) == 0 && !(ifp->if_flags & IFF_DYING)) break; } if (ifp != NULL) if_ref(ifp); IFNET_RUNLOCK_NOSLEEP(); return (ifp); } struct ifnet * ifunit(const char *name) { struct ifnet *ifp; IFNET_RLOCK_NOSLEEP(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { if (strncmp(name, ifp->if_xname, IFNAMSIZ) == 0) break; } IFNET_RUNLOCK_NOSLEEP(); return (ifp); } /* * Hardware specific interface ioctls. */ static int ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) { struct ifreq *ifr; int error = 0; int new_flags, temp_flags; size_t namelen, onamelen; size_t descrlen; char *descrbuf, *odescrbuf; char new_name[IFNAMSIZ]; struct ifaddr *ifa; struct sockaddr_dl *sdl; ifr = (struct ifreq *)data; switch (cmd) { case SIOCGIFINDEX: ifr->ifr_index = ifp->if_index; break; case SIOCGIFFLAGS: temp_flags = ifp->if_flags | ifp->if_drv_flags; ifr->ifr_flags = temp_flags & 0xffff; ifr->ifr_flagshigh = temp_flags >> 16; break; case SIOCGIFCAP: ifr->ifr_reqcap = ifp->if_capabilities; ifr->ifr_curcap = ifp->if_capenable; break; #ifdef MAC case SIOCGIFMAC: error = mac_ifnet_ioctl_get(td->td_ucred, ifr, ifp); break; #endif case SIOCGIFMETRIC: ifr->ifr_metric = ifp->if_metric; break; case SIOCGIFMTU: ifr->ifr_mtu = ifp->if_mtu; break; case SIOCGIFPHYS: /* XXXGL: did this ever worked? */ ifr->ifr_phys = 0; break; case SIOCGIFDESCR: error = 0; sx_slock(&ifdescr_sx); if (ifp->if_description == NULL) error = ENOMSG; else { /* space for terminating nul */ descrlen = strlen(ifp->if_description) + 1; if (ifr->ifr_buffer.length < descrlen) ifr->ifr_buffer.buffer = NULL; else error = copyout(ifp->if_description, ifr->ifr_buffer.buffer, descrlen); ifr->ifr_buffer.length = descrlen; } sx_sunlock(&ifdescr_sx); break; case SIOCSIFDESCR: error = priv_check(td, PRIV_NET_SETIFDESCR); if (error) return (error); /* * Copy only (length-1) bytes to make sure that * if_description is always nul terminated. The * length parameter is supposed to count the * terminating nul in. */ if (ifr->ifr_buffer.length > ifdescr_maxlen) return (ENAMETOOLONG); else if (ifr->ifr_buffer.length == 0) descrbuf = NULL; else { descrbuf = malloc(ifr->ifr_buffer.length, M_IFDESCR, M_WAITOK | M_ZERO); error = copyin(ifr->ifr_buffer.buffer, descrbuf, ifr->ifr_buffer.length - 1); if (error) { free(descrbuf, M_IFDESCR); break; } } sx_xlock(&ifdescr_sx); odescrbuf = ifp->if_description; ifp->if_description = descrbuf; sx_xunlock(&ifdescr_sx); getmicrotime(&ifp->if_lastchange); free(odescrbuf, M_IFDESCR); break; case SIOCGIFFIB: ifr->ifr_fib = ifp->if_fib; break; case SIOCSIFFIB: error = priv_check(td, PRIV_NET_SETIFFIB); if (error) return (error); if (ifr->ifr_fib >= rt_numfibs) return (EINVAL); ifp->if_fib = ifr->ifr_fib; break; case SIOCSIFFLAGS: error = priv_check(td, PRIV_NET_SETIFFLAGS); if (error) return (error); /* * Currently, no driver owned flags pass the IFF_CANTCHANGE * check, so we don't need special handling here yet. */ new_flags = (ifr->ifr_flags & 0xffff) | (ifr->ifr_flagshigh << 16); if (ifp->if_flags & IFF_UP && (new_flags & IFF_UP) == 0) { if_down(ifp); } else if (new_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { if_up(ifp); } /* See if permanently promiscuous mode bit is about to flip */ if ((ifp->if_flags ^ new_flags) & IFF_PPROMISC) { if (new_flags & IFF_PPROMISC) ifp->if_flags |= IFF_PROMISC; else if (ifp->if_pcount == 0) ifp->if_flags &= ~IFF_PROMISC; log(LOG_INFO, "%s: permanently promiscuous mode %s\n", ifp->if_xname, (new_flags & IFF_PPROMISC) ? "enabled" : "disabled"); } ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | (new_flags &~ IFF_CANTCHANGE); if (ifp->if_ioctl) { (void) (*ifp->if_ioctl)(ifp, cmd, data); } getmicrotime(&ifp->if_lastchange); break; case SIOCSIFCAP: error = priv_check(td, PRIV_NET_SETIFCAP); if (error) return (error); if (ifp->if_ioctl == NULL) return (EOPNOTSUPP); if (ifr->ifr_reqcap & ~ifp->if_capabilities) return (EINVAL); error = (*ifp->if_ioctl)(ifp, cmd, data); if (error == 0) getmicrotime(&ifp->if_lastchange); break; #ifdef MAC case SIOCSIFMAC: error = mac_ifnet_ioctl_set(td->td_ucred, ifr, ifp); break; #endif case SIOCSIFNAME: error = priv_check(td, PRIV_NET_SETIFNAME); if (error) return (error); error = copyinstr(ifr->ifr_data, new_name, IFNAMSIZ, NULL); if (error != 0) return (error); if (new_name[0] == '\0') return (EINVAL); if (ifunit(new_name) != NULL) return (EEXIST); /* * XXX: Locking. Nothing else seems to lock if_flags, * and there are numerous other races with the * ifunit() checks not being atomic with namespace * changes (renames, vmoves, if_attach, etc). */ ifp->if_flags |= IFF_RENAMING; /* Announce the departure of the interface. */ rt_ifannouncemsg(ifp, IFAN_DEPARTURE); EVENTHANDLER_INVOKE(ifnet_departure_event, ifp); log(LOG_INFO, "%s: changing name to '%s'\n", ifp->if_xname, new_name); IF_ADDR_WLOCK(ifp); strlcpy(ifp->if_xname, new_name, sizeof(ifp->if_xname)); ifa = ifp->if_addr; sdl = (struct sockaddr_dl *)ifa->ifa_addr; namelen = strlen(new_name); onamelen = sdl->sdl_nlen; /* * Move the address if needed. This is safe because we * allocate space for a name of length IFNAMSIZ when we * create this in if_attach(). */ if (namelen != onamelen) { bcopy(sdl->sdl_data + onamelen, sdl->sdl_data + namelen, sdl->sdl_alen); } bcopy(new_name, sdl->sdl_data, namelen); sdl->sdl_nlen = namelen; sdl = (struct sockaddr_dl *)ifa->ifa_netmask; bzero(sdl->sdl_data, onamelen); while (namelen != 0) sdl->sdl_data[--namelen] = 0xff; IF_ADDR_WUNLOCK(ifp); EVENTHANDLER_INVOKE(ifnet_arrival_event, ifp); /* Announce the return of the interface. */ rt_ifannouncemsg(ifp, IFAN_ARRIVAL); ifp->if_flags &= ~IFF_RENAMING; break; #ifdef VIMAGE case SIOCSIFVNET: error = priv_check(td, PRIV_NET_SETIFVNET); if (error) return (error); error = if_vmove_loan(td, ifp, ifr->ifr_name, ifr->ifr_jid); break; #endif case SIOCSIFMETRIC: error = priv_check(td, PRIV_NET_SETIFMETRIC); if (error) return (error); ifp->if_metric = ifr->ifr_metric; getmicrotime(&ifp->if_lastchange); break; case SIOCSIFPHYS: error = priv_check(td, PRIV_NET_SETIFPHYS); if (error) return (error); if (ifp->if_ioctl == NULL) return (EOPNOTSUPP); error = (*ifp->if_ioctl)(ifp, cmd, data); if (error == 0) getmicrotime(&ifp->if_lastchange); break; case SIOCSIFMTU: { u_long oldmtu = ifp->if_mtu; error = priv_check(td, PRIV_NET_SETIFMTU); if (error) return (error); if (ifr->ifr_mtu < IF_MINMTU || ifr->ifr_mtu > IF_MAXMTU) return (EINVAL); if (ifp->if_ioctl == NULL) return (EOPNOTSUPP); error = (*ifp->if_ioctl)(ifp, cmd, data); if (error == 0) { getmicrotime(&ifp->if_lastchange); rt_ifmsg(ifp); } /* * If the link MTU changed, do network layer specific procedure. */ if (ifp->if_mtu != oldmtu) { #ifdef INET6 nd6_setmtu(ifp); #endif rt_updatemtu(ifp); } break; } case SIOCADDMULTI: case SIOCDELMULTI: if (cmd == SIOCADDMULTI) error = priv_check(td, PRIV_NET_ADDMULTI); else error = priv_check(td, PRIV_NET_DELMULTI); if (error) return (error); /* Don't allow group membership on non-multicast interfaces. */ if ((ifp->if_flags & IFF_MULTICAST) == 0) return (EOPNOTSUPP); /* Don't let users screw up protocols' entries. */ if (ifr->ifr_addr.sa_family != AF_LINK) return (EINVAL); if (cmd == SIOCADDMULTI) { struct ifmultiaddr *ifma; /* * Userland is only permitted to join groups once * via the if_addmulti() KPI, because it cannot hold * struct ifmultiaddr * between calls. It may also * lose a race while we check if the membership * already exists. */ IF_ADDR_RLOCK(ifp); ifma = if_findmulti(ifp, &ifr->ifr_addr); IF_ADDR_RUNLOCK(ifp); if (ifma != NULL) error = EADDRINUSE; else error = if_addmulti(ifp, &ifr->ifr_addr, &ifma); } else { error = if_delmulti(ifp, &ifr->ifr_addr); } if (error == 0) getmicrotime(&ifp->if_lastchange); break; case SIOCSIFPHYADDR: case SIOCDIFPHYADDR: #ifdef INET6 case SIOCSIFPHYADDR_IN6: #endif case SIOCSIFMEDIA: case SIOCSIFGENERIC: error = priv_check(td, PRIV_NET_HWIOCTL); if (error) return (error); if (ifp->if_ioctl == NULL) return (EOPNOTSUPP); error = (*ifp->if_ioctl)(ifp, cmd, data); if (error == 0) getmicrotime(&ifp->if_lastchange); break; case SIOCGIFSTATUS: case SIOCGIFPSRCADDR: case SIOCGIFPDSTADDR: case SIOCGIFMEDIA: case SIOCGIFXMEDIA: case SIOCGIFGENERIC: if (ifp->if_ioctl == NULL) return (EOPNOTSUPP); error = (*ifp->if_ioctl)(ifp, cmd, data); break; case SIOCSIFLLADDR: error = priv_check(td, PRIV_NET_SETLLADDR); if (error) return (error); error = if_setlladdr(ifp, ifr->ifr_addr.sa_data, ifr->ifr_addr.sa_len); break; case SIOCAIFGROUP: { struct ifgroupreq *ifgr = (struct ifgroupreq *)ifr; error = priv_check(td, PRIV_NET_ADDIFGROUP); if (error) return (error); if ((error = if_addgroup(ifp, ifgr->ifgr_group))) return (error); break; } case SIOCGIFGROUP: if ((error = if_getgroup((struct ifgroupreq *)ifr, ifp))) return (error); break; case SIOCDIFGROUP: { struct ifgroupreq *ifgr = (struct ifgroupreq *)ifr; error = priv_check(td, PRIV_NET_DELIFGROUP); if (error) return (error); if ((error = if_delgroup(ifp, ifgr->ifgr_group))) return (error); break; } default: error = ENOIOCTL; break; } return (error); } #ifdef COMPAT_FREEBSD32 struct ifconf32 { int32_t ifc_len; union { uint32_t ifcu_buf; uint32_t ifcu_req; } ifc_ifcu; }; #define SIOCGIFCONF32 _IOWR('i', 36, struct ifconf32) #endif /* * Interface ioctls. */ int ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td) { struct ifnet *ifp; struct ifreq *ifr; int error; int oif_flags; CURVNET_SET(so->so_vnet); switch (cmd) { case SIOCGIFCONF: error = ifconf(cmd, data); CURVNET_RESTORE(); return (error); #ifdef COMPAT_FREEBSD32 case SIOCGIFCONF32: { struct ifconf32 *ifc32; struct ifconf ifc; ifc32 = (struct ifconf32 *)data; ifc.ifc_len = ifc32->ifc_len; ifc.ifc_buf = PTRIN(ifc32->ifc_buf); error = ifconf(SIOCGIFCONF, (void *)&ifc); CURVNET_RESTORE(); if (error == 0) ifc32->ifc_len = ifc.ifc_len; return (error); } #endif } ifr = (struct ifreq *)data; switch (cmd) { #ifdef VIMAGE case SIOCSIFRVNET: error = priv_check(td, PRIV_NET_SETIFVNET); if (error == 0) error = if_vmove_reclaim(td, ifr->ifr_name, ifr->ifr_jid); CURVNET_RESTORE(); return (error); #endif case SIOCIFCREATE: case SIOCIFCREATE2: error = priv_check(td, PRIV_NET_IFCREATE); if (error == 0) error = if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name), cmd == SIOCIFCREATE2 ? ifr->ifr_data : NULL); CURVNET_RESTORE(); return (error); case SIOCIFDESTROY: error = priv_check(td, PRIV_NET_IFDESTROY); if (error == 0) error = if_clone_destroy(ifr->ifr_name); CURVNET_RESTORE(); return (error); case SIOCIFGCLONERS: error = if_clone_list((struct if_clonereq *)data); CURVNET_RESTORE(); return (error); case SIOCGIFGMEMB: error = if_getgroupmembers((struct ifgroupreq *)data); CURVNET_RESTORE(); return (error); #if defined(INET) || defined(INET6) case SIOCSVH: case SIOCGVH: if (carp_ioctl_p == NULL) error = EPROTONOSUPPORT; else error = (*carp_ioctl_p)(ifr, cmd, td); CURVNET_RESTORE(); return (error); #endif } ifp = ifunit_ref(ifr->ifr_name); if (ifp == NULL) { CURVNET_RESTORE(); return (ENXIO); } error = ifhwioctl(cmd, ifp, data, td); if (error != ENOIOCTL) { if_rele(ifp); CURVNET_RESTORE(); return (error); } oif_flags = ifp->if_flags; if (so->so_proto == NULL) { if_rele(ifp); CURVNET_RESTORE(); return (EOPNOTSUPP); } /* * Pass the request on to the socket control method, and if the * latter returns EOPNOTSUPP, directly to the interface. * * Make an exception for the legacy SIOCSIF* requests. Drivers * trust SIOCSIFADDR et al to come from an already privileged * layer, and do not perform any credentials checks or input * validation. */ error = ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data, ifp, td)); if (error == EOPNOTSUPP && ifp != NULL && ifp->if_ioctl != NULL && cmd != SIOCSIFADDR && cmd != SIOCSIFBRDADDR && cmd != SIOCSIFDSTADDR && cmd != SIOCSIFNETMASK) error = (*ifp->if_ioctl)(ifp, cmd, data); if ((oif_flags ^ ifp->if_flags) & IFF_UP) { #ifdef INET6 if (ifp->if_flags & IFF_UP) in6_if_up(ifp); #endif } if_rele(ifp); CURVNET_RESTORE(); return (error); } /* * The code common to handling reference counted flags, * e.g., in ifpromisc() and if_allmulti(). * The "pflag" argument can specify a permanent mode flag to check, * such as IFF_PPROMISC for promiscuous mode; should be 0 if none. * * Only to be used on stack-owned flags, not driver-owned flags. */ static int if_setflag(struct ifnet *ifp, int flag, int pflag, int *refcount, int onswitch) { struct ifreq ifr; int error; int oldflags, oldcount; /* Sanity checks to catch programming errors */ KASSERT((flag & (IFF_DRV_OACTIVE|IFF_DRV_RUNNING)) == 0, ("%s: setting driver-owned flag %d", __func__, flag)); if (onswitch) KASSERT(*refcount >= 0, ("%s: increment negative refcount %d for flag %d", __func__, *refcount, flag)); else KASSERT(*refcount > 0, ("%s: decrement non-positive refcount %d for flag %d", __func__, *refcount, flag)); /* In case this mode is permanent, just touch refcount */ if (ifp->if_flags & pflag) { *refcount += onswitch ? 1 : -1; return (0); } /* Save ifnet parameters for if_ioctl() may fail */ oldcount = *refcount; oldflags = ifp->if_flags; /* * See if we aren't the only and touching refcount is enough. * Actually toggle interface flag if we are the first or last. */ if (onswitch) { if ((*refcount)++) return (0); ifp->if_flags |= flag; } else { if (--(*refcount)) return (0); ifp->if_flags &= ~flag; } /* Call down the driver since we've changed interface flags */ if (ifp->if_ioctl == NULL) { error = EOPNOTSUPP; goto recover; } ifr.ifr_flags = ifp->if_flags & 0xffff; ifr.ifr_flagshigh = ifp->if_flags >> 16; error = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr); if (error) goto recover; /* Notify userland that interface flags have changed */ rt_ifmsg(ifp); return (0); recover: /* Recover after driver error */ *refcount = oldcount; ifp->if_flags = oldflags; return (error); } /* * Set/clear promiscuous mode on interface ifp based on the truth value * of pswitch. The calls are reference counted so that only the first * "on" request actually has an effect, as does the final "off" request. * Results are undefined if the "off" and "on" requests are not matched. */ int ifpromisc(struct ifnet *ifp, int pswitch) { int error; int oldflags = ifp->if_flags; error = if_setflag(ifp, IFF_PROMISC, IFF_PPROMISC, &ifp->if_pcount, pswitch); /* If promiscuous mode status has changed, log a message */ if (error == 0 && ((ifp->if_flags ^ oldflags) & IFF_PROMISC)) log(LOG_INFO, "%s: promiscuous mode %s\n", ifp->if_xname, (ifp->if_flags & IFF_PROMISC) ? "enabled" : "disabled"); return (error); } /* * Return interface configuration * of system. List may be used * in later ioctl's (above) to get * other information. */ /*ARGSUSED*/ static int ifconf(u_long cmd, caddr_t data) { struct ifconf *ifc = (struct ifconf *)data; struct ifnet *ifp; struct ifaddr *ifa; struct ifreq ifr; struct sbuf *sb; int error, full = 0, valid_len, max_len; /* Limit initial buffer size to MAXPHYS to avoid DoS from userspace. */ max_len = MAXPHYS - 1; /* Prevent hostile input from being able to crash the system */ if (ifc->ifc_len <= 0) return (EINVAL); again: if (ifc->ifc_len <= max_len) { max_len = ifc->ifc_len; full = 1; } sb = sbuf_new(NULL, NULL, max_len + 1, SBUF_FIXEDLEN); max_len = 0; valid_len = 0; IFNET_RLOCK(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { int addrs; /* * Zero the ifr_name buffer to make sure we don't * disclose the contents of the stack. */ memset(ifr.ifr_name, 0, sizeof(ifr.ifr_name)); if (strlcpy(ifr.ifr_name, ifp->if_xname, sizeof(ifr.ifr_name)) >= sizeof(ifr.ifr_name)) { sbuf_delete(sb); IFNET_RUNLOCK(); return (ENAMETOOLONG); } addrs = 0; IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { struct sockaddr *sa = ifa->ifa_addr; if (prison_if(curthread->td_ucred, sa) != 0) continue; addrs++; if (sa->sa_len <= sizeof(*sa)) { ifr.ifr_addr = *sa; sbuf_bcat(sb, &ifr, sizeof(ifr)); max_len += sizeof(ifr); } else { sbuf_bcat(sb, &ifr, offsetof(struct ifreq, ifr_addr)); max_len += offsetof(struct ifreq, ifr_addr); sbuf_bcat(sb, sa, sa->sa_len); max_len += sa->sa_len; } if (sbuf_error(sb) == 0) valid_len = sbuf_len(sb); } IF_ADDR_RUNLOCK(ifp); if (addrs == 0) { bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); sbuf_bcat(sb, &ifr, sizeof(ifr)); max_len += sizeof(ifr); if (sbuf_error(sb) == 0) valid_len = sbuf_len(sb); } } IFNET_RUNLOCK(); /* * If we didn't allocate enough space (uncommon), try again. If * we have already allocated as much space as we are allowed, * return what we've got. */ if (valid_len != max_len && !full) { sbuf_delete(sb); goto again; } ifc->ifc_len = valid_len; sbuf_finish(sb); error = copyout(sbuf_data(sb), ifc->ifc_req, ifc->ifc_len); sbuf_delete(sb); return (error); } /* * Just like ifpromisc(), but for all-multicast-reception mode. */ int if_allmulti(struct ifnet *ifp, int onswitch) { return (if_setflag(ifp, IFF_ALLMULTI, 0, &ifp->if_amcount, onswitch)); } struct ifmultiaddr * if_findmulti(struct ifnet *ifp, const struct sockaddr *sa) { struct ifmultiaddr *ifma; IF_ADDR_LOCK_ASSERT(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (sa->sa_family == AF_LINK) { if (sa_dl_equal(ifma->ifma_addr, sa)) break; } else { if (sa_equal(ifma->ifma_addr, sa)) break; } } return ifma; } /* * Allocate a new ifmultiaddr and initialize based on passed arguments. We * make copies of passed sockaddrs. The ifmultiaddr will not be added to * the ifnet multicast address list here, so the caller must do that and * other setup work (such as notifying the device driver). The reference * count is initialized to 1. */ static struct ifmultiaddr * if_allocmulti(struct ifnet *ifp, struct sockaddr *sa, struct sockaddr *llsa, int mflags) { struct ifmultiaddr *ifma; struct sockaddr *dupsa; ifma = malloc(sizeof *ifma, M_IFMADDR, mflags | M_ZERO); if (ifma == NULL) return (NULL); dupsa = malloc(sa->sa_len, M_IFMADDR, mflags); if (dupsa == NULL) { free(ifma, M_IFMADDR); return (NULL); } bcopy(sa, dupsa, sa->sa_len); ifma->ifma_addr = dupsa; ifma->ifma_ifp = ifp; ifma->ifma_refcount = 1; ifma->ifma_protospec = NULL; if (llsa == NULL) { ifma->ifma_lladdr = NULL; return (ifma); } dupsa = malloc(llsa->sa_len, M_IFMADDR, mflags); if (dupsa == NULL) { free(ifma->ifma_addr, M_IFMADDR); free(ifma, M_IFMADDR); return (NULL); } bcopy(llsa, dupsa, llsa->sa_len); ifma->ifma_lladdr = dupsa; return (ifma); } /* * if_freemulti: free ifmultiaddr structure and possibly attached related * addresses. The caller is responsible for implementing reference * counting, notifying the driver, handling routing messages, and releasing * any dependent link layer state. */ static void if_freemulti(struct ifmultiaddr *ifma) { KASSERT(ifma->ifma_refcount == 0, ("if_freemulti: refcount %d", ifma->ifma_refcount)); if (ifma->ifma_lladdr != NULL) free(ifma->ifma_lladdr, M_IFMADDR); free(ifma->ifma_addr, M_IFMADDR); free(ifma, M_IFMADDR); } /* * Register an additional multicast address with a network interface. * * - If the address is already present, bump the reference count on the * address and return. * - If the address is not link-layer, look up a link layer address. * - Allocate address structures for one or both addresses, and attach to the * multicast address list on the interface. If automatically adding a link * layer address, the protocol address will own a reference to the link * layer address, to be freed when it is freed. * - Notify the network device driver of an addition to the multicast address * list. * * 'sa' points to caller-owned memory with the desired multicast address. * * 'retifma' will be used to return a pointer to the resulting multicast * address reference, if desired. */ int if_addmulti(struct ifnet *ifp, struct sockaddr *sa, struct ifmultiaddr **retifma) { struct ifmultiaddr *ifma, *ll_ifma; struct sockaddr *llsa; struct sockaddr_dl sdl; int error; /* * If the address is already present, return a new reference to it; * otherwise, allocate storage and set up a new address. */ IF_ADDR_WLOCK(ifp); ifma = if_findmulti(ifp, sa); if (ifma != NULL) { ifma->ifma_refcount++; if (retifma != NULL) *retifma = ifma; IF_ADDR_WUNLOCK(ifp); return (0); } /* * The address isn't already present; resolve the protocol address * into a link layer address, and then look that up, bump its * refcount or allocate an ifma for that also. * Most link layer resolving functions returns address data which * fits inside default sockaddr_dl structure. However callback * can allocate another sockaddr structure, in that case we need to * free it later. */ llsa = NULL; ll_ifma = NULL; if (ifp->if_resolvemulti != NULL) { /* Provide called function with buffer size information */ sdl.sdl_len = sizeof(sdl); llsa = (struct sockaddr *)&sdl; error = ifp->if_resolvemulti(ifp, &llsa, sa); if (error) goto unlock_out; } /* * Allocate the new address. Don't hook it up yet, as we may also * need to allocate a link layer multicast address. */ ifma = if_allocmulti(ifp, sa, llsa, M_NOWAIT); if (ifma == NULL) { error = ENOMEM; goto free_llsa_out; } /* * If a link layer address is found, we'll need to see if it's * already present in the address list, or allocate is as well. * When this block finishes, the link layer address will be on the * list. */ if (llsa != NULL) { ll_ifma = if_findmulti(ifp, llsa); if (ll_ifma == NULL) { ll_ifma = if_allocmulti(ifp, llsa, NULL, M_NOWAIT); if (ll_ifma == NULL) { --ifma->ifma_refcount; if_freemulti(ifma); error = ENOMEM; goto free_llsa_out; } TAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ll_ifma, ifma_link); } else ll_ifma->ifma_refcount++; ifma->ifma_llifma = ll_ifma; } /* * We now have a new multicast address, ifma, and possibly a new or * referenced link layer address. Add the primary address to the * ifnet address list. */ TAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link); if (retifma != NULL) *retifma = ifma; /* * Must generate the message while holding the lock so that 'ifma' * pointer is still valid. */ rt_newmaddrmsg(RTM_NEWMADDR, ifma); IF_ADDR_WUNLOCK(ifp); /* * We are certain we have added something, so call down to the * interface to let them know about it. */ if (ifp->if_ioctl != NULL) { (void) (*ifp->if_ioctl)(ifp, SIOCADDMULTI, 0); } if ((llsa != NULL) && (llsa != (struct sockaddr *)&sdl)) link_free_sdl(llsa); return (0); free_llsa_out: if ((llsa != NULL) && (llsa != (struct sockaddr *)&sdl)) link_free_sdl(llsa); unlock_out: IF_ADDR_WUNLOCK(ifp); return (error); } /* * Delete a multicast group membership by network-layer group address. * * Returns ENOENT if the entry could not be found. If ifp no longer * exists, results are undefined. This entry point should only be used * from subsystems which do appropriate locking to hold ifp for the * duration of the call. * Network-layer protocol domains must use if_delmulti_ifma(). */ int if_delmulti(struct ifnet *ifp, struct sockaddr *sa) { struct ifmultiaddr *ifma; int lastref; #ifdef INVARIANTS struct ifnet *oifp; IFNET_RLOCK_NOSLEEP(); TAILQ_FOREACH(oifp, &V_ifnet, if_link) if (ifp == oifp) break; if (ifp != oifp) ifp = NULL; IFNET_RUNLOCK_NOSLEEP(); KASSERT(ifp != NULL, ("%s: ifnet went away", __func__)); #endif if (ifp == NULL) return (ENOENT); IF_ADDR_WLOCK(ifp); lastref = 0; ifma = if_findmulti(ifp, sa); if (ifma != NULL) lastref = if_delmulti_locked(ifp, ifma, 0); IF_ADDR_WUNLOCK(ifp); if (ifma == NULL) return (ENOENT); if (lastref && ifp->if_ioctl != NULL) { (void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, 0); } return (0); } /* * Delete all multicast group membership for an interface. * Should be used to quickly flush all multicast filters. */ void if_delallmulti(struct ifnet *ifp) { struct ifmultiaddr *ifma; struct ifmultiaddr *next; IF_ADDR_WLOCK(ifp); TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next) if_delmulti_locked(ifp, ifma, 0); IF_ADDR_WUNLOCK(ifp); } /* * Delete a multicast group membership by group membership pointer. * Network-layer protocol domains must use this routine. * * It is safe to call this routine if the ifp disappeared. */ void if_delmulti_ifma(struct ifmultiaddr *ifma) { struct ifnet *ifp; int lastref; ifp = ifma->ifma_ifp; #ifdef DIAGNOSTIC if (ifp == NULL) { printf("%s: ifma_ifp seems to be detached\n", __func__); } else { struct ifnet *oifp; IFNET_RLOCK_NOSLEEP(); TAILQ_FOREACH(oifp, &V_ifnet, if_link) if (ifp == oifp) break; if (ifp != oifp) { printf("%s: ifnet %p disappeared\n", __func__, ifp); ifp = NULL; } IFNET_RUNLOCK_NOSLEEP(); } #endif /* * If and only if the ifnet instance exists: Acquire the address lock. */ if (ifp != NULL) IF_ADDR_WLOCK(ifp); lastref = if_delmulti_locked(ifp, ifma, 0); if (ifp != NULL) { /* * If and only if the ifnet instance exists: * Release the address lock. * If the group was left: update the hardware hash filter. */ IF_ADDR_WUNLOCK(ifp); if (lastref && ifp->if_ioctl != NULL) { (void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, 0); } } } /* * Perform deletion of network-layer and/or link-layer multicast address. * * Return 0 if the reference count was decremented. * Return 1 if the final reference was released, indicating that the * hardware hash filter should be reprogrammed. */ static int if_delmulti_locked(struct ifnet *ifp, struct ifmultiaddr *ifma, int detaching) { struct ifmultiaddr *ll_ifma; if (ifp != NULL && ifma->ifma_ifp != NULL) { KASSERT(ifma->ifma_ifp == ifp, ("%s: inconsistent ifp %p", __func__, ifp)); IF_ADDR_WLOCK_ASSERT(ifp); } ifp = ifma->ifma_ifp; /* * If the ifnet is detaching, null out references to ifnet, * so that upper protocol layers will notice, and not attempt * to obtain locks for an ifnet which no longer exists. The * routing socket announcement must happen before the ifnet * instance is detached from the system. */ if (detaching) { #ifdef DIAGNOSTIC printf("%s: detaching ifnet instance %p\n", __func__, ifp); #endif /* * ifp may already be nulled out if we are being reentered * to delete the ll_ifma. */ if (ifp != NULL) { rt_newmaddrmsg(RTM_DELMADDR, ifma); ifma->ifma_ifp = NULL; } } if (--ifma->ifma_refcount > 0) return 0; /* * If this ifma is a network-layer ifma, a link-layer ifma may * have been associated with it. Release it first if so. */ ll_ifma = ifma->ifma_llifma; if (ll_ifma != NULL) { KASSERT(ifma->ifma_lladdr != NULL, ("%s: llifma w/o lladdr", __func__)); if (detaching) ll_ifma->ifma_ifp = NULL; /* XXX */ if (--ll_ifma->ifma_refcount == 0) { if (ifp != NULL) { TAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma, ifma_link); } if_freemulti(ll_ifma); } } if (ifp != NULL) TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link); if_freemulti(ifma); /* * The last reference to this instance of struct ifmultiaddr * was released; the hardware should be notified of this change. */ return 1; } /* * Set the link layer address on an interface. * * At this time we only support certain types of interfaces, * and we don't allow the length of the address to change. * * Set noinline to be dtrace-friendly */ __noinline int if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len) { struct sockaddr_dl *sdl; struct ifaddr *ifa; struct ifreq ifr; IF_ADDR_RLOCK(ifp); ifa = ifp->if_addr; if (ifa == NULL) { IF_ADDR_RUNLOCK(ifp); return (EINVAL); } ifa_ref(ifa); IF_ADDR_RUNLOCK(ifp); sdl = (struct sockaddr_dl *)ifa->ifa_addr; if (sdl == NULL) { ifa_free(ifa); return (EINVAL); } if (len != sdl->sdl_alen) { /* don't allow length to change */ ifa_free(ifa); return (EINVAL); } switch (ifp->if_type) { case IFT_ETHER: case IFT_FDDI: case IFT_XETHER: case IFT_ISO88025: case IFT_L2VLAN: case IFT_BRIDGE: case IFT_ARCNET: case IFT_IEEE8023ADLAG: case IFT_IEEE80211: bcopy(lladdr, LLADDR(sdl), len); ifa_free(ifa); break; default: ifa_free(ifa); return (ENODEV); } /* * If the interface is already up, we need * to re-init it in order to reprogram its * address filter. */ if ((ifp->if_flags & IFF_UP) != 0) { if (ifp->if_ioctl) { ifp->if_flags &= ~IFF_UP; ifr.ifr_flags = ifp->if_flags & 0xffff; ifr.ifr_flagshigh = ifp->if_flags >> 16; (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr); ifp->if_flags |= IFF_UP; ifr.ifr_flags = ifp->if_flags & 0xffff; ifr.ifr_flagshigh = ifp->if_flags >> 16; (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr); } } EVENTHANDLER_INVOKE(iflladdr_event, ifp); return (0); } /* * The name argument must be a pointer to storage which will last as * long as the interface does. For physical devices, the result of * device_get_name(dev) is a good choice and for pseudo-devices a * static string works well. */ void if_initname(struct ifnet *ifp, const char *name, int unit) { ifp->if_dname = name; ifp->if_dunit = unit; if (unit != IF_DUNIT_NONE) snprintf(ifp->if_xname, IFNAMSIZ, "%s%d", name, unit); else strlcpy(ifp->if_xname, name, IFNAMSIZ); } int if_printf(struct ifnet *ifp, const char * fmt, ...) { va_list ap; int retval; retval = printf("%s: ", ifp->if_xname); va_start(ap, fmt); retval += vprintf(fmt, ap); va_end(ap); return (retval); } void if_start(struct ifnet *ifp) { (*(ifp)->if_start)(ifp); } /* * Backwards compatibility interface for drivers * that have not implemented it */ static int if_transmit(struct ifnet *ifp, struct mbuf *m) { int error; IFQ_HANDOFF(ifp, m, error); return (error); } static void if_input_default(struct ifnet *ifp __unused, struct mbuf *m) { m_freem(m); } int if_handoff(struct ifqueue *ifq, struct mbuf *m, struct ifnet *ifp, int adjust) { int active = 0; IF_LOCK(ifq); if (_IF_QFULL(ifq)) { IF_UNLOCK(ifq); if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1); m_freem(m); return (0); } if (ifp != NULL) { if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len + adjust); if (m->m_flags & (M_BCAST|M_MCAST)) if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1); active = ifp->if_drv_flags & IFF_DRV_OACTIVE; } _IF_ENQUEUE(ifq, m); IF_UNLOCK(ifq); if (ifp != NULL && !active) (*(ifp)->if_start)(ifp); return (1); } void if_register_com_alloc(u_char type, if_com_alloc_t *a, if_com_free_t *f) { KASSERT(if_com_alloc[type] == NULL, ("if_register_com_alloc: %d already registered", type)); KASSERT(if_com_free[type] == NULL, ("if_register_com_alloc: %d free already registered", type)); if_com_alloc[type] = a; if_com_free[type] = f; } void if_deregister_com_alloc(u_char type) { KASSERT(if_com_alloc[type] != NULL, ("if_deregister_com_alloc: %d not registered", type)); KASSERT(if_com_free[type] != NULL, ("if_deregister_com_alloc: %d free not registered", type)); if_com_alloc[type] = NULL; if_com_free[type] = NULL; } /* API for driver access to network stack owned ifnet.*/ uint64_t if_setbaudrate(struct ifnet *ifp, uint64_t baudrate) { uint64_t oldbrate; oldbrate = ifp->if_baudrate; ifp->if_baudrate = baudrate; return (oldbrate); } uint64_t if_getbaudrate(if_t ifp) { return (((struct ifnet *)ifp)->if_baudrate); } int if_setcapabilities(if_t ifp, int capabilities) { ((struct ifnet *)ifp)->if_capabilities = capabilities; return (0); } int if_setcapabilitiesbit(if_t ifp, int setbit, int clearbit) { ((struct ifnet *)ifp)->if_capabilities |= setbit; ((struct ifnet *)ifp)->if_capabilities &= ~clearbit; return (0); } int if_getcapabilities(if_t ifp) { return ((struct ifnet *)ifp)->if_capabilities; } int if_setcapenable(if_t ifp, int capabilities) { ((struct ifnet *)ifp)->if_capenable = capabilities; return (0); } int if_setcapenablebit(if_t ifp, int setcap, int clearcap) { if(setcap) ((struct ifnet *)ifp)->if_capenable |= setcap; if(clearcap) ((struct ifnet *)ifp)->if_capenable &= ~clearcap; return (0); } const char * if_getdname(if_t ifp) { return ((struct ifnet *)ifp)->if_dname; } int if_togglecapenable(if_t ifp, int togglecap) { ((struct ifnet *)ifp)->if_capenable ^= togglecap; return (0); } int if_getcapenable(if_t ifp) { return ((struct ifnet *)ifp)->if_capenable; } /* * This is largely undesirable because it ties ifnet to a device, but does * provide flexiblity for an embedded product vendor. Should be used with * the understanding that it violates the interface boundaries, and should be * a last resort only. */ int if_setdev(if_t ifp, void *dev) { return (0); } int if_setdrvflagbits(if_t ifp, int set_flags, int clear_flags) { ((struct ifnet *)ifp)->if_drv_flags |= set_flags; ((struct ifnet *)ifp)->if_drv_flags &= ~clear_flags; return (0); } int if_getdrvflags(if_t ifp) { return ((struct ifnet *)ifp)->if_drv_flags; } int if_setdrvflags(if_t ifp, int flags) { ((struct ifnet *)ifp)->if_drv_flags = flags; return (0); } int if_setflags(if_t ifp, int flags) { ((struct ifnet *)ifp)->if_flags = flags; return (0); } int if_setflagbits(if_t ifp, int set, int clear) { ((struct ifnet *)ifp)->if_flags |= set; ((struct ifnet *)ifp)->if_flags &= ~clear; return (0); } int if_getflags(if_t ifp) { return ((struct ifnet *)ifp)->if_flags; } int if_clearhwassist(if_t ifp) { ((struct ifnet *)ifp)->if_hwassist = 0; return (0); } int if_sethwassistbits(if_t ifp, int toset, int toclear) { ((struct ifnet *)ifp)->if_hwassist |= toset; ((struct ifnet *)ifp)->if_hwassist &= ~toclear; return (0); } int if_sethwassist(if_t ifp, int hwassist_bit) { ((struct ifnet *)ifp)->if_hwassist = hwassist_bit; return (0); } int if_gethwassist(if_t ifp) { return ((struct ifnet *)ifp)->if_hwassist; } int if_setmtu(if_t ifp, int mtu) { ((struct ifnet *)ifp)->if_mtu = mtu; return (0); } int if_getmtu(if_t ifp) { return ((struct ifnet *)ifp)->if_mtu; } int if_getmtu_family(if_t ifp, int family) { struct domain *dp; for (dp = domains; dp; dp = dp->dom_next) { if (dp->dom_family == family && dp->dom_ifmtu != NULL) return (dp->dom_ifmtu((struct ifnet *)ifp)); } return (((struct ifnet *)ifp)->if_mtu); } int if_setsoftc(if_t ifp, void *softc) { ((struct ifnet *)ifp)->if_softc = softc; return (0); } void * if_getsoftc(if_t ifp) { return ((struct ifnet *)ifp)->if_softc; } void if_setrcvif(struct mbuf *m, if_t ifp) { m->m_pkthdr.rcvif = (struct ifnet *)ifp; } void if_setvtag(struct mbuf *m, uint16_t tag) { m->m_pkthdr.ether_vtag = tag; } uint16_t if_getvtag(struct mbuf *m) { return (m->m_pkthdr.ether_vtag); } int if_sendq_empty(if_t ifp) { return IFQ_DRV_IS_EMPTY(&((struct ifnet *)ifp)->if_snd); } struct ifaddr * if_getifaddr(if_t ifp) { return ((struct ifnet *)ifp)->if_addr; } int if_getamcount(if_t ifp) { return ((struct ifnet *)ifp)->if_amcount; } int if_setsendqready(if_t ifp) { IFQ_SET_READY(&((struct ifnet *)ifp)->if_snd); return (0); } int if_setsendqlen(if_t ifp, int tx_desc_count) { IFQ_SET_MAXLEN(&((struct ifnet *)ifp)->if_snd, tx_desc_count); ((struct ifnet *)ifp)->if_snd.ifq_drv_maxlen = tx_desc_count; return (0); } int if_vlantrunkinuse(if_t ifp) { return ((struct ifnet *)ifp)->if_vlantrunk != NULL?1:0; } int if_input(if_t ifp, struct mbuf* sendmp) { (*((struct ifnet *)ifp)->if_input)((struct ifnet *)ifp, sendmp); return (0); } /* XXX */ #ifndef ETH_ADDR_LEN #define ETH_ADDR_LEN 6 #endif int if_setupmultiaddr(if_t ifp, void *mta, int *cnt, int max) { struct ifmultiaddr *ifma; uint8_t *lmta = (uint8_t *)mta; int mcnt = 0; TAILQ_FOREACH(ifma, &((struct ifnet *)ifp)->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; if (mcnt == max) break; bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), &lmta[mcnt * ETH_ADDR_LEN], ETH_ADDR_LEN); mcnt++; } *cnt = mcnt; return (0); } int if_multiaddr_array(if_t ifp, void *mta, int *cnt, int max) { int error; if_maddr_rlock(ifp); error = if_setupmultiaddr(ifp, mta, cnt, max); if_maddr_runlock(ifp); return (error); } int if_multiaddr_count(if_t ifp, int max) { struct ifmultiaddr *ifma; int count; count = 0; if_maddr_rlock(ifp); TAILQ_FOREACH(ifma, &((struct ifnet *)ifp)->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; count++; if (count == max) break; } if_maddr_runlock(ifp); return (count); } struct mbuf * if_dequeue(if_t ifp) { struct mbuf *m; IFQ_DRV_DEQUEUE(&((struct ifnet *)ifp)->if_snd, m); return (m); } int if_sendq_prepend(if_t ifp, struct mbuf *m) { IFQ_DRV_PREPEND(&((struct ifnet *)ifp)->if_snd, m); return (0); } int if_setifheaderlen(if_t ifp, int len) { ((struct ifnet *)ifp)->if_hdrlen = len; return (0); } caddr_t if_getlladdr(if_t ifp) { return (IF_LLADDR((struct ifnet *)ifp)); } void * if_gethandle(u_char type) { return (if_alloc(type)); } void if_bpfmtap(if_t ifh, struct mbuf *m) { struct ifnet *ifp = (struct ifnet *)ifh; BPF_MTAP(ifp, m); } void if_etherbpfmtap(if_t ifh, struct mbuf *m) { struct ifnet *ifp = (struct ifnet *)ifh; ETHER_BPF_MTAP(ifp, m); } void if_vlancap(if_t ifh) { struct ifnet *ifp = (struct ifnet *)ifh; VLAN_CAPABILITIES(ifp); } void if_setinitfn(if_t ifp, void (*init_fn)(void *)) { ((struct ifnet *)ifp)->if_init = init_fn; } void if_setioctlfn(if_t ifp, int (*ioctl_fn)(if_t, u_long, caddr_t)) { ((struct ifnet *)ifp)->if_ioctl = (void *)ioctl_fn; } void if_setstartfn(if_t ifp, void (*start_fn)(if_t)) { ((struct ifnet *)ifp)->if_start = (void *)start_fn; } void if_settransmitfn(if_t ifp, if_transmit_fn_t start_fn) { ((struct ifnet *)ifp)->if_transmit = start_fn; } void if_setqflushfn(if_t ifp, if_qflush_fn_t flush_fn) { ((struct ifnet *)ifp)->if_qflush = flush_fn; } void if_setgetcounterfn(if_t ifp, if_get_counter_t fn) { ifp->if_get_counter = fn; } /* Revisit these - These are inline functions originally. */ int drbr_inuse_drv(if_t ifh, struct buf_ring *br) { return drbr_inuse(ifh, br); } struct mbuf* drbr_dequeue_drv(if_t ifh, struct buf_ring *br) { return drbr_dequeue(ifh, br); } int drbr_needs_enqueue_drv(if_t ifh, struct buf_ring *br) { return drbr_needs_enqueue(ifh, br); } int drbr_enqueue_drv(if_t ifh, struct buf_ring *br, struct mbuf *m) { return drbr_enqueue(ifh, br, m); } Index: user/alc/PQ_LAUNDRY/sys/net/if_lagg.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/net/if_lagg.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/net/if_lagg.c (revision 292449) @@ -1,2224 +1,2219 @@ /* $OpenBSD: if_trunk.c,v 1.30 2007/01/31 06:20:19 reyk Exp $ */ /* * Copyright (c) 2005, 2006 Reyk Floeter * Copyright (c) 2007 Andrew Thompson * Copyright (c) 2014 Marcelo Araujo * * 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. */ #include __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(INET) || defined(INET6) #include #include #endif #ifdef INET #include #include #endif #ifdef INET6 #include #include #include #endif #include #include #include /* Special flags we should propagate to the lagg ports. */ static struct { int flag; int (*func)(struct ifnet *, int); } lagg_pflags[] = { {IFF_PROMISC, ifpromisc}, {IFF_ALLMULTI, if_allmulti}, {0, NULL} }; VNET_DEFINE(SLIST_HEAD(__trhead, lagg_softc), lagg_list); /* list of laggs */ #define V_lagg_list VNET(lagg_list) static VNET_DEFINE(struct mtx, lagg_list_mtx); #define V_lagg_list_mtx VNET(lagg_list_mtx) #define LAGG_LIST_LOCK_INIT(x) mtx_init(&V_lagg_list_mtx, \ "if_lagg list", NULL, MTX_DEF) #define LAGG_LIST_LOCK_DESTROY(x) mtx_destroy(&V_lagg_list_mtx) #define LAGG_LIST_LOCK(x) mtx_lock(&V_lagg_list_mtx) #define LAGG_LIST_UNLOCK(x) mtx_unlock(&V_lagg_list_mtx) eventhandler_tag lagg_detach_cookie = NULL; static int lagg_clone_create(struct if_clone *, int, caddr_t); static void lagg_clone_destroy(struct ifnet *); static VNET_DEFINE(struct if_clone *, lagg_cloner); #define V_lagg_cloner VNET(lagg_cloner) static const char laggname[] = "lagg"; static void lagg_lladdr(struct lagg_softc *, uint8_t *); static void lagg_capabilities(struct lagg_softc *); static void lagg_port_lladdr(struct lagg_port *, uint8_t *, lagg_llqtype); static void lagg_port_setlladdr(void *, int); static int lagg_port_create(struct lagg_softc *, struct ifnet *); static int lagg_port_destroy(struct lagg_port *, int); static struct mbuf *lagg_input(struct ifnet *, struct mbuf *); static void lagg_linkstate(struct lagg_softc *); -static void lagg_port_state(struct ifnet *); +static void lagg_port_state(struct ifnet *, int); static int lagg_port_ioctl(struct ifnet *, u_long, caddr_t); static int lagg_port_output(struct ifnet *, struct mbuf *, const struct sockaddr *, struct route *); static void lagg_port_ifdetach(void *arg __unused, struct ifnet *); #ifdef LAGG_PORT_STACKING static int lagg_port_checkstacking(struct lagg_softc *); #endif static void lagg_port2req(struct lagg_port *, struct lagg_reqport *); static void lagg_init(void *); static void lagg_stop(struct lagg_softc *); static int lagg_ioctl(struct ifnet *, u_long, caddr_t); static int lagg_ether_setmulti(struct lagg_softc *); static int lagg_ether_cmdmulti(struct lagg_port *, int); static int lagg_setflag(struct lagg_port *, int, int, int (*func)(struct ifnet *, int)); static int lagg_setflags(struct lagg_port *, int status); static uint64_t lagg_get_counter(struct ifnet *ifp, ift_counter cnt); static int lagg_transmit(struct ifnet *, struct mbuf *); static void lagg_qflush(struct ifnet *); static int lagg_media_change(struct ifnet *); static void lagg_media_status(struct ifnet *, struct ifmediareq *); static struct lagg_port *lagg_link_active(struct lagg_softc *, struct lagg_port *); /* Simple round robin */ static void lagg_rr_attach(struct lagg_softc *); static int lagg_rr_start(struct lagg_softc *, struct mbuf *); static struct mbuf *lagg_rr_input(struct lagg_softc *, struct lagg_port *, struct mbuf *); /* Active failover */ static int lagg_fail_start(struct lagg_softc *, struct mbuf *); static struct mbuf *lagg_fail_input(struct lagg_softc *, struct lagg_port *, struct mbuf *); /* Loadbalancing */ static void lagg_lb_attach(struct lagg_softc *); static void lagg_lb_detach(struct lagg_softc *); static int lagg_lb_port_create(struct lagg_port *); static void lagg_lb_port_destroy(struct lagg_port *); static int lagg_lb_start(struct lagg_softc *, struct mbuf *); static struct mbuf *lagg_lb_input(struct lagg_softc *, struct lagg_port *, struct mbuf *); static int lagg_lb_porttable(struct lagg_softc *, struct lagg_port *); /* Broadcast */ static int lagg_bcast_start(struct lagg_softc *, struct mbuf *); static struct mbuf *lagg_bcast_input(struct lagg_softc *, struct lagg_port *, struct mbuf *); /* 802.3ad LACP */ static void lagg_lacp_attach(struct lagg_softc *); static void lagg_lacp_detach(struct lagg_softc *); static int lagg_lacp_start(struct lagg_softc *, struct mbuf *); static struct mbuf *lagg_lacp_input(struct lagg_softc *, struct lagg_port *, struct mbuf *); static void lagg_lacp_lladdr(struct lagg_softc *); /* lagg protocol table */ static const struct lagg_proto { lagg_proto pr_num; void (*pr_attach)(struct lagg_softc *); void (*pr_detach)(struct lagg_softc *); int (*pr_start)(struct lagg_softc *, struct mbuf *); struct mbuf * (*pr_input)(struct lagg_softc *, struct lagg_port *, struct mbuf *); int (*pr_addport)(struct lagg_port *); void (*pr_delport)(struct lagg_port *); void (*pr_linkstate)(struct lagg_port *); void (*pr_init)(struct lagg_softc *); void (*pr_stop)(struct lagg_softc *); void (*pr_lladdr)(struct lagg_softc *); void (*pr_request)(struct lagg_softc *, void *); void (*pr_portreq)(struct lagg_port *, void *); } lagg_protos[] = { { .pr_num = LAGG_PROTO_NONE }, { .pr_num = LAGG_PROTO_ROUNDROBIN, .pr_attach = lagg_rr_attach, .pr_start = lagg_rr_start, .pr_input = lagg_rr_input, }, { .pr_num = LAGG_PROTO_FAILOVER, .pr_start = lagg_fail_start, .pr_input = lagg_fail_input, }, { .pr_num = LAGG_PROTO_LOADBALANCE, .pr_attach = lagg_lb_attach, .pr_detach = lagg_lb_detach, .pr_start = lagg_lb_start, .pr_input = lagg_lb_input, .pr_addport = lagg_lb_port_create, .pr_delport = lagg_lb_port_destroy, }, { .pr_num = LAGG_PROTO_LACP, .pr_attach = lagg_lacp_attach, .pr_detach = lagg_lacp_detach, .pr_start = lagg_lacp_start, .pr_input = lagg_lacp_input, .pr_addport = lacp_port_create, .pr_delport = lacp_port_destroy, .pr_linkstate = lacp_linkstate, .pr_init = lacp_init, .pr_stop = lacp_stop, .pr_lladdr = lagg_lacp_lladdr, .pr_request = lacp_req, .pr_portreq = lacp_portreq, }, { .pr_num = LAGG_PROTO_BROADCAST, .pr_start = lagg_bcast_start, .pr_input = lagg_bcast_input, }, }; SYSCTL_DECL(_net_link); SYSCTL_NODE(_net_link, OID_AUTO, lagg, CTLFLAG_RW, 0, "Link Aggregation"); /* Allow input on any failover links */ static VNET_DEFINE(int, lagg_failover_rx_all); #define V_lagg_failover_rx_all VNET(lagg_failover_rx_all) SYSCTL_INT(_net_link_lagg, OID_AUTO, failover_rx_all, CTLFLAG_RW | CTLFLAG_VNET, &VNET_NAME(lagg_failover_rx_all), 0, "Accept input from any interface in a failover lagg"); /* Default value for using flowid */ static VNET_DEFINE(int, def_use_flowid) = 1; #define V_def_use_flowid VNET(def_use_flowid) SYSCTL_INT(_net_link_lagg, OID_AUTO, default_use_flowid, CTLFLAG_RWTUN, &VNET_NAME(def_use_flowid), 0, "Default setting for using flow id for load sharing"); /* Default value for flowid shift */ static VNET_DEFINE(int, def_flowid_shift) = 16; #define V_def_flowid_shift VNET(def_flowid_shift) SYSCTL_INT(_net_link_lagg, OID_AUTO, default_flowid_shift, CTLFLAG_RWTUN, &VNET_NAME(def_flowid_shift), 0, "Default setting for flowid shift for load sharing"); static void vnet_lagg_init(const void *unused __unused) { LAGG_LIST_LOCK_INIT(); SLIST_INIT(&V_lagg_list); V_lagg_cloner = if_clone_simple(laggname, lagg_clone_create, lagg_clone_destroy, 0); } VNET_SYSINIT(vnet_lagg_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, vnet_lagg_init, NULL); static void vnet_lagg_uninit(const void *unused __unused) { if_clone_detach(V_lagg_cloner); LAGG_LIST_LOCK_DESTROY(); } VNET_SYSUNINIT(vnet_lagg_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, vnet_lagg_uninit, NULL); static int lagg_modevent(module_t mod, int type, void *data) { switch (type) { case MOD_LOAD: lagg_input_p = lagg_input; lagg_linkstate_p = lagg_port_state; lagg_detach_cookie = EVENTHANDLER_REGISTER( ifnet_departure_event, lagg_port_ifdetach, NULL, EVENTHANDLER_PRI_ANY); break; case MOD_UNLOAD: EVENTHANDLER_DEREGISTER(ifnet_departure_event, lagg_detach_cookie); lagg_input_p = NULL; lagg_linkstate_p = NULL; break; default: return (EOPNOTSUPP); } return (0); } static moduledata_t lagg_mod = { "if_lagg", lagg_modevent, 0 }; DECLARE_MODULE(if_lagg, lagg_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); MODULE_VERSION(if_lagg, 1); static void lagg_proto_attach(struct lagg_softc *sc, lagg_proto pr) { KASSERT(sc->sc_proto == LAGG_PROTO_NONE, ("%s: sc %p has proto", __func__, sc)); if (sc->sc_ifflags & IFF_DEBUG) if_printf(sc->sc_ifp, "using proto %u\n", pr); if (lagg_protos[pr].pr_attach != NULL) lagg_protos[pr].pr_attach(sc); sc->sc_proto = pr; } static void lagg_proto_detach(struct lagg_softc *sc) { lagg_proto pr; LAGG_WLOCK_ASSERT(sc); pr = sc->sc_proto; sc->sc_proto = LAGG_PROTO_NONE; if (lagg_protos[pr].pr_detach != NULL) lagg_protos[pr].pr_detach(sc); else LAGG_WUNLOCK(sc); } static int lagg_proto_start(struct lagg_softc *sc, struct mbuf *m) { return (lagg_protos[sc->sc_proto].pr_start(sc, m)); } static struct mbuf * lagg_proto_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m) { return (lagg_protos[sc->sc_proto].pr_input(sc, lp, m)); } static int lagg_proto_addport(struct lagg_softc *sc, struct lagg_port *lp) { if (lagg_protos[sc->sc_proto].pr_addport == NULL) return (0); else return (lagg_protos[sc->sc_proto].pr_addport(lp)); } static void lagg_proto_delport(struct lagg_softc *sc, struct lagg_port *lp) { if (lagg_protos[sc->sc_proto].pr_delport != NULL) lagg_protos[sc->sc_proto].pr_delport(lp); } static void lagg_proto_linkstate(struct lagg_softc *sc, struct lagg_port *lp) { if (lagg_protos[sc->sc_proto].pr_linkstate != NULL) lagg_protos[sc->sc_proto].pr_linkstate(lp); } static void lagg_proto_init(struct lagg_softc *sc) { if (lagg_protos[sc->sc_proto].pr_init != NULL) lagg_protos[sc->sc_proto].pr_init(sc); } static void lagg_proto_stop(struct lagg_softc *sc) { if (lagg_protos[sc->sc_proto].pr_stop != NULL) lagg_protos[sc->sc_proto].pr_stop(sc); } static void lagg_proto_lladdr(struct lagg_softc *sc) { if (lagg_protos[sc->sc_proto].pr_lladdr != NULL) lagg_protos[sc->sc_proto].pr_lladdr(sc); } static void lagg_proto_request(struct lagg_softc *sc, void *v) { if (lagg_protos[sc->sc_proto].pr_request != NULL) lagg_protos[sc->sc_proto].pr_request(sc, v); } static void lagg_proto_portreq(struct lagg_softc *sc, struct lagg_port *lp, void *v) { if (lagg_protos[sc->sc_proto].pr_portreq != NULL) lagg_protos[sc->sc_proto].pr_portreq(lp, v); } /* * This routine is run via an vlan * config EVENT */ static void lagg_register_vlan(void *arg, struct ifnet *ifp, u_int16_t vtag) { struct lagg_softc *sc = ifp->if_softc; struct lagg_port *lp; struct rm_priotracker tracker; if (ifp->if_softc != arg) /* Not our event */ return; LAGG_RLOCK(sc, &tracker); if (!SLIST_EMPTY(&sc->sc_ports)) { SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) EVENTHANDLER_INVOKE(vlan_config, lp->lp_ifp, vtag); } LAGG_RUNLOCK(sc, &tracker); } /* * This routine is run via an vlan * unconfig EVENT */ static void lagg_unregister_vlan(void *arg, struct ifnet *ifp, u_int16_t vtag) { struct lagg_softc *sc = ifp->if_softc; struct lagg_port *lp; struct rm_priotracker tracker; if (ifp->if_softc != arg) /* Not our event */ return; LAGG_RLOCK(sc, &tracker); if (!SLIST_EMPTY(&sc->sc_ports)) { SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) EVENTHANDLER_INVOKE(vlan_unconfig, lp->lp_ifp, vtag); } LAGG_RUNLOCK(sc, &tracker); } static int lagg_clone_create(struct if_clone *ifc, int unit, caddr_t params) { struct lagg_softc *sc; struct ifnet *ifp; static const u_char eaddr[6]; /* 00:00:00:00:00:00 */ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); ifp = sc->sc_ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { free(sc, M_DEVBUF); return (ENOSPC); } if (V_def_use_flowid) sc->sc_opts |= LAGG_OPT_USE_FLOWID; sc->flowid_shift = V_def_flowid_shift; /* Hash all layers by default */ sc->sc_flags = MBUF_HASHFLAG_L2|MBUF_HASHFLAG_L3|MBUF_HASHFLAG_L4; lagg_proto_attach(sc, LAGG_PROTO_DEFAULT); LAGG_LOCK_INIT(sc); SLIST_INIT(&sc->sc_ports); TASK_INIT(&sc->sc_lladdr_task, 0, lagg_port_setlladdr, sc); /* Initialise pseudo media types */ ifmedia_init(&sc->sc_media, 0, lagg_media_change, lagg_media_status); ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO); if_initname(ifp, laggname, unit); ifp->if_softc = sc; ifp->if_transmit = lagg_transmit; ifp->if_qflush = lagg_qflush; ifp->if_init = lagg_init; ifp->if_ioctl = lagg_ioctl; ifp->if_get_counter = lagg_get_counter; ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; ifp->if_capenable = ifp->if_capabilities = IFCAP_HWSTATS; /* * Attach as an ordinary ethernet device, children will be attached * as special device IFT_IEEE8023ADLAG. */ ether_ifattach(ifp, eaddr); sc->vlan_attach = EVENTHANDLER_REGISTER(vlan_config, lagg_register_vlan, sc, EVENTHANDLER_PRI_FIRST); sc->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, lagg_unregister_vlan, sc, EVENTHANDLER_PRI_FIRST); /* Insert into the global list of laggs */ LAGG_LIST_LOCK(); SLIST_INSERT_HEAD(&V_lagg_list, sc, sc_entries); LAGG_LIST_UNLOCK(); return (0); } static void lagg_clone_destroy(struct ifnet *ifp) { struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; struct lagg_port *lp; LAGG_WLOCK(sc); lagg_stop(sc); ifp->if_flags &= ~IFF_UP; EVENTHANDLER_DEREGISTER(vlan_config, sc->vlan_attach); EVENTHANDLER_DEREGISTER(vlan_unconfig, sc->vlan_detach); /* Shutdown and remove lagg ports */ while ((lp = SLIST_FIRST(&sc->sc_ports)) != NULL) lagg_port_destroy(lp, 1); /* Unhook the aggregation protocol */ lagg_proto_detach(sc); LAGG_UNLOCK_ASSERT(sc); ifmedia_removeall(&sc->sc_media); ether_ifdetach(ifp); if_free(ifp); LAGG_LIST_LOCK(); SLIST_REMOVE(&V_lagg_list, sc, lagg_softc, sc_entries); LAGG_LIST_UNLOCK(); taskqueue_drain(taskqueue_swi, &sc->sc_lladdr_task); LAGG_LOCK_DESTROY(sc); free(sc, M_DEVBUF); } /* * Set link-layer address on the lagg interface itself. * * Set noinline to be dtrace-friendly */ static __noinline void lagg_lladdr(struct lagg_softc *sc, uint8_t *lladdr) { struct ifnet *ifp = sc->sc_ifp; struct lagg_port lp; if (memcmp(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN) == 0) return; LAGG_WLOCK_ASSERT(sc); /* * Set the link layer address on the lagg interface. * lagg_proto_lladdr() notifies the MAC change to * the aggregation protocol. iflladdr_event handler which * may trigger gratuitous ARPs for INET will be handled in * a taskqueue. */ bcopy(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN); lagg_proto_lladdr(sc); /* * Send notification request for lagg interface * itself. Note that new lladdr is already set. */ bzero(&lp, sizeof(lp)); lp.lp_ifp = sc->sc_ifp; lp.lp_softc = sc; /* Do not request lladdr change */ lagg_port_lladdr(&lp, lladdr, LAGG_LLQTYPE_VIRT); } static void lagg_capabilities(struct lagg_softc *sc) { struct lagg_port *lp; int cap = ~0, ena = ~0; u_long hwa = ~0UL; struct ifnet_hw_tsomax hw_tsomax; LAGG_WLOCK_ASSERT(sc); memset(&hw_tsomax, 0, sizeof(hw_tsomax)); /* Get capabilities from the lagg ports */ SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { cap &= lp->lp_ifp->if_capabilities; ena &= lp->lp_ifp->if_capenable; hwa &= lp->lp_ifp->if_hwassist; if_hw_tsomax_common(lp->lp_ifp, &hw_tsomax); } cap = (cap == ~0 ? 0 : cap); ena = (ena == ~0 ? 0 : ena); hwa = (hwa == ~0 ? 0 : hwa); if (sc->sc_ifp->if_capabilities != cap || sc->sc_ifp->if_capenable != ena || sc->sc_ifp->if_hwassist != hwa || if_hw_tsomax_update(sc->sc_ifp, &hw_tsomax) != 0) { sc->sc_ifp->if_capabilities = cap; sc->sc_ifp->if_capenable = ena; sc->sc_ifp->if_hwassist = hwa; getmicrotime(&sc->sc_ifp->if_lastchange); if (sc->sc_ifflags & IFF_DEBUG) if_printf(sc->sc_ifp, "capabilities 0x%08x enabled 0x%08x\n", cap, ena); } } /* * Enqueue interface lladdr notification. * If request is already queued, it is updated. * If setting lladdr is also desired, @do_change has to be set to 1. * * Set noinline to be dtrace-friendly */ static __noinline void lagg_port_lladdr(struct lagg_port *lp, uint8_t *lladdr, lagg_llqtype llq_type) { struct lagg_softc *sc = lp->lp_softc; struct ifnet *ifp = lp->lp_ifp; struct lagg_llq *llq; LAGG_WLOCK_ASSERT(sc); /* * Do not enqueue requests where lladdr is the same for * "physical" interfaces (e.g. ports in lagg) */ if (llq_type == LAGG_LLQTYPE_PHYS && memcmp(IF_LLADDR(ifp), lladdr, ETHER_ADDR_LEN) == 0) return; /* Check to make sure its not already queued to be changed */ SLIST_FOREACH(llq, &sc->sc_llq_head, llq_entries) { if (llq->llq_ifp == ifp) { /* Update lladdr, it may have changed */ bcopy(lladdr, llq->llq_lladdr, ETHER_ADDR_LEN); return; } } llq = malloc(sizeof(struct lagg_llq), M_DEVBUF, M_NOWAIT | M_ZERO); if (llq == NULL) /* XXX what to do */ return; llq->llq_ifp = ifp; llq->llq_type = llq_type; bcopy(lladdr, llq->llq_lladdr, ETHER_ADDR_LEN); /* XXX: We should insert to tail */ SLIST_INSERT_HEAD(&sc->sc_llq_head, llq, llq_entries); taskqueue_enqueue(taskqueue_swi, &sc->sc_lladdr_task); } /* * Set the interface MAC address from a taskqueue to avoid a LOR. * * Set noinline to be dtrace-friendly */ static __noinline void lagg_port_setlladdr(void *arg, int pending) { struct lagg_softc *sc = (struct lagg_softc *)arg; struct lagg_llq *llq, *head; struct ifnet *ifp; /* Grab a local reference of the queue and remove it from the softc */ LAGG_WLOCK(sc); head = SLIST_FIRST(&sc->sc_llq_head); SLIST_FIRST(&sc->sc_llq_head) = NULL; LAGG_WUNLOCK(sc); /* * Traverse the queue and set the lladdr on each ifp. It is safe to do * unlocked as we have the only reference to it. */ for (llq = head; llq != NULL; llq = head) { ifp = llq->llq_ifp; CURVNET_SET(ifp->if_vnet); /* * Set the link layer address on the laggport interface. * Note that if_setlladdr() or iflladdr_event handler * may result in arp transmission / lltable updates. */ if (llq->llq_type == LAGG_LLQTYPE_PHYS) if_setlladdr(ifp, llq->llq_lladdr, ETHER_ADDR_LEN); else EVENTHANDLER_INVOKE(iflladdr_event, ifp); CURVNET_RESTORE(); head = SLIST_NEXT(llq, llq_entries); free(llq, M_DEVBUF); } } static int lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp) { struct lagg_softc *sc_ptr; struct lagg_port *lp, *tlp; int error, i; uint64_t *pval; LAGG_WLOCK_ASSERT(sc); /* Limit the maximal number of lagg ports */ if (sc->sc_count >= LAGG_MAX_PORTS) return (ENOSPC); /* Check if port has already been associated to a lagg */ if (ifp->if_lagg != NULL) { /* Port is already in the current lagg? */ lp = (struct lagg_port *)ifp->if_lagg; if (lp->lp_softc == sc) return (EEXIST); return (EBUSY); } /* XXX Disallow non-ethernet interfaces (this should be any of 802) */ if (ifp->if_type != IFT_ETHER && ifp->if_type != IFT_L2VLAN) return (EPROTONOSUPPORT); /* Allow the first Ethernet member to define the MTU */ if (SLIST_EMPTY(&sc->sc_ports)) sc->sc_ifp->if_mtu = ifp->if_mtu; else if (sc->sc_ifp->if_mtu != ifp->if_mtu) { if_printf(sc->sc_ifp, "invalid MTU for %s\n", ifp->if_xname); return (EINVAL); } if ((lp = malloc(sizeof(struct lagg_port), M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) return (ENOMEM); /* Check if port is a stacked lagg */ LAGG_LIST_LOCK(); SLIST_FOREACH(sc_ptr, &V_lagg_list, sc_entries) { if (ifp == sc_ptr->sc_ifp) { LAGG_LIST_UNLOCK(); free(lp, M_DEVBUF); return (EINVAL); /* XXX disable stacking for the moment, its untested */ #ifdef LAGG_PORT_STACKING lp->lp_flags |= LAGG_PORT_STACK; if (lagg_port_checkstacking(sc_ptr) >= LAGG_MAX_STACKING) { LAGG_LIST_UNLOCK(); free(lp, M_DEVBUF); return (E2BIG); } #endif } } LAGG_LIST_UNLOCK(); /* Change the interface type */ lp->lp_iftype = ifp->if_type; ifp->if_type = IFT_IEEE8023ADLAG; ifp->if_lagg = lp; lp->lp_ioctl = ifp->if_ioctl; ifp->if_ioctl = lagg_port_ioctl; lp->lp_output = ifp->if_output; ifp->if_output = lagg_port_output; lp->lp_ifp = ifp; lp->lp_softc = sc; /* Save port link layer address */ bcopy(IF_LLADDR(ifp), lp->lp_lladdr, ETHER_ADDR_LEN); if (SLIST_EMPTY(&sc->sc_ports)) { sc->sc_primary = lp; /* First port in lagg. Update/notify lagg lladdress */ lagg_lladdr(sc, IF_LLADDR(ifp)); } else { /* * Update link layer address for this port and * send notifications to other subsystems. */ lagg_port_lladdr(lp, IF_LLADDR(sc->sc_ifp), LAGG_LLQTYPE_PHYS); } /* * Insert into the list of ports. * Keep ports sorted by if_index. It is handy, when configuration * is predictable and `ifconfig laggN create ...` command * will lead to the same result each time. */ SLIST_FOREACH(tlp, &sc->sc_ports, lp_entries) { if (tlp->lp_ifp->if_index < ifp->if_index && ( SLIST_NEXT(tlp, lp_entries) == NULL || SLIST_NEXT(tlp, lp_entries)->lp_ifp->if_index > ifp->if_index)) break; } if (tlp != NULL) SLIST_INSERT_AFTER(tlp, lp, lp_entries); else SLIST_INSERT_HEAD(&sc->sc_ports, lp, lp_entries); sc->sc_count++; /* Update lagg capabilities */ lagg_capabilities(sc); lagg_linkstate(sc); /* Read port counters */ pval = lp->port_counters.val; for (i = 0; i < IFCOUNTERS; i++, pval++) *pval = ifp->if_get_counter(ifp, i); /* Add multicast addresses and interface flags to this port */ lagg_ether_cmdmulti(lp, 1); lagg_setflags(lp, 1); if ((error = lagg_proto_addport(sc, lp)) != 0) { /* Remove the port, without calling pr_delport. */ lagg_port_destroy(lp, 0); return (error); } return (0); } #ifdef LAGG_PORT_STACKING static int lagg_port_checkstacking(struct lagg_softc *sc) { struct lagg_softc *sc_ptr; struct lagg_port *lp; int m = 0; LAGG_WLOCK_ASSERT(sc); SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { if (lp->lp_flags & LAGG_PORT_STACK) { sc_ptr = (struct lagg_softc *)lp->lp_ifp->if_softc; m = MAX(m, lagg_port_checkstacking(sc_ptr)); } } return (m + 1); } #endif static int lagg_port_destroy(struct lagg_port *lp, int rundelport) { struct lagg_softc *sc = lp->lp_softc; struct lagg_port *lp_ptr, *lp0; struct lagg_llq *llq; struct ifnet *ifp = lp->lp_ifp; uint64_t *pval, vdiff; int i; LAGG_WLOCK_ASSERT(sc); if (rundelport) lagg_proto_delport(sc, lp); /* * Remove multicast addresses and interface flags from this port and * reset the MAC address, skip if the interface is being detached. */ if (!lp->lp_detaching) { lagg_ether_cmdmulti(lp, 0); lagg_setflags(lp, 0); lagg_port_lladdr(lp, lp->lp_lladdr, LAGG_LLQTYPE_PHYS); } /* Restore interface */ ifp->if_type = lp->lp_iftype; ifp->if_ioctl = lp->lp_ioctl; ifp->if_output = lp->lp_output; ifp->if_lagg = NULL; /* Update detached port counters */ pval = lp->port_counters.val; for (i = 0; i < IFCOUNTERS; i++, pval++) { vdiff = ifp->if_get_counter(ifp, i) - *pval; sc->detached_counters.val[i] += vdiff; } /* Finally, remove the port from the lagg */ SLIST_REMOVE(&sc->sc_ports, lp, lagg_port, lp_entries); sc->sc_count--; /* Update the primary interface */ if (lp == sc->sc_primary) { uint8_t lladdr[ETHER_ADDR_LEN]; if ((lp0 = SLIST_FIRST(&sc->sc_ports)) == NULL) { bzero(&lladdr, ETHER_ADDR_LEN); } else { bcopy(lp0->lp_lladdr, lladdr, ETHER_ADDR_LEN); } lagg_lladdr(sc, lladdr); /* Mark lp0 as new primary */ sc->sc_primary = lp0; /* * Enqueue lladdr update/notification for each port * (new primary needs update as well, to switch from * old lladdr to its 'real' one). */ SLIST_FOREACH(lp_ptr, &sc->sc_ports, lp_entries) lagg_port_lladdr(lp_ptr, lladdr, LAGG_LLQTYPE_PHYS); } /* Remove any pending lladdr changes from the queue */ if (lp->lp_detaching) { SLIST_FOREACH(llq, &sc->sc_llq_head, llq_entries) { if (llq->llq_ifp == ifp) { SLIST_REMOVE(&sc->sc_llq_head, llq, lagg_llq, llq_entries); free(llq, M_DEVBUF); break; /* Only appears once */ } } } if (lp->lp_ifflags) if_printf(ifp, "%s: lp_ifflags unclean\n", __func__); free(lp, M_DEVBUF); /* Update lagg capabilities */ lagg_capabilities(sc); lagg_linkstate(sc); return (0); } static int lagg_port_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct lagg_reqport *rp = (struct lagg_reqport *)data; struct lagg_softc *sc; struct lagg_port *lp = NULL; int error = 0; struct rm_priotracker tracker; /* Should be checked by the caller */ if (ifp->if_type != IFT_IEEE8023ADLAG || (lp = ifp->if_lagg) == NULL || (sc = lp->lp_softc) == NULL) goto fallback; switch (cmd) { case SIOCGLAGGPORT: if (rp->rp_portname[0] == '\0' || ifunit(rp->rp_portname) != ifp) { error = EINVAL; break; } LAGG_RLOCK(sc, &tracker); if ((lp = ifp->if_lagg) == NULL || lp->lp_softc != sc) { error = ENOENT; LAGG_RUNLOCK(sc, &tracker); break; } lagg_port2req(lp, rp); LAGG_RUNLOCK(sc, &tracker); break; case SIOCSIFCAP: if (lp->lp_ioctl == NULL) { error = EINVAL; break; } error = (*lp->lp_ioctl)(ifp, cmd, data); if (error) break; /* Update lagg interface capabilities */ LAGG_WLOCK(sc); lagg_capabilities(sc); LAGG_WUNLOCK(sc); break; case SIOCSIFMTU: /* Do not allow the MTU to be changed once joined */ error = EINVAL; break; default: goto fallback; } return (error); fallback: if (lp->lp_ioctl != NULL) return ((*lp->lp_ioctl)(ifp, cmd, data)); return (EINVAL); } /* * Requests counter @cnt data. * * Counter value is calculated the following way: * 1) for each port, sum difference between current and "initial" measurements. * 2) add lagg logical interface counters. * 3) add data from detached_counters array. * * We also do the following things on ports attach/detach: * 1) On port attach we store all counters it has into port_counter array. * 2) On port detach we add the different between "initial" and * current counters data to detached_counters array. */ static uint64_t lagg_get_counter(struct ifnet *ifp, ift_counter cnt) { struct lagg_softc *sc; struct lagg_port *lp; struct ifnet *lpifp; struct rm_priotracker tracker; uint64_t newval, oldval, vsum; /* Revise this when we've got non-generic counters. */ KASSERT(cnt < IFCOUNTERS, ("%s: invalid cnt %d", __func__, cnt)); sc = (struct lagg_softc *)ifp->if_softc; LAGG_RLOCK(sc, &tracker); vsum = 0; SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { /* Saved attached value */ oldval = lp->port_counters.val[cnt]; /* current value */ lpifp = lp->lp_ifp; newval = lpifp->if_get_counter(lpifp, cnt); /* Calculate diff and save new */ vsum += newval - oldval; } /* * Add counter data which might be added by upper * layer protocols operating on logical interface. */ vsum += if_get_counter_default(ifp, cnt); /* * Add counter data from detached ports counters */ vsum += sc->detached_counters.val[cnt]; LAGG_RUNLOCK(sc, &tracker); return (vsum); } /* * For direct output to child ports. */ static int lagg_port_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, struct route *ro) { struct lagg_port *lp = ifp->if_lagg; switch (dst->sa_family) { case pseudo_AF_HDRCMPLT: case AF_UNSPEC: return ((*lp->lp_output)(ifp, m, dst, ro)); } /* drop any other frames */ m_freem(m); return (ENETDOWN); } static void lagg_port_ifdetach(void *arg __unused, struct ifnet *ifp) { struct lagg_port *lp; struct lagg_softc *sc; if ((lp = ifp->if_lagg) == NULL) return; /* If the ifnet is just being renamed, don't do anything. */ if (ifp->if_flags & IFF_RENAMING) return; sc = lp->lp_softc; LAGG_WLOCK(sc); lp->lp_detaching = 1; lagg_port_destroy(lp, 1); LAGG_WUNLOCK(sc); } static void lagg_port2req(struct lagg_port *lp, struct lagg_reqport *rp) { struct lagg_softc *sc = lp->lp_softc; strlcpy(rp->rp_ifname, sc->sc_ifname, sizeof(rp->rp_ifname)); strlcpy(rp->rp_portname, lp->lp_ifp->if_xname, sizeof(rp->rp_portname)); rp->rp_prio = lp->lp_prio; rp->rp_flags = lp->lp_flags; lagg_proto_portreq(sc, lp, &rp->rp_psc); /* Add protocol specific flags */ switch (sc->sc_proto) { case LAGG_PROTO_FAILOVER: if (lp == sc->sc_primary) rp->rp_flags |= LAGG_PORT_MASTER; if (lp == lagg_link_active(sc, sc->sc_primary)) rp->rp_flags |= LAGG_PORT_ACTIVE; break; case LAGG_PROTO_ROUNDROBIN: case LAGG_PROTO_LOADBALANCE: case LAGG_PROTO_BROADCAST: if (LAGG_PORTACTIVE(lp)) rp->rp_flags |= LAGG_PORT_ACTIVE; break; case LAGG_PROTO_LACP: /* LACP has a different definition of active */ if (lacp_isactive(lp)) rp->rp_flags |= LAGG_PORT_ACTIVE; if (lacp_iscollecting(lp)) rp->rp_flags |= LAGG_PORT_COLLECTING; if (lacp_isdistributing(lp)) rp->rp_flags |= LAGG_PORT_DISTRIBUTING; break; } } static void lagg_init(void *xsc) { struct lagg_softc *sc = (struct lagg_softc *)xsc; struct ifnet *ifp = sc->sc_ifp; struct lagg_port *lp; if (ifp->if_drv_flags & IFF_DRV_RUNNING) return; LAGG_WLOCK(sc); ifp->if_drv_flags |= IFF_DRV_RUNNING; /* * Update the port lladdrs if needed. * This might be if_setlladdr() notification * that lladdr has been changed. */ SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) lagg_port_lladdr(lp, IF_LLADDR(ifp), LAGG_LLQTYPE_PHYS); lagg_proto_init(sc); LAGG_WUNLOCK(sc); } static void lagg_stop(struct lagg_softc *sc) { struct ifnet *ifp = sc->sc_ifp; LAGG_WLOCK_ASSERT(sc); if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) return; ifp->if_drv_flags &= ~IFF_DRV_RUNNING; lagg_proto_stop(sc); } static int lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; struct lagg_reqall *ra = (struct lagg_reqall *)data; struct lagg_reqopts *ro = (struct lagg_reqopts *)data; struct lagg_reqport *rp = (struct lagg_reqport *)data, rpbuf; struct lagg_reqflags *rf = (struct lagg_reqflags *)data; struct ifreq *ifr = (struct ifreq *)data; struct lagg_port *lp; struct ifnet *tpif; struct thread *td = curthread; char *buf, *outbuf; int count, buflen, len, error = 0; struct rm_priotracker tracker; bzero(&rpbuf, sizeof(rpbuf)); switch (cmd) { case SIOCGLAGG: LAGG_RLOCK(sc, &tracker); count = 0; SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) count++; buflen = count * sizeof(struct lagg_reqport); LAGG_RUNLOCK(sc, &tracker); outbuf = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO); LAGG_RLOCK(sc, &tracker); ra->ra_proto = sc->sc_proto; lagg_proto_request(sc, &ra->ra_psc); count = 0; buf = outbuf; len = min(ra->ra_size, buflen); SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { if (len < sizeof(rpbuf)) break; lagg_port2req(lp, &rpbuf); memcpy(buf, &rpbuf, sizeof(rpbuf)); count++; buf += sizeof(rpbuf); len -= sizeof(rpbuf); } LAGG_RUNLOCK(sc, &tracker); ra->ra_ports = count; ra->ra_size = count * sizeof(rpbuf); error = copyout(outbuf, ra->ra_port, ra->ra_size); free(outbuf, M_TEMP); break; case SIOCSLAGG: error = priv_check(td, PRIV_NET_LAGG); if (error) break; if (ra->ra_proto < 1 || ra->ra_proto >= LAGG_PROTO_MAX) { error = EPROTONOSUPPORT; break; } LAGG_WLOCK(sc); lagg_proto_detach(sc); LAGG_UNLOCK_ASSERT(sc); lagg_proto_attach(sc, ra->ra_proto); break; case SIOCGLAGGOPTS: ro->ro_opts = sc->sc_opts; if (sc->sc_proto == LAGG_PROTO_LACP) { struct lacp_softc *lsc; lsc = (struct lacp_softc *)sc->sc_psc; if (lsc->lsc_debug.lsc_tx_test != 0) ro->ro_opts |= LAGG_OPT_LACP_TXTEST; if (lsc->lsc_debug.lsc_rx_test != 0) ro->ro_opts |= LAGG_OPT_LACP_RXTEST; if (lsc->lsc_strict_mode != 0) ro->ro_opts |= LAGG_OPT_LACP_STRICT; if (lsc->lsc_fast_timeout != 0) ro->ro_opts |= LAGG_OPT_LACP_TIMEOUT; ro->ro_active = sc->sc_active; } else { ro->ro_active = 0; SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) ro->ro_active += LAGG_PORTACTIVE(lp); } ro->ro_flapping = sc->sc_flapping; ro->ro_flowid_shift = sc->flowid_shift; break; case SIOCSLAGGOPTS: error = priv_check(td, PRIV_NET_LAGG); if (error) break; if (ro->ro_opts == 0) break; /* * Set options. LACP options are stored in sc->sc_psc, * not in sc_opts. */ int valid, lacp; switch (ro->ro_opts) { case LAGG_OPT_USE_FLOWID: case -LAGG_OPT_USE_FLOWID: case LAGG_OPT_FLOWIDSHIFT: valid = 1; lacp = 0; break; case LAGG_OPT_LACP_TXTEST: case -LAGG_OPT_LACP_TXTEST: case LAGG_OPT_LACP_RXTEST: case -LAGG_OPT_LACP_RXTEST: case LAGG_OPT_LACP_STRICT: case -LAGG_OPT_LACP_STRICT: case LAGG_OPT_LACP_TIMEOUT: case -LAGG_OPT_LACP_TIMEOUT: valid = lacp = 1; break; default: valid = lacp = 0; break; } LAGG_WLOCK(sc); if (valid == 0 || (lacp == 1 && sc->sc_proto != LAGG_PROTO_LACP)) { /* Invalid combination of options specified. */ error = EINVAL; LAGG_WUNLOCK(sc); break; /* Return from SIOCSLAGGOPTS. */ } /* * Store new options into sc->sc_opts except for * FLOWIDSHIFT and LACP options. */ if (lacp == 0) { if (ro->ro_opts == LAGG_OPT_FLOWIDSHIFT) sc->flowid_shift = ro->ro_flowid_shift; else if (ro->ro_opts > 0) sc->sc_opts |= ro->ro_opts; else sc->sc_opts &= ~ro->ro_opts; } else { struct lacp_softc *lsc; struct lacp_port *lp; lsc = (struct lacp_softc *)sc->sc_psc; switch (ro->ro_opts) { case LAGG_OPT_LACP_TXTEST: lsc->lsc_debug.lsc_tx_test = 1; break; case -LAGG_OPT_LACP_TXTEST: lsc->lsc_debug.lsc_tx_test = 0; break; case LAGG_OPT_LACP_RXTEST: lsc->lsc_debug.lsc_rx_test = 1; break; case -LAGG_OPT_LACP_RXTEST: lsc->lsc_debug.lsc_rx_test = 0; break; case LAGG_OPT_LACP_STRICT: lsc->lsc_strict_mode = 1; break; case -LAGG_OPT_LACP_STRICT: lsc->lsc_strict_mode = 0; break; case LAGG_OPT_LACP_TIMEOUT: LACP_LOCK(lsc); LIST_FOREACH(lp, &lsc->lsc_ports, lp_next) lp->lp_state |= LACP_STATE_TIMEOUT; LACP_UNLOCK(lsc); lsc->lsc_fast_timeout = 1; break; case -LAGG_OPT_LACP_TIMEOUT: LACP_LOCK(lsc); LIST_FOREACH(lp, &lsc->lsc_ports, lp_next) lp->lp_state &= ~LACP_STATE_TIMEOUT; LACP_UNLOCK(lsc); lsc->lsc_fast_timeout = 0; break; } } LAGG_WUNLOCK(sc); break; case SIOCGLAGGFLAGS: rf->rf_flags = 0; LAGG_RLOCK(sc, &tracker); if (sc->sc_flags & MBUF_HASHFLAG_L2) rf->rf_flags |= LAGG_F_HASHL2; if (sc->sc_flags & MBUF_HASHFLAG_L3) rf->rf_flags |= LAGG_F_HASHL3; if (sc->sc_flags & MBUF_HASHFLAG_L4) rf->rf_flags |= LAGG_F_HASHL4; LAGG_RUNLOCK(sc, &tracker); break; case SIOCSLAGGHASH: error = priv_check(td, PRIV_NET_LAGG); if (error) break; if ((rf->rf_flags & LAGG_F_HASHMASK) == 0) { error = EINVAL; break; } LAGG_WLOCK(sc); sc->sc_flags = 0; if (rf->rf_flags & LAGG_F_HASHL2) sc->sc_flags |= MBUF_HASHFLAG_L2; if (rf->rf_flags & LAGG_F_HASHL3) sc->sc_flags |= MBUF_HASHFLAG_L3; if (rf->rf_flags & LAGG_F_HASHL4) sc->sc_flags |= MBUF_HASHFLAG_L4; LAGG_WUNLOCK(sc); break; case SIOCGLAGGPORT: if (rp->rp_portname[0] == '\0' || (tpif = ifunit(rp->rp_portname)) == NULL) { error = EINVAL; break; } LAGG_RLOCK(sc, &tracker); if ((lp = (struct lagg_port *)tpif->if_lagg) == NULL || lp->lp_softc != sc) { error = ENOENT; LAGG_RUNLOCK(sc, &tracker); break; } lagg_port2req(lp, rp); LAGG_RUNLOCK(sc, &tracker); break; case SIOCSLAGGPORT: error = priv_check(td, PRIV_NET_LAGG); if (error) break; if (rp->rp_portname[0] == '\0' || (tpif = ifunit(rp->rp_portname)) == NULL) { error = EINVAL; break; } #ifdef INET6 /* * A laggport interface should not have inet6 address * because two interfaces with a valid link-local * scope zone must not be merged in any form. This * restriction is needed to prevent violation of * link-local scope zone. Attempts to add a laggport * interface which has inet6 addresses triggers * removal of all inet6 addresses on the member * interface. */ if (in6ifa_llaonifp(tpif)) { in6_ifdetach(tpif); if_printf(sc->sc_ifp, "IPv6 addresses on %s have been removed " "before adding it as a member to prevent " "IPv6 address scope violation.\n", tpif->if_xname); } #endif LAGG_WLOCK(sc); error = lagg_port_create(sc, tpif); LAGG_WUNLOCK(sc); break; case SIOCSLAGGDELPORT: error = priv_check(td, PRIV_NET_LAGG); if (error) break; if (rp->rp_portname[0] == '\0' || (tpif = ifunit(rp->rp_portname)) == NULL) { error = EINVAL; break; } LAGG_WLOCK(sc); if ((lp = (struct lagg_port *)tpif->if_lagg) == NULL || lp->lp_softc != sc) { error = ENOENT; LAGG_WUNLOCK(sc); break; } error = lagg_port_destroy(lp, 1); LAGG_WUNLOCK(sc); break; case SIOCSIFFLAGS: /* Set flags on ports too */ LAGG_WLOCK(sc); SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { lagg_setflags(lp, 1); } LAGG_WUNLOCK(sc); if (!(ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING)) { /* * If interface is marked down and it is running, * then stop and disable it. */ LAGG_WLOCK(sc); lagg_stop(sc); LAGG_WUNLOCK(sc); } else if ((ifp->if_flags & IFF_UP) && !(ifp->if_drv_flags & IFF_DRV_RUNNING)) { /* * If interface is marked up and it is stopped, then * start it. */ (*ifp->if_init)(sc); } break; case SIOCADDMULTI: case SIOCDELMULTI: LAGG_WLOCK(sc); error = lagg_ether_setmulti(sc); LAGG_WUNLOCK(sc); break; case SIOCSIFMEDIA: case SIOCGIFMEDIA: error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); break; case SIOCSIFCAP: case SIOCSIFMTU: /* Do not allow the MTU or caps to be directly changed */ error = EINVAL; break; default: error = ether_ioctl(ifp, cmd, data); break; } return (error); } static int lagg_ether_setmulti(struct lagg_softc *sc) { struct lagg_port *lp; LAGG_WLOCK_ASSERT(sc); SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { /* First, remove any existing filter entries. */ lagg_ether_cmdmulti(lp, 0); /* copy all addresses from the lagg interface to the port */ lagg_ether_cmdmulti(lp, 1); } return (0); } static int lagg_ether_cmdmulti(struct lagg_port *lp, int set) { struct lagg_softc *sc = lp->lp_softc; struct ifnet *ifp = lp->lp_ifp; struct ifnet *scifp = sc->sc_ifp; struct lagg_mc *mc; struct ifmultiaddr *ifma; int error; LAGG_WLOCK_ASSERT(sc); if (set) { IF_ADDR_WLOCK(scifp); TAILQ_FOREACH(ifma, &scifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; mc = malloc(sizeof(struct lagg_mc), M_DEVBUF, M_NOWAIT); if (mc == NULL) { IF_ADDR_WUNLOCK(scifp); return (ENOMEM); } bcopy(ifma->ifma_addr, &mc->mc_addr, ifma->ifma_addr->sa_len); mc->mc_addr.sdl_index = ifp->if_index; mc->mc_ifma = NULL; SLIST_INSERT_HEAD(&lp->lp_mc_head, mc, mc_entries); } IF_ADDR_WUNLOCK(scifp); SLIST_FOREACH (mc, &lp->lp_mc_head, mc_entries) { error = if_addmulti(ifp, (struct sockaddr *)&mc->mc_addr, &mc->mc_ifma); if (error) return (error); } } else { while ((mc = SLIST_FIRST(&lp->lp_mc_head)) != NULL) { SLIST_REMOVE(&lp->lp_mc_head, mc, lagg_mc, mc_entries); if (mc->mc_ifma && !lp->lp_detaching) if_delmulti_ifma(mc->mc_ifma); free(mc, M_DEVBUF); } } return (0); } /* Handle a ref counted flag that should be set on the lagg port as well */ static int lagg_setflag(struct lagg_port *lp, int flag, int status, int (*func)(struct ifnet *, int)) { struct lagg_softc *sc = lp->lp_softc; struct ifnet *scifp = sc->sc_ifp; struct ifnet *ifp = lp->lp_ifp; int error; LAGG_WLOCK_ASSERT(sc); status = status ? (scifp->if_flags & flag) : 0; /* Now "status" contains the flag value or 0 */ /* * See if recorded ports status is different from what * we want it to be. If it is, flip it. We record ports * status in lp_ifflags so that we won't clear ports flag * we haven't set. In fact, we don't clear or set ports * flags directly, but get or release references to them. * That's why we can be sure that recorded flags still are * in accord with actual ports flags. */ if (status != (lp->lp_ifflags & flag)) { error = (*func)(ifp, status); if (error) return (error); lp->lp_ifflags &= ~flag; lp->lp_ifflags |= status; } return (0); } /* * Handle IFF_* flags that require certain changes on the lagg port * if "status" is true, update ports flags respective to the lagg * if "status" is false, forcedly clear the flags set on port. */ static int lagg_setflags(struct lagg_port *lp, int status) { int error, i; for (i = 0; lagg_pflags[i].flag; i++) { error = lagg_setflag(lp, lagg_pflags[i].flag, status, lagg_pflags[i].func); if (error) return (error); } return (0); } static int lagg_transmit(struct ifnet *ifp, struct mbuf *m) { struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; int error, len, mcast; struct rm_priotracker tracker; len = m->m_pkthdr.len; mcast = (m->m_flags & (M_MCAST | M_BCAST)) ? 1 : 0; LAGG_RLOCK(sc, &tracker); /* We need a Tx algorithm and at least one port */ if (sc->sc_proto == LAGG_PROTO_NONE || sc->sc_count == 0) { LAGG_RUNLOCK(sc, &tracker); m_freem(m); if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); return (ENXIO); } ETHER_BPF_MTAP(ifp, m); error = lagg_proto_start(sc, m); LAGG_RUNLOCK(sc, &tracker); if (error != 0) if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); return (error); } /* * The ifp->if_qflush entry point for lagg(4) is no-op. */ static void lagg_qflush(struct ifnet *ifp __unused) { } static struct mbuf * lagg_input(struct ifnet *ifp, struct mbuf *m) { struct lagg_port *lp = ifp->if_lagg; struct lagg_softc *sc = lp->lp_softc; struct ifnet *scifp = sc->sc_ifp; struct rm_priotracker tracker; LAGG_RLOCK(sc, &tracker); if ((scifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || (lp->lp_flags & LAGG_PORT_DISABLED) || sc->sc_proto == LAGG_PROTO_NONE) { LAGG_RUNLOCK(sc, &tracker); m_freem(m); return (NULL); } ETHER_BPF_MTAP(scifp, m); if (lp->lp_detaching != 0) { m_freem(m); m = NULL; } else m = lagg_proto_input(sc, lp, m); if (m != NULL) { if (scifp->if_flags & IFF_MONITOR) { m_freem(m); m = NULL; } } LAGG_RUNLOCK(sc, &tracker); return (m); } static int lagg_media_change(struct ifnet *ifp) { struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; if (sc->sc_ifflags & IFF_DEBUG) printf("%s\n", __func__); /* Ignore */ return (0); } static void lagg_media_status(struct ifnet *ifp, struct ifmediareq *imr) { struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; struct lagg_port *lp; struct rm_priotracker tracker; imr->ifm_status = IFM_AVALID; imr->ifm_active = IFM_ETHER | IFM_AUTO; LAGG_RLOCK(sc, &tracker); SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { if (LAGG_PORTACTIVE(lp)) imr->ifm_status |= IFM_ACTIVE; } LAGG_RUNLOCK(sc, &tracker); } static void lagg_linkstate(struct lagg_softc *sc) { struct lagg_port *lp; int new_link = LINK_STATE_DOWN; uint64_t speed; /* Our link is considered up if at least one of our ports is active */ SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { if (lp->lp_ifp->if_link_state == LINK_STATE_UP) { new_link = LINK_STATE_UP; break; } } + if_link_state_change(sc->sc_ifp, new_link); - /* - * Force state change to ensure ifnet_link_event is generated allowing - * protocols to notify other nodes of potential address move. - */ - if_link_state_change_cond(sc->sc_ifp, new_link, 1); - /* Update if_baudrate to reflect the max possible speed */ switch (sc->sc_proto) { case LAGG_PROTO_FAILOVER: sc->sc_ifp->if_baudrate = sc->sc_primary != NULL ? sc->sc_primary->lp_ifp->if_baudrate : 0; break; case LAGG_PROTO_ROUNDROBIN: case LAGG_PROTO_LOADBALANCE: case LAGG_PROTO_BROADCAST: speed = 0; SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) speed += lp->lp_ifp->if_baudrate; sc->sc_ifp->if_baudrate = speed; break; case LAGG_PROTO_LACP: /* LACP updates if_baudrate itself */ break; } } static void -lagg_port_state(struct ifnet *ifp) +lagg_port_state(struct ifnet *ifp, int state) { struct lagg_port *lp = (struct lagg_port *)ifp->if_lagg; struct lagg_softc *sc = NULL; if (lp != NULL) sc = lp->lp_softc; if (sc == NULL) return; LAGG_WLOCK(sc); lagg_linkstate(sc); lagg_proto_linkstate(sc, lp); LAGG_WUNLOCK(sc); } -static struct lagg_port * +struct lagg_port * lagg_link_active(struct lagg_softc *sc, struct lagg_port *lp) { struct lagg_port *lp_next, *rval = NULL; // int new_link = LINK_STATE_DOWN; LAGG_RLOCK_ASSERT(sc); /* * Search a port which reports an active link state. */ if (lp == NULL) goto search; if (LAGG_PORTACTIVE(lp)) { rval = lp; goto found; } if ((lp_next = SLIST_NEXT(lp, lp_entries)) != NULL && LAGG_PORTACTIVE(lp_next)) { rval = lp_next; goto found; } search: SLIST_FOREACH(lp_next, &sc->sc_ports, lp_entries) { if (LAGG_PORTACTIVE(lp_next)) { rval = lp_next; goto found; } } found: if (rval != NULL) { /* * The IEEE 802.1D standard assumes that a lagg with * multiple ports is always full duplex. This is valid * for load sharing laggs and if at least two links * are active. Unfortunately, checking the latter would * be too expensive at this point. XXX if ((sc->sc_capabilities & IFCAP_LAGG_FULLDUPLEX) && (sc->sc_count > 1)) new_link = LINK_STATE_FULL_DUPLEX; else new_link = rval->lp_link_state; */ } return (rval); } int lagg_enqueue(struct ifnet *ifp, struct mbuf *m) { return (ifp->if_transmit)(ifp, m); } /* * Simple round robin aggregation */ static void lagg_rr_attach(struct lagg_softc *sc) { sc->sc_capabilities = IFCAP_LAGG_FULLDUPLEX; sc->sc_seq = 0; } static int lagg_rr_start(struct lagg_softc *sc, struct mbuf *m) { struct lagg_port *lp; uint32_t p; p = atomic_fetchadd_32(&sc->sc_seq, 1); p %= sc->sc_count; lp = SLIST_FIRST(&sc->sc_ports); while (p--) lp = SLIST_NEXT(lp, lp_entries); /* * Check the port's link state. This will return the next active * port if the link is down or the port is NULL. */ if ((lp = lagg_link_active(sc, lp)) == NULL) { m_freem(m); return (ENETDOWN); } /* Send mbuf */ return (lagg_enqueue(lp->lp_ifp, m)); } static struct mbuf * lagg_rr_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m) { struct ifnet *ifp = sc->sc_ifp; /* Just pass in the packet to our lagg device */ m->m_pkthdr.rcvif = ifp; return (m); } /* * Broadcast mode */ static int lagg_bcast_start(struct lagg_softc *sc, struct mbuf *m) { int active_ports = 0; int errors = 0; int ret; struct lagg_port *lp, *last = NULL; struct mbuf *m0; SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { if (!LAGG_PORTACTIVE(lp)) continue; active_ports++; if (last != NULL) { m0 = m_copym(m, 0, M_COPYALL, M_NOWAIT); if (m0 == NULL) { ret = ENOBUFS; errors++; break; } ret = lagg_enqueue(last->lp_ifp, m0); if (ret != 0) errors++; } last = lp; } if (last == NULL) { m_freem(m); return (ENOENT); } if ((last = lagg_link_active(sc, last)) == NULL) { m_freem(m); return (ENETDOWN); } ret = lagg_enqueue(last->lp_ifp, m); if (ret != 0) errors++; if (errors == 0) return (ret); return (0); } static struct mbuf* lagg_bcast_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m) { struct ifnet *ifp = sc->sc_ifp; /* Just pass in the packet to our lagg device */ m->m_pkthdr.rcvif = ifp; return (m); } /* * Active failover */ static int lagg_fail_start(struct lagg_softc *sc, struct mbuf *m) { struct lagg_port *lp; /* Use the master port if active or the next available port */ if ((lp = lagg_link_active(sc, sc->sc_primary)) == NULL) { m_freem(m); return (ENETDOWN); } /* Send mbuf */ return (lagg_enqueue(lp->lp_ifp, m)); } static struct mbuf * lagg_fail_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m) { struct ifnet *ifp = sc->sc_ifp; struct lagg_port *tmp_tp; if (lp == sc->sc_primary || V_lagg_failover_rx_all) { m->m_pkthdr.rcvif = ifp; return (m); } if (!LAGG_PORTACTIVE(sc->sc_primary)) { tmp_tp = lagg_link_active(sc, sc->sc_primary); /* * If tmp_tp is null, we've recieved a packet when all * our links are down. Weird, but process it anyways. */ if ((tmp_tp == NULL || tmp_tp == lp)) { m->m_pkthdr.rcvif = ifp; return (m); } } m_freem(m); return (NULL); } /* * Loadbalancing */ static void lagg_lb_attach(struct lagg_softc *sc) { struct lagg_port *lp; struct lagg_lb *lb; lb = malloc(sizeof(struct lagg_lb), M_DEVBUF, M_WAITOK | M_ZERO); sc->sc_capabilities = IFCAP_LAGG_FULLDUPLEX; lb->lb_key = m_ether_tcpip_hash_init(); sc->sc_psc = lb; SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) lagg_lb_port_create(lp); } static void lagg_lb_detach(struct lagg_softc *sc) { struct lagg_lb *lb; lb = (struct lagg_lb *)sc->sc_psc; LAGG_WUNLOCK(sc); if (lb != NULL) free(lb, M_DEVBUF); } static int lagg_lb_porttable(struct lagg_softc *sc, struct lagg_port *lp) { struct lagg_lb *lb = (struct lagg_lb *)sc->sc_psc; struct lagg_port *lp_next; int i = 0; bzero(&lb->lb_ports, sizeof(lb->lb_ports)); SLIST_FOREACH(lp_next, &sc->sc_ports, lp_entries) { if (lp_next == lp) continue; if (i >= LAGG_MAX_PORTS) return (EINVAL); if (sc->sc_ifflags & IFF_DEBUG) printf("%s: port %s at index %d\n", sc->sc_ifname, lp_next->lp_ifp->if_xname, i); lb->lb_ports[i++] = lp_next; } return (0); } static int lagg_lb_port_create(struct lagg_port *lp) { struct lagg_softc *sc = lp->lp_softc; return (lagg_lb_porttable(sc, NULL)); } static void lagg_lb_port_destroy(struct lagg_port *lp) { struct lagg_softc *sc = lp->lp_softc; lagg_lb_porttable(sc, lp); } static int lagg_lb_start(struct lagg_softc *sc, struct mbuf *m) { struct lagg_lb *lb = (struct lagg_lb *)sc->sc_psc; struct lagg_port *lp = NULL; uint32_t p = 0; if ((sc->sc_opts & LAGG_OPT_USE_FLOWID) && M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) p = m->m_pkthdr.flowid >> sc->flowid_shift; else p = m_ether_tcpip_hash(sc->sc_flags, m, lb->lb_key); p %= sc->sc_count; lp = lb->lb_ports[p]; /* * Check the port's link state. This will return the next active * port if the link is down or the port is NULL. */ if ((lp = lagg_link_active(sc, lp)) == NULL) { m_freem(m); return (ENETDOWN); } /* Send mbuf */ return (lagg_enqueue(lp->lp_ifp, m)); } static struct mbuf * lagg_lb_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m) { struct ifnet *ifp = sc->sc_ifp; /* Just pass in the packet to our lagg device */ m->m_pkthdr.rcvif = ifp; return (m); } /* * 802.3ad LACP */ static void lagg_lacp_attach(struct lagg_softc *sc) { struct lagg_port *lp; lacp_attach(sc); SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) lacp_port_create(lp); } static void lagg_lacp_detach(struct lagg_softc *sc) { struct lagg_port *lp; void *psc; SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) lacp_port_destroy(lp); psc = sc->sc_psc; sc->sc_psc = NULL; LAGG_WUNLOCK(sc); lacp_detach(psc); } static void lagg_lacp_lladdr(struct lagg_softc *sc) { struct lagg_port *lp; /* purge all the lacp ports */ SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) lacp_port_destroy(lp); /* add them back in */ SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) lacp_port_create(lp); } static int lagg_lacp_start(struct lagg_softc *sc, struct mbuf *m) { struct lagg_port *lp; lp = lacp_select_tx_port(sc, m); if (lp == NULL) { m_freem(m); return (ENETDOWN); } /* Send mbuf */ return (lagg_enqueue(lp->lp_ifp, m)); } static struct mbuf * lagg_lacp_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m) { struct ifnet *ifp = sc->sc_ifp; struct ether_header *eh; u_short etype; eh = mtod(m, struct ether_header *); etype = ntohs(eh->ether_type); /* Tap off LACP control messages */ if ((m->m_flags & M_VLANTAG) == 0 && etype == ETHERTYPE_SLOW) { m = lacp_input(lp, m); if (m == NULL) return (NULL); } /* * If the port is not collecting or not in the active aggregator then * free and return. */ if (lacp_iscollecting(lp) == 0 || lacp_isactive(lp) == 0) { m_freem(m); return (NULL); } m->m_pkthdr.rcvif = ifp; return (m); } Index: user/alc/PQ_LAUNDRY/sys/net/if_lagg.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/net/if_lagg.h (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/net/if_lagg.h (revision 292449) @@ -1,292 +1,292 @@ /* $OpenBSD: if_trunk.h,v 1.11 2007/01/31 06:20:19 reyk Exp $ */ /* * Copyright (c) 2005, 2006 Reyk Floeter * * 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. * * $FreeBSD$ */ #ifndef _NET_LAGG_H #define _NET_LAGG_H /* * Global definitions */ #define LAGG_MAX_PORTS 32 /* logically */ #define LAGG_MAX_NAMESIZE 32 /* name of a protocol */ #define LAGG_MAX_STACKING 4 /* maximum number of stacked laggs */ /* Lagg flags */ #define LAGG_F_HASHL2 0x00000001 /* hash layer 2 */ #define LAGG_F_HASHL3 0x00000002 /* hash layer 3 */ #define LAGG_F_HASHL4 0x00000004 /* hash layer 4 */ #define LAGG_F_HASHMASK 0x00000007 /* Port flags */ #define LAGG_PORT_SLAVE 0x00000000 /* normal enslaved port */ #define LAGG_PORT_MASTER 0x00000001 /* primary port */ #define LAGG_PORT_STACK 0x00000002 /* stacked lagg port */ #define LAGG_PORT_ACTIVE 0x00000004 /* port is active */ #define LAGG_PORT_COLLECTING 0x00000008 /* port is receiving frames */ #define LAGG_PORT_DISTRIBUTING 0x00000010 /* port is sending frames */ #define LAGG_PORT_DISABLED 0x00000020 /* port is disabled */ #define LAGG_PORT_BITS "\20\01MASTER\02STACK\03ACTIVE\04COLLECTING" \ "\05DISTRIBUTING\06DISABLED" /* Supported lagg PROTOs */ typedef enum { LAGG_PROTO_NONE = 0, /* no lagg protocol defined */ LAGG_PROTO_ROUNDROBIN, /* simple round robin */ LAGG_PROTO_FAILOVER, /* active failover */ LAGG_PROTO_LOADBALANCE, /* loadbalance */ LAGG_PROTO_LACP, /* 802.3ad lacp */ LAGG_PROTO_BROADCAST, /* broadcast */ LAGG_PROTO_MAX, } lagg_proto; struct lagg_protos { const char *lpr_name; lagg_proto lpr_proto; }; #define LAGG_PROTO_DEFAULT LAGG_PROTO_FAILOVER #define LAGG_PROTOS { \ { "failover", LAGG_PROTO_FAILOVER }, \ { "lacp", LAGG_PROTO_LACP }, \ { "loadbalance", LAGG_PROTO_LOADBALANCE }, \ { "roundrobin", LAGG_PROTO_ROUNDROBIN }, \ { "broadcast", LAGG_PROTO_BROADCAST }, \ { "none", LAGG_PROTO_NONE }, \ { "default", LAGG_PROTO_DEFAULT } \ } /* * lagg ioctls. */ /* * LACP current operational parameters structure. */ struct lacp_opreq { uint16_t actor_prio; uint8_t actor_mac[ETHER_ADDR_LEN]; uint16_t actor_key; uint16_t actor_portprio; uint16_t actor_portno; uint8_t actor_state; uint16_t partner_prio; uint8_t partner_mac[ETHER_ADDR_LEN]; uint16_t partner_key; uint16_t partner_portprio; uint16_t partner_portno; uint8_t partner_state; }; /* lagg port settings */ struct lagg_reqport { char rp_ifname[IFNAMSIZ]; /* name of the lagg */ char rp_portname[IFNAMSIZ]; /* name of the port */ u_int32_t rp_prio; /* port priority */ u_int32_t rp_flags; /* port flags */ union { struct lacp_opreq rpsc_lacp; } rp_psc; #define rp_lacpreq rp_psc.rpsc_lacp }; #define SIOCGLAGGPORT _IOWR('i', 140, struct lagg_reqport) #define SIOCSLAGGPORT _IOW('i', 141, struct lagg_reqport) #define SIOCSLAGGDELPORT _IOW('i', 142, struct lagg_reqport) /* lagg, ports and options */ struct lagg_reqall { char ra_ifname[IFNAMSIZ]; /* name of the lagg */ u_int ra_proto; /* lagg protocol */ size_t ra_size; /* size of buffer */ struct lagg_reqport *ra_port; /* allocated buffer */ int ra_ports; /* total port count */ union { struct lacp_opreq rpsc_lacp; } ra_psc; #define ra_lacpreq ra_psc.rpsc_lacp }; #define SIOCGLAGG _IOWR('i', 143, struct lagg_reqall) #define SIOCSLAGG _IOW('i', 144, struct lagg_reqall) struct lagg_reqflags { char rf_ifname[IFNAMSIZ]; /* name of the lagg */ uint32_t rf_flags; /* lagg protocol */ }; #define SIOCGLAGGFLAGS _IOWR('i', 145, struct lagg_reqflags) #define SIOCSLAGGHASH _IOW('i', 146, struct lagg_reqflags) struct lagg_reqopts { char ro_ifname[IFNAMSIZ]; /* name of the lagg */ int ro_opts; /* Option bitmap */ #define LAGG_OPT_NONE 0x00 #define LAGG_OPT_USE_FLOWID 0x01 /* enable use of flowid */ /* Pseudo flags which are used in ro_opts but not stored into sc_opts. */ #define LAGG_OPT_FLOWIDSHIFT 0x02 /* set flowid shift */ #define LAGG_OPT_FLOWIDSHIFT_MASK 0x1f /* flowid is uint32_t */ #define LAGG_OPT_LACP_STRICT 0x10 /* LACP strict mode */ #define LAGG_OPT_LACP_TXTEST 0x20 /* LACP debug: txtest */ #define LAGG_OPT_LACP_RXTEST 0x40 /* LACP debug: rxtest */ #define LAGG_OPT_LACP_TIMEOUT 0x80 /* LACP timeout */ u_int ro_count; /* number of ports */ u_int ro_active; /* active port count */ u_int ro_flapping; /* number of flapping */ int ro_flowid_shift; /* shift the flowid */ }; #define SIOCGLAGGOPTS _IOWR('i', 152, struct lagg_reqopts) #define SIOCSLAGGOPTS _IOW('i', 153, struct lagg_reqopts) #define LAGG_OPT_BITS "\020\001USE_FLOWID\005LACP_STRICT" \ "\006LACP_TXTEST\007LACP_RXTEST" #ifdef _KERNEL /* * Internal kernel part */ #define LAGG_PORTACTIVE(_tp) ( \ ((_tp)->lp_ifp->if_link_state == LINK_STATE_UP) && \ ((_tp)->lp_ifp->if_flags & IFF_UP) \ ) struct lagg_ifreq { union { struct ifreq ifreq; struct { char ifr_name[IFNAMSIZ]; struct sockaddr_storage ifr_ss; } ifreq_storage; } ifreq; }; #define sc_ifflags sc_ifp->if_flags /* flags */ #define sc_ifname sc_ifp->if_xname /* name */ #define sc_capabilities sc_ifp->if_capabilities /* capabilities */ #define IFCAP_LAGG_MASK 0xffff0000 /* private capabilities */ #define IFCAP_LAGG_FULLDUPLEX 0x00010000 /* full duplex with >1 ports */ /* Private data used by the loadbalancing protocol */ struct lagg_lb { u_int32_t lb_key; struct lagg_port *lb_ports[LAGG_MAX_PORTS]; }; struct lagg_mc { struct sockaddr_dl mc_addr; struct ifmultiaddr *mc_ifma; SLIST_ENTRY(lagg_mc) mc_entries; }; typedef enum { LAGG_LLQTYPE_PHYS = 0, /* Task related to physical (underlying) port */ LAGG_LLQTYPE_VIRT, /* Task related to lagg interface itself */ } lagg_llqtype; /* List of interfaces to have the MAC address modified */ struct lagg_llq { struct ifnet *llq_ifp; uint8_t llq_lladdr[ETHER_ADDR_LEN]; lagg_llqtype llq_type; SLIST_ENTRY(lagg_llq) llq_entries; }; struct lagg_counters { uint64_t val[IFCOUNTERS]; }; struct lagg_softc { struct ifnet *sc_ifp; /* virtual interface */ struct rmlock sc_mtx; int sc_proto; /* lagg protocol */ u_int sc_count; /* number of ports */ u_int sc_active; /* active port count */ u_int sc_flapping; /* number of flapping * events */ struct lagg_port *sc_primary; /* primary port */ struct ifmedia sc_media; /* media config */ void *sc_psc; /* protocol data */ uint32_t sc_seq; /* sequence counter */ uint32_t sc_flags; SLIST_HEAD(__tplhd, lagg_port) sc_ports; /* list of interfaces */ SLIST_ENTRY(lagg_softc) sc_entries; struct task sc_lladdr_task; SLIST_HEAD(__llqhd, lagg_llq) sc_llq_head; /* interfaces to program the lladdr on */ eventhandler_tag vlan_attach; eventhandler_tag vlan_detach; struct callout sc_callout; u_int sc_opts; int flowid_shift; /* shift the flowid */ struct lagg_counters detached_counters; /* detached ports sum */ }; struct lagg_port { struct ifnet *lp_ifp; /* physical interface */ struct lagg_softc *lp_softc; /* parent lagg */ uint8_t lp_lladdr[ETHER_ADDR_LEN]; u_char lp_iftype; /* interface type */ uint32_t lp_prio; /* port priority */ uint32_t lp_flags; /* port flags */ int lp_ifflags; /* saved ifp flags */ void *lh_cookie; /* if state hook */ void *lp_psc; /* protocol data */ int lp_detaching; /* ifnet is detaching */ SLIST_HEAD(__mclhd, lagg_mc) lp_mc_head; /* multicast addresses */ /* Redirected callbacks */ int (*lp_ioctl)(struct ifnet *, u_long, caddr_t); int (*lp_output)(struct ifnet *, struct mbuf *, const struct sockaddr *, struct route *); struct lagg_counters port_counters; /* ifp counters copy */ SLIST_ENTRY(lagg_port) lp_entries; }; #define LAGG_LOCK_INIT(_sc) rm_init(&(_sc)->sc_mtx, "if_lagg rmlock") #define LAGG_LOCK_DESTROY(_sc) rm_destroy(&(_sc)->sc_mtx) #define LAGG_RLOCK(_sc, _p) rm_rlock(&(_sc)->sc_mtx, (_p)) #define LAGG_WLOCK(_sc) rm_wlock(&(_sc)->sc_mtx) #define LAGG_RUNLOCK(_sc, _p) rm_runlock(&(_sc)->sc_mtx, (_p)) #define LAGG_WUNLOCK(_sc) rm_wunlock(&(_sc)->sc_mtx) #define LAGG_RLOCK_ASSERT(_sc) rm_assert(&(_sc)->sc_mtx, RA_RLOCKED) #define LAGG_WLOCK_ASSERT(_sc) rm_assert(&(_sc)->sc_mtx, RA_WLOCKED) #define LAGG_UNLOCK_ASSERT(_sc) rm_assert(&(_sc)->sc_mtx, RA_UNLOCKED) extern struct mbuf *(*lagg_input_p)(struct ifnet *, struct mbuf *); -extern void (*lagg_linkstate_p)(struct ifnet *); +extern void (*lagg_linkstate_p)(struct ifnet *, int ); int lagg_enqueue(struct ifnet *, struct mbuf *); SYSCTL_DECL(_net_link_lagg); #endif /* _KERNEL */ #endif /* _NET_LAGG_H */ Index: user/alc/PQ_LAUNDRY/sys/net/if_var.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/net/if_var.h (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/net/if_var.h (revision 292449) @@ -1,621 +1,620 @@ /*- * Copyright (c) 1982, 1986, 1989, 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. * 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. * * From: @(#)if.h 8.1 (Berkeley) 6/10/93 * $FreeBSD$ */ #ifndef _NET_IF_VAR_H_ #define _NET_IF_VAR_H_ /* * Structures defining a network interface, providing a packet * transport mechanism (ala level 0 of the PUP protocols). * * Each interface accepts output datagrams of a specified maximum * length, and provides higher level routines with input datagrams * received from its medium. * * Output occurs when the routine if_output is called, with three parameters: * (*ifp->if_output)(ifp, m, dst, rt) * Here m is the mbuf chain to be sent and dst is the destination address. * The output routine encapsulates the supplied datagram if necessary, * and then transmits it on its medium. * * On input, each interface unwraps the data received by it, and either * places it on the input queue of an internetwork datagram routine * and posts the associated software interrupt, or passes the datagram to a raw * packet input routine. * * Routines exist for locating interfaces by their addresses * or for locating an interface on a certain network, as well as more general * routing and gateway routines maintaining information used to locate * interfaces. These routines live in the files if.c and route.c */ struct rtentry; /* ifa_rtrequest */ struct rt_addrinfo; /* ifa_rtrequest */ struct socket; struct carp_if; struct carp_softc; struct ifvlantrunk; struct route; /* if_output */ struct vnet; struct ifmedia; struct netmap_adapter; #ifdef _KERNEL #include /* ifqueue only? */ #include #include #endif /* _KERNEL */ #include #include /* XXX */ #include /* struct ifqueue */ #include /* XXX */ #include /* XXX */ #include /* if_link_task */ #define IF_DUNIT_NONE -1 #include TAILQ_HEAD(ifnethead, ifnet); /* we use TAILQs so that the order of */ TAILQ_HEAD(ifaddrhead, ifaddr); /* instantiation is preserved in the list */ TAILQ_HEAD(ifmultihead, ifmultiaddr); TAILQ_HEAD(ifgrouphead, ifg_group); #ifdef _KERNEL VNET_DECLARE(struct pfil_head, link_pfil_hook); /* packet filter hooks */ #define V_link_pfil_hook VNET(link_pfil_hook) #define HHOOK_IPSEC_INET 0 #define HHOOK_IPSEC_INET6 1 #define HHOOK_IPSEC_COUNT 2 VNET_DECLARE(struct hhook_head *, ipsec_hhh_in[HHOOK_IPSEC_COUNT]); VNET_DECLARE(struct hhook_head *, ipsec_hhh_out[HHOOK_IPSEC_COUNT]); #define V_ipsec_hhh_in VNET(ipsec_hhh_in) #define V_ipsec_hhh_out VNET(ipsec_hhh_out) #endif /* _KERNEL */ typedef enum { IFCOUNTER_IPACKETS = 0, IFCOUNTER_IERRORS, IFCOUNTER_OPACKETS, IFCOUNTER_OERRORS, IFCOUNTER_COLLISIONS, IFCOUNTER_IBYTES, IFCOUNTER_OBYTES, IFCOUNTER_IMCASTS, IFCOUNTER_OMCASTS, IFCOUNTER_IQDROPS, IFCOUNTER_OQDROPS, IFCOUNTER_NOPROTO, IFCOUNTERS /* Array size. */ } ift_counter; typedef struct ifnet * if_t; typedef void (*if_start_fn_t)(if_t); typedef int (*if_ioctl_fn_t)(if_t, u_long, caddr_t); typedef void (*if_init_fn_t)(void *); typedef void (*if_qflush_fn_t)(if_t); typedef int (*if_transmit_fn_t)(if_t, struct mbuf *); typedef uint64_t (*if_get_counter_t)(if_t, ift_counter); struct ifnet_hw_tsomax { u_int tsomaxbytes; /* TSO total burst length limit in bytes */ u_int tsomaxsegcount; /* TSO maximum segment count */ u_int tsomaxsegsize; /* TSO maximum segment size in bytes */ }; /* * Structure defining a network interface. * * Size ILP32: 592 (approx) * LP64: 1048 (approx) */ struct ifnet { /* General book keeping of interface lists. */ TAILQ_ENTRY(ifnet) if_link; /* all struct ifnets are chained */ LIST_ENTRY(ifnet) if_clones; /* interfaces of a cloner */ TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */ /* protected by if_addr_lock */ u_char if_alloctype; /* if_type at time of allocation */ /* Driver and protocol specific information that remains stable. */ void *if_softc; /* pointer to driver state */ void *if_llsoftc; /* link layer softc */ void *if_l2com; /* pointer to protocol bits */ const char *if_dname; /* driver name */ int if_dunit; /* unit or IF_DUNIT_NONE */ u_short if_index; /* numeric abbreviation for this if */ short if_index_reserved; /* spare space to grow if_index */ char if_xname[IFNAMSIZ]; /* external name (name + unit) */ char *if_description; /* interface description */ /* Variable fields that are touched by the stack and drivers. */ int if_flags; /* up/down, broadcast, etc. */ int if_drv_flags; /* driver-managed status flags */ int if_capabilities; /* interface features & capabilities */ int if_capenable; /* enabled features & capabilities */ void *if_linkmib; /* link-type-specific MIB data */ size_t if_linkmiblen; /* length of above data */ u_int if_refcount; /* reference count */ /* These fields are shared with struct if_data. */ uint8_t if_type; /* ethernet, tokenring, etc */ uint8_t if_addrlen; /* media address length */ uint8_t if_hdrlen; /* media header length */ uint8_t if_link_state; /* current link state */ uint32_t if_mtu; /* maximum transmission unit */ uint32_t if_metric; /* routing metric (external only) */ uint64_t if_baudrate; /* linespeed */ uint64_t if_hwassist; /* HW offload capabilities, see IFCAP */ time_t if_epoch; /* uptime at attach or stat reset */ struct timeval if_lastchange; /* time of last administrative change */ struct ifaltq if_snd; /* output queue (includes altq) */ struct task if_linktask; /* task for link change events */ /* Addresses of different protocol families assigned to this if. */ struct rwlock if_addr_lock; /* lock to protect address lists */ /* * if_addrhead is the list of all addresses associated to * an interface. * Some code in the kernel assumes that first element * of the list has type AF_LINK, and contains sockaddr_dl * addresses which store the link-level address and the name * of the interface. * However, access to the AF_LINK address through this * field is deprecated. Use if_addr or ifaddr_byindex() instead. */ struct ifaddrhead if_addrhead; /* linked list of addresses per if */ struct ifmultihead if_multiaddrs; /* multicast addresses configured */ int if_amcount; /* number of all-multicast requests */ struct ifaddr *if_addr; /* pointer to link-level address */ const u_int8_t *if_broadcastaddr; /* linklevel broadcast bytestring */ struct rwlock if_afdata_lock; void *if_afdata[AF_MAX]; int if_afdata_initialized; /* Additional features hung off the interface. */ u_int if_fib; /* interface FIB */ struct vnet *if_vnet; /* pointer to network stack instance */ struct vnet *if_home_vnet; /* where this ifnet originates from */ struct ifvlantrunk *if_vlantrunk; /* pointer to 802.1q data */ struct bpf_if *if_bpf; /* packet filter structure */ int if_pcount; /* number of promiscuous listeners */ void *if_bridge; /* bridge glue */ void *if_lagg; /* lagg glue */ void *if_pf_kif; /* pf glue */ struct carp_if *if_carp; /* carp interface structure */ struct label *if_label; /* interface MAC label */ struct netmap_adapter *if_netmap; /* netmap(4) softc */ /* Various procedures of the layer2 encapsulation and drivers. */ int (*if_output) /* output routine (enqueue) */ (struct ifnet *, struct mbuf *, const struct sockaddr *, struct route *); void (*if_input) /* input routine (from h/w driver) */ (struct ifnet *, struct mbuf *); if_start_fn_t if_start; /* initiate output routine */ if_ioctl_fn_t if_ioctl; /* ioctl routine */ if_init_fn_t if_init; /* Init routine */ int (*if_resolvemulti) /* validate/resolve multicast */ (struct ifnet *, struct sockaddr **, struct sockaddr *); if_qflush_fn_t if_qflush; /* flush any queue */ if_transmit_fn_t if_transmit; /* initiate output routine */ void (*if_reassign) /* reassign to vnet routine */ (struct ifnet *, struct vnet *, char *); if_get_counter_t if_get_counter; /* get counter values */ /* Statistics. */ counter_u64_t if_counters[IFCOUNTERS]; /* Stuff that's only temporary and doesn't belong here. */ /* * Network adapter TSO limits: * =========================== * * If the "if_hw_tsomax" field is zero the maximum segment * length limit does not apply. If the "if_hw_tsomaxsegcount" * or the "if_hw_tsomaxsegsize" field is zero the TSO segment * count limit does not apply. If all three fields are zero, * there is no TSO limit. * * NOTE: The TSO limits should reflect the values used in the * BUSDMA tag a network adapter is using to load a mbuf chain * for transmission. The TCP/IP network stack will subtract * space for all linklevel and protocol level headers and * ensure that the full mbuf chain passed to the network * adapter fits within the given limits. */ u_int if_hw_tsomax; /* TSO maximum size in bytes */ u_int if_hw_tsomaxsegcount; /* TSO maximum segment count */ u_int if_hw_tsomaxsegsize; /* TSO maximum segment size in bytes */ /* * Spare fields to be added before branching a stable branch, so * that structure can be enhanced without changing the kernel * binary interface. */ }; /* for compatibility with other BSDs */ #define if_addrlist if_addrhead #define if_list if_link #define if_name(ifp) ((ifp)->if_xname) /* * Locks for address lists on the network interface. */ #define IF_ADDR_LOCK_INIT(if) rw_init(&(if)->if_addr_lock, "if_addr_lock") #define IF_ADDR_LOCK_DESTROY(if) rw_destroy(&(if)->if_addr_lock) #define IF_ADDR_WLOCK(if) rw_wlock(&(if)->if_addr_lock) #define IF_ADDR_WUNLOCK(if) rw_wunlock(&(if)->if_addr_lock) #define IF_ADDR_RLOCK(if) rw_rlock(&(if)->if_addr_lock) #define IF_ADDR_RUNLOCK(if) rw_runlock(&(if)->if_addr_lock) #define IF_ADDR_LOCK_ASSERT(if) rw_assert(&(if)->if_addr_lock, RA_LOCKED) #define IF_ADDR_WLOCK_ASSERT(if) rw_assert(&(if)->if_addr_lock, RA_WLOCKED) /* * Function variations on locking macros intended to be used by loadable * kernel modules in order to divorce them from the internals of address list * locking. */ void if_addr_rlock(struct ifnet *ifp); /* if_addrhead */ void if_addr_runlock(struct ifnet *ifp); /* if_addrhead */ void if_maddr_rlock(if_t ifp); /* if_multiaddrs */ void if_maddr_runlock(if_t ifp); /* if_multiaddrs */ #ifdef _KERNEL #ifdef _SYS_EVENTHANDLER_H_ /* interface link layer address change event */ typedef void (*iflladdr_event_handler_t)(void *, struct ifnet *); EVENTHANDLER_DECLARE(iflladdr_event, iflladdr_event_handler_t); /* interface address change event */ typedef void (*ifaddr_event_handler_t)(void *, struct ifnet *); EVENTHANDLER_DECLARE(ifaddr_event, ifaddr_event_handler_t); /* new interface arrival event */ typedef void (*ifnet_arrival_event_handler_t)(void *, struct ifnet *); EVENTHANDLER_DECLARE(ifnet_arrival_event, ifnet_arrival_event_handler_t); /* interface departure event */ typedef void (*ifnet_departure_event_handler_t)(void *, struct ifnet *); EVENTHANDLER_DECLARE(ifnet_departure_event, ifnet_departure_event_handler_t); /* Interface link state change event */ typedef void (*ifnet_link_event_handler_t)(void *, struct ifnet *, int); EVENTHANDLER_DECLARE(ifnet_link_event, ifnet_link_event_handler_t); #endif /* _SYS_EVENTHANDLER_H_ */ /* * interface groups */ struct ifg_group { char ifg_group[IFNAMSIZ]; u_int ifg_refcnt; void *ifg_pf_kif; TAILQ_HEAD(, ifg_member) ifg_members; TAILQ_ENTRY(ifg_group) ifg_next; }; struct ifg_member { TAILQ_ENTRY(ifg_member) ifgm_next; struct ifnet *ifgm_ifp; }; struct ifg_list { struct ifg_group *ifgl_group; TAILQ_ENTRY(ifg_list) ifgl_next; }; #ifdef _SYS_EVENTHANDLER_H_ /* group attach event */ typedef void (*group_attach_event_handler_t)(void *, struct ifg_group *); EVENTHANDLER_DECLARE(group_attach_event, group_attach_event_handler_t); /* group detach event */ typedef void (*group_detach_event_handler_t)(void *, struct ifg_group *); EVENTHANDLER_DECLARE(group_detach_event, group_detach_event_handler_t); /* group change event */ typedef void (*group_change_event_handler_t)(void *, const char *); EVENTHANDLER_DECLARE(group_change_event, group_change_event_handler_t); #endif /* _SYS_EVENTHANDLER_H_ */ #define IF_AFDATA_LOCK_INIT(ifp) \ rw_init(&(ifp)->if_afdata_lock, "if_afdata") #define IF_AFDATA_WLOCK(ifp) rw_wlock(&(ifp)->if_afdata_lock) #define IF_AFDATA_RLOCK(ifp) rw_rlock(&(ifp)->if_afdata_lock) #define IF_AFDATA_WUNLOCK(ifp) rw_wunlock(&(ifp)->if_afdata_lock) #define IF_AFDATA_RUNLOCK(ifp) rw_runlock(&(ifp)->if_afdata_lock) #define IF_AFDATA_LOCK(ifp) IF_AFDATA_WLOCK(ifp) #define IF_AFDATA_UNLOCK(ifp) IF_AFDATA_WUNLOCK(ifp) #define IF_AFDATA_TRYLOCK(ifp) rw_try_wlock(&(ifp)->if_afdata_lock) #define IF_AFDATA_DESTROY(ifp) rw_destroy(&(ifp)->if_afdata_lock) #define IF_AFDATA_LOCK_ASSERT(ifp) rw_assert(&(ifp)->if_afdata_lock, RA_LOCKED) #define IF_AFDATA_RLOCK_ASSERT(ifp) rw_assert(&(ifp)->if_afdata_lock, RA_RLOCKED) #define IF_AFDATA_WLOCK_ASSERT(ifp) rw_assert(&(ifp)->if_afdata_lock, RA_WLOCKED) #define IF_AFDATA_UNLOCK_ASSERT(ifp) rw_assert(&(ifp)->if_afdata_lock, RA_UNLOCKED) /* * 72 was chosen below because it is the size of a TCP/IP * header (40) + the minimum mss (32). */ #define IF_MINMTU 72 #define IF_MAXMTU 65535 #define TOEDEV(ifp) ((ifp)->if_llsoftc) /* * The ifaddr structure contains information about one address * of an interface. They are maintained by the different address families, * are allocated and attached when an address is set, and are linked * together so all addresses for an interface can be located. * * NOTE: a 'struct ifaddr' is always at the beginning of a larger * chunk of malloc'ed memory, where we store the three addresses * (ifa_addr, ifa_dstaddr and ifa_netmask) referenced here. */ struct ifaddr { struct sockaddr *ifa_addr; /* address of interface */ struct sockaddr *ifa_dstaddr; /* other end of p-to-p link */ #define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ struct sockaddr *ifa_netmask; /* used to determine subnet */ struct ifnet *ifa_ifp; /* back-pointer to interface */ struct carp_softc *ifa_carp; /* pointer to CARP data */ TAILQ_ENTRY(ifaddr) ifa_link; /* queue macro glue */ void (*ifa_rtrequest) /* check or clean routes (+ or -)'d */ (int, struct rtentry *, struct rt_addrinfo *); u_short ifa_flags; /* mostly rt_flags for cloning */ #define IFA_ROUTE RTF_UP /* route installed */ #define IFA_RTSELF RTF_HOST /* loopback route to self installed */ u_int ifa_refcnt; /* references to this structure */ counter_u64_t ifa_ipackets; counter_u64_t ifa_opackets; counter_u64_t ifa_ibytes; counter_u64_t ifa_obytes; }; /* For compatibility with other BSDs. SCTP uses it. */ #define ifa_list ifa_link struct ifaddr * ifa_alloc(size_t size, int flags); void ifa_free(struct ifaddr *ifa); void ifa_ref(struct ifaddr *ifa); /* * Multicast address structure. This is analogous to the ifaddr * structure except that it keeps track of multicast addresses. */ struct ifmultiaddr { TAILQ_ENTRY(ifmultiaddr) ifma_link; /* queue macro glue */ struct sockaddr *ifma_addr; /* address this membership is for */ struct sockaddr *ifma_lladdr; /* link-layer translation, if any */ struct ifnet *ifma_ifp; /* back-pointer to interface */ u_int ifma_refcount; /* reference count */ void *ifma_protospec; /* protocol-specific state, if any */ struct ifmultiaddr *ifma_llifma; /* pointer to ifma for ifma_lladdr */ }; extern struct rwlock ifnet_rwlock; extern struct sx ifnet_sxlock; #define IFNET_WLOCK() do { \ sx_xlock(&ifnet_sxlock); \ rw_wlock(&ifnet_rwlock); \ } while (0) #define IFNET_WUNLOCK() do { \ rw_wunlock(&ifnet_rwlock); \ sx_xunlock(&ifnet_sxlock); \ } while (0) /* * To assert the ifnet lock, you must know not only whether it's for read or * write, but also whether it was acquired with sleep support or not. */ #define IFNET_RLOCK_ASSERT() sx_assert(&ifnet_sxlock, SA_SLOCKED) #define IFNET_RLOCK_NOSLEEP_ASSERT() rw_assert(&ifnet_rwlock, RA_RLOCKED) #define IFNET_WLOCK_ASSERT() do { \ sx_assert(&ifnet_sxlock, SA_XLOCKED); \ rw_assert(&ifnet_rwlock, RA_WLOCKED); \ } while (0) #define IFNET_RLOCK() sx_slock(&ifnet_sxlock) #define IFNET_RLOCK_NOSLEEP() rw_rlock(&ifnet_rwlock) #define IFNET_RUNLOCK() sx_sunlock(&ifnet_sxlock) #define IFNET_RUNLOCK_NOSLEEP() rw_runlock(&ifnet_rwlock) /* * Look up an ifnet given its index; the _ref variant also acquires a * reference that must be freed using if_rele(). It is almost always a bug * to call ifnet_byindex() instead if ifnet_byindex_ref(). */ struct ifnet *ifnet_byindex(u_short idx); struct ifnet *ifnet_byindex_locked(u_short idx); struct ifnet *ifnet_byindex_ref(u_short idx); /* * Given the index, ifaddr_byindex() returns the one and only * link-level ifaddr for the interface. You are not supposed to use * it to traverse the list of addresses associated to the interface. */ struct ifaddr *ifaddr_byindex(u_short idx); VNET_DECLARE(struct ifnethead, ifnet); VNET_DECLARE(struct ifgrouphead, ifg_head); VNET_DECLARE(int, if_index); VNET_DECLARE(struct ifnet *, loif); /* first loopback interface */ #define V_ifnet VNET(ifnet) #define V_ifg_head VNET(ifg_head) #define V_if_index VNET(if_index) #define V_loif VNET(loif) int if_addgroup(struct ifnet *, const char *); int if_delgroup(struct ifnet *, const char *); int if_addmulti(struct ifnet *, struct sockaddr *, struct ifmultiaddr **); int if_allmulti(struct ifnet *, int); struct ifnet* if_alloc(u_char); void if_attach(struct ifnet *); void if_dead(struct ifnet *); int if_delmulti(struct ifnet *, struct sockaddr *); void if_delmulti_ifma(struct ifmultiaddr *); void if_detach(struct ifnet *); void if_vmove(struct ifnet *, struct vnet *); void if_purgeaddrs(struct ifnet *); void if_delallmulti(struct ifnet *); void if_down(struct ifnet *); struct ifmultiaddr * if_findmulti(struct ifnet *, const struct sockaddr *); void if_free(struct ifnet *); void if_initname(struct ifnet *, const char *, int); void if_link_state_change(struct ifnet *, int); -void if_link_state_change_cond(struct ifnet *, int, int); int if_printf(struct ifnet *, const char *, ...) __printflike(2, 3); void if_ref(struct ifnet *); void if_rele(struct ifnet *); int if_setlladdr(struct ifnet *, const u_char *, int); void if_up(struct ifnet *); int ifioctl(struct socket *, u_long, caddr_t, struct thread *); int ifpromisc(struct ifnet *, int); struct ifnet *ifunit(const char *); struct ifnet *ifunit_ref(const char *); int ifa_add_loopback_route(struct ifaddr *, struct sockaddr *); int ifa_del_loopback_route(struct ifaddr *, struct sockaddr *); int ifa_switch_loopback_route(struct ifaddr *, struct sockaddr *); struct ifaddr *ifa_ifwithaddr(const struct sockaddr *); int ifa_ifwithaddr_check(const struct sockaddr *); struct ifaddr *ifa_ifwithbroadaddr(const struct sockaddr *, int); struct ifaddr *ifa_ifwithdstaddr(const struct sockaddr *, int); struct ifaddr *ifa_ifwithnet(const struct sockaddr *, int, int); struct ifaddr *ifa_ifwithroute(int, const struct sockaddr *, struct sockaddr *, u_int); struct ifaddr *ifaof_ifpforaddr(const struct sockaddr *, struct ifnet *); int ifa_preferred(struct ifaddr *, struct ifaddr *); int if_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen); typedef void *if_com_alloc_t(u_char type, struct ifnet *ifp); typedef void if_com_free_t(void *com, u_char type); void if_register_com_alloc(u_char type, if_com_alloc_t *a, if_com_free_t *f); void if_deregister_com_alloc(u_char type); void if_data_copy(struct ifnet *, struct if_data *); uint64_t if_get_counter_default(struct ifnet *, ift_counter); void if_inc_counter(struct ifnet *, ift_counter, int64_t); #define IF_LLADDR(ifp) \ LLADDR((struct sockaddr_dl *)((ifp)->if_addr->ifa_addr)) uint64_t if_setbaudrate(if_t ifp, uint64_t baudrate); uint64_t if_getbaudrate(if_t ifp); int if_setcapabilities(if_t ifp, int capabilities); int if_setcapabilitiesbit(if_t ifp, int setbit, int clearbit); int if_getcapabilities(if_t ifp); int if_togglecapenable(if_t ifp, int togglecap); int if_setcapenable(if_t ifp, int capenable); int if_setcapenablebit(if_t ifp, int setcap, int clearcap); int if_getcapenable(if_t ifp); const char *if_getdname(if_t ifp); int if_setdev(if_t ifp, void *dev); int if_setdrvflagbits(if_t ifp, int if_setflags, int clear_flags); int if_getdrvflags(if_t ifp); int if_setdrvflags(if_t ifp, int flags); int if_clearhwassist(if_t ifp); int if_sethwassistbits(if_t ifp, int toset, int toclear); int if_sethwassist(if_t ifp, int hwassist_bit); int if_gethwassist(if_t ifp); int if_setsoftc(if_t ifp, void *softc); void *if_getsoftc(if_t ifp); int if_setflags(if_t ifp, int flags); int if_setmtu(if_t ifp, int mtu); int if_getmtu(if_t ifp); int if_getmtu_family(if_t ifp, int family); int if_setflagbits(if_t ifp, int set, int clear); int if_getflags(if_t ifp); int if_sendq_empty(if_t ifp); int if_setsendqready(if_t ifp); int if_setsendqlen(if_t ifp, int tx_desc_count); int if_input(if_t ifp, struct mbuf* sendmp); int if_sendq_prepend(if_t ifp, struct mbuf *m); struct mbuf *if_dequeue(if_t ifp); int if_setifheaderlen(if_t ifp, int len); void if_setrcvif(struct mbuf *m, if_t ifp); void if_setvtag(struct mbuf *m, u_int16_t tag); u_int16_t if_getvtag(struct mbuf *m); int if_vlantrunkinuse(if_t ifp); caddr_t if_getlladdr(if_t ifp); void *if_gethandle(u_char); void if_bpfmtap(if_t ifp, struct mbuf *m); void if_etherbpfmtap(if_t ifp, struct mbuf *m); void if_vlancap(if_t ifp); int if_setupmultiaddr(if_t ifp, void *mta, int *cnt, int max); int if_multiaddr_array(if_t ifp, void *mta, int *cnt, int max); int if_multiaddr_count(if_t ifp, int max); int if_getamcount(if_t ifp); struct ifaddr * if_getifaddr(if_t ifp); /* Functions */ void if_setinitfn(if_t ifp, void (*)(void *)); void if_setioctlfn(if_t ifp, int (*)(if_t, u_long, caddr_t)); void if_setstartfn(if_t ifp, void (*)(if_t)); void if_settransmitfn(if_t ifp, if_transmit_fn_t); void if_setqflushfn(if_t ifp, if_qflush_fn_t); void if_setgetcounterfn(if_t ifp, if_get_counter_t); /* Revisit the below. These are inline functions originally */ int drbr_inuse_drv(if_t ifp, struct buf_ring *br); struct mbuf* drbr_dequeue_drv(if_t ifp, struct buf_ring *br); int drbr_needs_enqueue_drv(if_t ifp, struct buf_ring *br); int drbr_enqueue_drv(if_t ifp, struct buf_ring *br, struct mbuf *m); /* TSO */ void if_hw_tsomax_common(if_t ifp, struct ifnet_hw_tsomax *); int if_hw_tsomax_update(if_t ifp, struct ifnet_hw_tsomax *); #ifdef DEVICE_POLLING enum poll_cmd { POLL_ONLY, POLL_AND_CHECK_STATUS }; typedef int poll_handler_t(if_t ifp, enum poll_cmd cmd, int count); int ether_poll_register(poll_handler_t *h, if_t ifp); int ether_poll_deregister(if_t ifp); #endif /* DEVICE_POLLING */ #endif /* _KERNEL */ #include /* XXXAO: temporary unconditional include */ #endif /* !_NET_IF_VAR_H_ */ Index: user/alc/PQ_LAUNDRY/sys/netinet/if_ether.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/netinet/if_ether.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/netinet/if_ether.c (revision 292449) @@ -1,1301 +1,1235 @@ /*- * Copyright (c) 1982, 1986, 1988, 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. * 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. * * @(#)if_ether.c 8.1 (Berkeley) 6/10/93 */ /* * Ethernet address resolution protocol. * TODO: * add "inuse/lock" bit (or ref. count) along with valid bit */ #include __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef INET #include #endif #include #define SIN(s) ((const struct sockaddr_in *)(s)) static struct timeval arp_lastlog; static int arp_curpps; static int arp_maxpps = 1; /* Simple ARP state machine */ enum arp_llinfo_state { ARP_LLINFO_INCOMPLETE = 0, /* No LLE data */ ARP_LLINFO_REACHABLE, /* LLE is valid */ ARP_LLINFO_VERIFY, /* LLE is valid, need refresh */ ARP_LLINFO_DELETED, /* LLE is deleted */ }; SYSCTL_DECL(_net_link_ether); static SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, ""); static SYSCTL_NODE(_net_link_ether, PF_ARP, arp, CTLFLAG_RW, 0, ""); /* timer values */ static VNET_DEFINE(int, arpt_keep) = (20*60); /* once resolved, good for 20 * minutes */ static VNET_DEFINE(int, arp_maxtries) = 5; static VNET_DEFINE(int, arp_proxyall) = 0; static VNET_DEFINE(int, arpt_down) = 20; /* keep incomplete entries for * 20 seconds */ static VNET_DEFINE(int, arpt_rexmit) = 1; /* retransmit arp entries, sec*/ VNET_PCPUSTAT_DEFINE(struct arpstat, arpstat); /* ARP statistics, see if_arp.h */ VNET_PCPUSTAT_SYSINIT(arpstat); #ifdef VIMAGE VNET_PCPUSTAT_SYSUNINIT(arpstat); #endif /* VIMAGE */ static VNET_DEFINE(int, arp_maxhold) = 1; -static VNET_DEFINE(int, arp_on_link) = 1; #define V_arpt_keep VNET(arpt_keep) #define V_arpt_down VNET(arpt_down) #define V_arpt_rexmit VNET(arpt_rexmit) #define V_arp_maxtries VNET(arp_maxtries) #define V_arp_proxyall VNET(arp_proxyall) #define V_arp_maxhold VNET(arp_maxhold) -#define V_arp_on_link VNET(arp_on_link) SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(arpt_keep), 0, "ARP entry lifetime in seconds"); SYSCTL_INT(_net_link_ether_inet, OID_AUTO, maxtries, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(arp_maxtries), 0, "ARP resolution attempts before returning error"); SYSCTL_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(arp_proxyall), 0, "Enable proxy ARP for all suitable requests"); SYSCTL_INT(_net_link_ether_inet, OID_AUTO, wait, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(arpt_down), 0, "Incomplete ARP entry lifetime in seconds"); SYSCTL_VNET_PCPUSTAT(_net_link_ether_arp, OID_AUTO, stats, struct arpstat, arpstat, "ARP statistics (struct arpstat, net/if_arp.h)"); SYSCTL_INT(_net_link_ether_inet, OID_AUTO, maxhold, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(arp_maxhold), 0, "Number of packets to hold per ARP entry"); SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_log_per_second, CTLFLAG_RW, &arp_maxpps, 0, "Maximum number of remotely triggered ARP messages that can be " "logged per second"); -SYSCTL_INT(_net_link_ether_inet, OID_AUTO, arp_on_link, CTLFLAG_VNET | CTLFLAG_RW, - &VNET_NAME(arp_on_link), 0, - "Send gratuitous ARP's on interface link up events"); #define ARP_LOG(pri, ...) do { \ if (ppsratecheck(&arp_lastlog, &arp_curpps, arp_maxpps)) \ log((pri), "arp: " __VA_ARGS__); \ } while (0) static void arp_init(void); static void arpintr(struct mbuf *); static void arptimer(void *); #ifdef INET static void in_arpinput(struct mbuf *); #endif static void arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp, int bridged, struct llentry *la); static void arp_mark_lle_reachable(struct llentry *la); static void arp_iflladdr(void *arg __unused, struct ifnet *ifp); static eventhandler_tag iflladdr_tag; -static eventhandler_tag ifnet_link_event_tag; static const struct netisr_handler arp_nh = { .nh_name = "arp", .nh_handler = arpintr, .nh_proto = NETISR_ARP, .nh_policy = NETISR_POLICY_SOURCE, }; /* * Timeout routine. Age arp_tab entries periodically. */ static void arptimer(void *arg) { struct llentry *lle = (struct llentry *)arg; struct ifnet *ifp; int r_skip_req; if (lle->la_flags & LLE_STATIC) { return; } LLE_WLOCK(lle); if (callout_pending(&lle->lle_timer)) { /* * Here we are a bit odd here in the treatment of * active/pending. If the pending bit is set, it got * rescheduled before I ran. The active * bit we ignore, since if it was stopped * in ll_tablefree() and was currently running * it would have return 0 so the code would * not have deleted it since the callout could * not be stopped so we want to go through * with the delete here now. If the callout * was restarted, the pending bit will be back on and * we just want to bail since the callout_reset would * return 1 and our reference would have been removed * by arpresolve() below. */ LLE_WUNLOCK(lle); return; } ifp = lle->lle_tbl->llt_ifp; CURVNET_SET(ifp->if_vnet); switch (lle->ln_state) { case ARP_LLINFO_REACHABLE: /* * Expiration time is approaching. * Let's try to refresh entry if it is still * in use. * * Set r_skip_req to get feedback from * fast path. Change state and re-schedule * ourselves. */ LLE_REQ_LOCK(lle); lle->r_skip_req = 1; LLE_REQ_UNLOCK(lle); lle->ln_state = ARP_LLINFO_VERIFY; callout_schedule(&lle->lle_timer, hz * V_arpt_rexmit); LLE_WUNLOCK(lle); CURVNET_RESTORE(); return; case ARP_LLINFO_VERIFY: LLE_REQ_LOCK(lle); r_skip_req = lle->r_skip_req; LLE_REQ_UNLOCK(lle); if (r_skip_req == 0 && lle->la_preempt > 0) { /* Entry was used, issue refresh request */ struct in_addr dst; dst = lle->r_l3addr.addr4; lle->la_preempt--; callout_schedule(&lle->lle_timer, hz * V_arpt_rexmit); LLE_WUNLOCK(lle); arprequest(ifp, NULL, &dst, NULL); CURVNET_RESTORE(); return; } /* Nothing happened. Reschedule if not too late */ if (lle->la_expire > time_uptime) { callout_schedule(&lle->lle_timer, hz * V_arpt_rexmit); LLE_WUNLOCK(lle); CURVNET_RESTORE(); return; } break; case ARP_LLINFO_INCOMPLETE: case ARP_LLINFO_DELETED: break; } if ((lle->la_flags & LLE_DELETED) == 0) { int evt; if (lle->la_flags & LLE_VALID) evt = LLENTRY_EXPIRED; else evt = LLENTRY_TIMEDOUT; EVENTHANDLER_INVOKE(lle_event, lle, evt); } callout_stop(&lle->lle_timer); /* XXX: LOR avoidance. We still have ref on lle. */ LLE_WUNLOCK(lle); IF_AFDATA_LOCK(ifp); LLE_WLOCK(lle); /* Guard against race with other llentry_free(). */ if (lle->la_flags & LLE_LINKED) { LLE_REMREF(lle); lltable_unlink_entry(lle->lle_tbl, lle); } IF_AFDATA_UNLOCK(ifp); size_t pkts_dropped = llentry_free(lle); ARPSTAT_ADD(dropped, pkts_dropped); ARPSTAT_INC(timeouts); CURVNET_RESTORE(); } /* * Broadcast an ARP request. Caller specifies: * - arp header source ip address * - arp header target ip address * - arp header source ethernet address */ void arprequest(struct ifnet *ifp, const struct in_addr *sip, const struct in_addr *tip, u_char *enaddr) { struct mbuf *m; struct arphdr *ah; struct sockaddr sa; u_char *carpaddr = NULL; if (sip == NULL) { /* * The caller did not supply a source address, try to find * a compatible one among those assigned to this interface. */ struct ifaddr *ifa; IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET) continue; if (ifa->ifa_carp) { if ((*carp_iamatch_p)(ifa, &carpaddr) == 0) continue; sip = &IA_SIN(ifa)->sin_addr; } else { carpaddr = NULL; sip = &IA_SIN(ifa)->sin_addr; } if (0 == ((sip->s_addr ^ tip->s_addr) & IA_MASKSIN(ifa)->sin_addr.s_addr)) break; /* found it. */ } IF_ADDR_RUNLOCK(ifp); if (sip == NULL) { printf("%s: cannot find matching address\n", __func__); return; } } if (enaddr == NULL) enaddr = carpaddr ? carpaddr : (u_char *)IF_LLADDR(ifp); if ((m = m_gethdr(M_NOWAIT, MT_DATA)) == NULL) return; m->m_len = sizeof(*ah) + 2 * sizeof(struct in_addr) + 2 * ifp->if_addrlen; m->m_pkthdr.len = m->m_len; M_ALIGN(m, m->m_len); ah = mtod(m, struct arphdr *); bzero((caddr_t)ah, m->m_len); #ifdef MAC mac_netinet_arp_send(ifp, m); #endif ah->ar_pro = htons(ETHERTYPE_IP); ah->ar_hln = ifp->if_addrlen; /* hardware address length */ ah->ar_pln = sizeof(struct in_addr); /* protocol address length */ ah->ar_op = htons(ARPOP_REQUEST); bcopy(enaddr, ar_sha(ah), ah->ar_hln); bcopy(sip, ar_spa(ah), ah->ar_pln); bcopy(tip, ar_tpa(ah), ah->ar_pln); sa.sa_family = AF_ARP; sa.sa_len = 2; m->m_flags |= M_BCAST; m_clrprotoflags(m); /* Avoid confusing lower layers. */ (*ifp->if_output)(ifp, m, &sa, NULL); ARPSTAT_INC(txrequests); } /* * Resolve an IP address into an ethernet address - heavy version. * Used internally by arpresolve(). * We have already checked than we can't use existing lle without * modification so we have to acquire LLE_EXCLUSIVE lle lock. * * On success, desten and flags are filled in and the function returns 0; * If the packet must be held pending resolution, we return EWOULDBLOCK * On other errors, we return the corresponding error code. * Note that m_freem() handles NULL. */ static int arpresolve_full(struct ifnet *ifp, int is_gw, int create, struct mbuf *m, const struct sockaddr *dst, u_char *desten, uint32_t *pflags) { struct llentry *la = NULL, *la_tmp; struct mbuf *curr = NULL; struct mbuf *next = NULL; int error, renew; if (pflags != NULL) *pflags = 0; if (create == 0) { IF_AFDATA_RLOCK(ifp); la = lla_lookup(LLTABLE(ifp), LLE_EXCLUSIVE, dst); IF_AFDATA_RUNLOCK(ifp); } if (la == NULL && (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) { la = lltable_alloc_entry(LLTABLE(ifp), 0, dst); if (la == NULL) { log(LOG_DEBUG, "arpresolve: can't allocate llinfo for %s on %s\n", inet_ntoa(SIN(dst)->sin_addr), if_name(ifp)); m_freem(m); return (EINVAL); } IF_AFDATA_WLOCK(ifp); LLE_WLOCK(la); la_tmp = lla_lookup(LLTABLE(ifp), LLE_EXCLUSIVE, dst); /* Prefer ANY existing lle over newly-created one */ if (la_tmp == NULL) lltable_link_entry(LLTABLE(ifp), la); IF_AFDATA_WUNLOCK(ifp); if (la_tmp != NULL) { lltable_free_entry(LLTABLE(ifp), la); la = la_tmp; } } if (la == NULL) { m_freem(m); return (EINVAL); } if ((la->la_flags & LLE_VALID) && ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) { bcopy(&la->ll_addr, desten, ifp->if_addrlen); /* Check if we have feedback request from arptimer() */ if (la->r_skip_req != 0) { LLE_REQ_LOCK(la); la->r_skip_req = 0; /* Notify that entry was used */ LLE_REQ_UNLOCK(la); } if (pflags != NULL) *pflags = la->la_flags & (LLE_VALID|LLE_IFADDR); LLE_WUNLOCK(la); return (0); } renew = (la->la_asked == 0 || la->la_expire != time_uptime); /* * There is an arptab entry, but no ethernet address * response yet. Add the mbuf to the list, dropping * the oldest packet if we have exceeded the system * setting. */ if (m != NULL) { if (la->la_numheld >= V_arp_maxhold) { if (la->la_hold != NULL) { next = la->la_hold->m_nextpkt; m_freem(la->la_hold); la->la_hold = next; la->la_numheld--; ARPSTAT_INC(dropped); } } if (la->la_hold != NULL) { curr = la->la_hold; while (curr->m_nextpkt != NULL) curr = curr->m_nextpkt; curr->m_nextpkt = m; } else la->la_hold = m; la->la_numheld++; } /* * Return EWOULDBLOCK if we have tried less than arp_maxtries. It * will be masked by ether_output(). Return EHOSTDOWN/EHOSTUNREACH * if we have already sent arp_maxtries ARP requests. Retransmit the * ARP request, but not faster than one request per second. */ if (la->la_asked < V_arp_maxtries) error = EWOULDBLOCK; /* First request. */ else error = is_gw != 0 ? EHOSTUNREACH : EHOSTDOWN; if (renew) { int canceled; LLE_ADDREF(la); la->la_expire = time_uptime; canceled = callout_reset(&la->lle_timer, hz * V_arpt_down, arptimer, la); if (canceled) LLE_REMREF(la); la->la_asked++; LLE_WUNLOCK(la); arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL); return (error); } LLE_WUNLOCK(la); return (error); } /* * Resolve an IP address into an ethernet address. * On input: * ifp is the interface we use * is_gw != 0 if @dst represents gateway to some destination * m is the mbuf. May be NULL if we don't have a packet. * dst is the next hop, * desten is the storage to put LL address. * flags returns subset of lle flags: LLE_VALID | LLE_IFADDR * * On success, desten and flags are filled in and the function returns 0; * If the packet must be held pending resolution, we return EWOULDBLOCK * On other errors, we return the corresponding error code. * Note that m_freem() handles NULL. */ int arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m, const struct sockaddr *dst, u_char *desten, uint32_t *pflags) { struct llentry *la = 0; if (pflags != NULL) *pflags = 0; if (m != NULL) { if (m->m_flags & M_BCAST) { /* broadcast */ (void)memcpy(desten, ifp->if_broadcastaddr, ifp->if_addrlen); return (0); } if (m->m_flags & M_MCAST) { /* multicast */ ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten); return (0); } } IF_AFDATA_RLOCK(ifp); la = lla_lookup(LLTABLE(ifp), LLE_UNLOCKED, dst); if (la != NULL && (la->r_flags & RLLE_VALID) != 0) { /* Entry found, let's copy lle info */ bcopy(&la->ll_addr, desten, ifp->if_addrlen); if (pflags != NULL) *pflags = LLE_VALID | (la->r_flags & RLLE_IFADDR); /* Check if we have feedback request from arptimer() */ if (la->r_skip_req != 0) { LLE_REQ_LOCK(la); la->r_skip_req = 0; /* Notify that entry was used */ LLE_REQ_UNLOCK(la); } IF_AFDATA_RUNLOCK(ifp); return (0); } IF_AFDATA_RUNLOCK(ifp); return (arpresolve_full(ifp, is_gw, 1, m, dst, desten, pflags)); } /* * Common length and type checks are done here, * then the protocol-specific routine is called. */ static void arpintr(struct mbuf *m) { struct arphdr *ar; struct ifnet *ifp; char *layer; int hlen; ifp = m->m_pkthdr.rcvif; if (m->m_len < sizeof(struct arphdr) && ((m = m_pullup(m, sizeof(struct arphdr))) == NULL)) { ARP_LOG(LOG_NOTICE, "packet with short header received on %s\n", if_name(ifp)); return; } ar = mtod(m, struct arphdr *); /* Check if length is sufficient */ if (m->m_len < arphdr_len(ar)) { m = m_pullup(m, arphdr_len(ar)); if (m == NULL) { ARP_LOG(LOG_NOTICE, "short packet received on %s\n", if_name(ifp)); return; } ar = mtod(m, struct arphdr *); } hlen = 0; layer = ""; switch (ntohs(ar->ar_hrd)) { case ARPHRD_ETHER: hlen = ETHER_ADDR_LEN; /* RFC 826 */ layer = "ethernet"; break; case ARPHRD_IEEE802: hlen = 6; /* RFC 1390, FDDI_ADDR_LEN */ layer = "fddi"; break; case ARPHRD_ARCNET: hlen = 1; /* RFC 1201, ARC_ADDR_LEN */ layer = "arcnet"; break; case ARPHRD_INFINIBAND: hlen = 20; /* RFC 4391, INFINIBAND_ALEN */ layer = "infiniband"; break; case ARPHRD_IEEE1394: hlen = 0; /* SHALL be 16 */ /* RFC 2734 */ layer = "firewire"; /* * Restrict too long harware addresses. * Currently we are capable of handling 20-byte * addresses ( sizeof(lle->ll_addr) ) */ if (ar->ar_hln >= 20) hlen = 16; break; default: ARP_LOG(LOG_NOTICE, "packet with unknown harware format 0x%02d received on %s\n", ntohs(ar->ar_hrd), if_name(ifp)); m_freem(m); return; } if (hlen != 0 && hlen != ar->ar_hln) { ARP_LOG(LOG_NOTICE, "packet with invalid %s address length %d received on %s\n", layer, ar->ar_hln, if_name(ifp)); m_freem(m); return; } ARPSTAT_INC(received); switch (ntohs(ar->ar_pro)) { #ifdef INET case ETHERTYPE_IP: in_arpinput(m); return; #endif } m_freem(m); } #ifdef INET /* * ARP for Internet protocols on 10 Mb/s Ethernet. * Algorithm is that given in RFC 826. * In addition, a sanity check is performed on the sender * protocol address, to catch impersonators. * We no longer handle negotiations for use of trailer protocol: * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent * along with IP replies if we wanted trailers sent to us, * and also sent them in response to IP replies. * This allowed either end to announce the desire to receive * trailer packets. * We no longer reply to requests for ETHERTYPE_TRAIL protocol either, * but formerly didn't normally send requests. */ static int log_arp_wrong_iface = 1; static int log_arp_movements = 1; static int log_arp_permanent_modify = 1; static int allow_multicast = 0; SYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_wrong_iface, CTLFLAG_RW, &log_arp_wrong_iface, 0, "log arp packets arriving on the wrong interface"); SYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_movements, CTLFLAG_RW, &log_arp_movements, 0, "log arp replies from MACs different than the one in the cache"); SYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_permanent_modify, CTLFLAG_RW, &log_arp_permanent_modify, 0, "log arp replies from MACs different than the one in the permanent arp entry"); SYSCTL_INT(_net_link_ether_inet, OID_AUTO, allow_multicast, CTLFLAG_RW, &allow_multicast, 0, "accept multicast addresses"); static void in_arpinput(struct mbuf *m) { struct rm_priotracker in_ifa_tracker; struct arphdr *ah; struct ifnet *ifp = m->m_pkthdr.rcvif; struct llentry *la = NULL, *la_tmp; struct ifaddr *ifa; struct in_ifaddr *ia; struct sockaddr sa; struct in_addr isaddr, itaddr, myaddr; u_int8_t *enaddr = NULL; int op; int bridged = 0, is_bridge = 0; int carped; struct sockaddr_in sin; struct sockaddr *dst; struct nhop4_basic nh4; sin.sin_len = sizeof(struct sockaddr_in); sin.sin_family = AF_INET; sin.sin_addr.s_addr = 0; if (ifp->if_bridge) bridged = 1; if (ifp->if_type == IFT_BRIDGE) is_bridge = 1; /* * We already have checked that mbuf contains enough contiguous data * to hold entire arp message according to the arp header. */ ah = mtod(m, struct arphdr *); /* * ARP is only for IPv4 so we can reject packets with * a protocol length not equal to an IPv4 address. */ if (ah->ar_pln != sizeof(struct in_addr)) { ARP_LOG(LOG_NOTICE, "requested protocol length != %zu\n", sizeof(struct in_addr)); goto drop; } if (allow_multicast == 0 && ETHER_IS_MULTICAST(ar_sha(ah))) { ARP_LOG(LOG_NOTICE, "%*D is multicast\n", ifp->if_addrlen, (u_char *)ar_sha(ah), ":"); goto drop; } op = ntohs(ah->ar_op); (void)memcpy(&isaddr, ar_spa(ah), sizeof (isaddr)); (void)memcpy(&itaddr, ar_tpa(ah), sizeof (itaddr)); if (op == ARPOP_REPLY) ARPSTAT_INC(rxreplies); /* * For a bridge, we want to check the address irrespective * of the receive interface. (This will change slightly * when we have clusters of interfaces). */ IN_IFADDR_RLOCK(&in_ifa_tracker); LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) || ia->ia_ifp == ifp) && itaddr.s_addr == ia->ia_addr.sin_addr.s_addr && (ia->ia_ifa.ifa_carp == NULL || (*carp_iamatch_p)(&ia->ia_ifa, &enaddr))) { ifa_ref(&ia->ia_ifa); IN_IFADDR_RUNLOCK(&in_ifa_tracker); goto match; } } LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash) if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) || ia->ia_ifp == ifp) && isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) { ifa_ref(&ia->ia_ifa); IN_IFADDR_RUNLOCK(&in_ifa_tracker); goto match; } #define BDG_MEMBER_MATCHES_ARP(addr, ifp, ia) \ (ia->ia_ifp->if_bridge == ifp->if_softc && \ !bcmp(IF_LLADDR(ia->ia_ifp), IF_LLADDR(ifp), ifp->if_addrlen) && \ addr == ia->ia_addr.sin_addr.s_addr) /* * Check the case when bridge shares its MAC address with * some of its children, so packets are claimed by bridge * itself (bridge_input() does it first), but they are really * meant to be destined to the bridge member. */ if (is_bridge) { LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) { ifa_ref(&ia->ia_ifa); ifp = ia->ia_ifp; IN_IFADDR_RUNLOCK(&in_ifa_tracker); goto match; } } } #undef BDG_MEMBER_MATCHES_ARP IN_IFADDR_RUNLOCK(&in_ifa_tracker); /* * No match, use the first inet address on the receive interface * as a dummy address for the rest of the function. */ IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) if (ifa->ifa_addr->sa_family == AF_INET && (ifa->ifa_carp == NULL || (*carp_iamatch_p)(ifa, &enaddr))) { ia = ifatoia(ifa); ifa_ref(ifa); IF_ADDR_RUNLOCK(ifp); goto match; } IF_ADDR_RUNLOCK(ifp); /* * If bridging, fall back to using any inet address. */ IN_IFADDR_RLOCK(&in_ifa_tracker); if (!bridged || (ia = TAILQ_FIRST(&V_in_ifaddrhead)) == NULL) { IN_IFADDR_RUNLOCK(&in_ifa_tracker); goto drop; } ifa_ref(&ia->ia_ifa); IN_IFADDR_RUNLOCK(&in_ifa_tracker); match: if (!enaddr) enaddr = (u_int8_t *)IF_LLADDR(ifp); carped = (ia->ia_ifa.ifa_carp != NULL); myaddr = ia->ia_addr.sin_addr; ifa_free(&ia->ia_ifa); if (!bcmp(ar_sha(ah), enaddr, ifp->if_addrlen)) goto drop; /* it's from me, ignore it. */ if (!bcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen)) { ARP_LOG(LOG_NOTICE, "link address is broadcast for IP address " "%s!\n", inet_ntoa(isaddr)); goto drop; } if (ifp->if_addrlen != ah->ar_hln) { ARP_LOG(LOG_WARNING, "from %*D: addr len: new %d, " "i/f %d (ignored)\n", ifp->if_addrlen, (u_char *) ar_sha(ah), ":", ah->ar_hln, ifp->if_addrlen); goto drop; } /* * Warn if another host is using the same IP address, but only if the * IP address isn't 0.0.0.0, which is used for DHCP only, in which * case we suppress the warning to avoid false positive complaints of * potential misconfiguration. */ if (!bridged && !carped && isaddr.s_addr == myaddr.s_addr && myaddr.s_addr != 0) { ARP_LOG(LOG_ERR, "%*D is using my IP address %s on %s!\n", ifp->if_addrlen, (u_char *)ar_sha(ah), ":", inet_ntoa(isaddr), ifp->if_xname); itaddr = myaddr; ARPSTAT_INC(dupips); goto reply; } if (ifp->if_flags & IFF_STATICARP) goto reply; bzero(&sin, sizeof(sin)); sin.sin_len = sizeof(struct sockaddr_in); sin.sin_family = AF_INET; sin.sin_addr = isaddr; dst = (struct sockaddr *)&sin; IF_AFDATA_RLOCK(ifp); la = lla_lookup(LLTABLE(ifp), LLE_EXCLUSIVE, dst); IF_AFDATA_RUNLOCK(ifp); if (la != NULL) arp_check_update_lle(ah, isaddr, ifp, bridged, la); else if (itaddr.s_addr == myaddr.s_addr) { /* * Request/reply to our address, but no lle exists yet. * Try to create new llentry. */ la = lltable_alloc_entry(LLTABLE(ifp), 0, dst); if (la == NULL) { /* * lle creation may fail if source address belongs * to non-directly connected subnet. However, we * will try to answer the request instead of dropping * frame. */ goto reply; } lltable_set_entry_addr(ifp, la, ar_sha(ah)); IF_AFDATA_WLOCK(ifp); LLE_WLOCK(la); la_tmp = lla_lookup(LLTABLE(ifp), LLE_EXCLUSIVE, dst); /* * Check if lle still does not exists. * If it does, that means that we either * 1) have configured it explicitly, via * 1a) 'arp -s' static entry or * 1b) interface address static record * or * 2) it was the result of sending first packet to-host * or * 3) it was another arp reply packet we handled in * different thread. * * In all cases except 3) we definitely need to prefer * existing lle. For the sake of simplicity, prefer any * existing lle over newly-create one. */ if (la_tmp == NULL) lltable_link_entry(LLTABLE(ifp), la); IF_AFDATA_WUNLOCK(ifp); if (la_tmp == NULL) { arp_mark_lle_reachable(la); LLE_WUNLOCK(la); } else { /* Free newly-create entry and handle packet */ lltable_free_entry(LLTABLE(ifp), la); la = la_tmp; la_tmp = NULL; arp_check_update_lle(ah, isaddr, ifp, bridged, la); /* arp_check_update_lle() returns @la unlocked */ } la = NULL; } reply: if (op != ARPOP_REQUEST) goto drop; ARPSTAT_INC(rxrequests); if (itaddr.s_addr == myaddr.s_addr) { /* Shortcut.. the receiving interface is the target. */ (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); } else { struct llentry *lle = NULL; sin.sin_addr = itaddr; IF_AFDATA_RLOCK(ifp); lle = lla_lookup(LLTABLE(ifp), 0, (struct sockaddr *)&sin); IF_AFDATA_RUNLOCK(ifp); if ((lle != NULL) && (lle->la_flags & LLE_PUB)) { (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); (void)memcpy(ar_sha(ah), &lle->ll_addr, ah->ar_hln); LLE_RUNLOCK(lle); } else { if (lle != NULL) LLE_RUNLOCK(lle); if (!V_arp_proxyall) goto drop; /* XXX MRT use table 0 for arp reply */ if (fib4_lookup_nh_basic(0, itaddr, 0, 0, &nh4) != 0) goto drop; /* * Don't send proxies for nodes on the same interface * as this one came out of, or we'll get into a fight * over who claims what Ether address. */ if (nh4.nh_ifp == ifp) goto drop; (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); /* * Also check that the node which sent the ARP packet * is on the interface we expect it to be on. This * avoids ARP chaos if an interface is connected to the * wrong network. */ /* XXX MRT use table 0 for arp checks */ if (fib4_lookup_nh_basic(0, isaddr, 0, 0, &nh4) != 0) goto drop; if (nh4.nh_ifp != ifp) { ARP_LOG(LOG_INFO, "proxy: ignoring request" " from %s via %s\n", inet_ntoa(isaddr), ifp->if_xname); goto drop; } #ifdef DEBUG_PROXY printf("arp: proxying for %s\n", inet_ntoa(itaddr)); #endif } } if (itaddr.s_addr == myaddr.s_addr && IN_LINKLOCAL(ntohl(itaddr.s_addr))) { /* RFC 3927 link-local IPv4; always reply by broadcast. */ #ifdef DEBUG_LINKLOCAL printf("arp: sending reply for link-local addr %s\n", inet_ntoa(itaddr)); #endif m->m_flags |= M_BCAST; m->m_flags &= ~M_MCAST; } else { /* default behaviour; never reply by broadcast. */ m->m_flags &= ~(M_BCAST|M_MCAST); } (void)memcpy(ar_tpa(ah), ar_spa(ah), ah->ar_pln); (void)memcpy(ar_spa(ah), &itaddr, ah->ar_pln); ah->ar_op = htons(ARPOP_REPLY); ah->ar_pro = htons(ETHERTYPE_IP); /* let's be sure! */ m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln); m->m_pkthdr.len = m->m_len; m->m_pkthdr.rcvif = NULL; sa.sa_family = AF_ARP; sa.sa_len = 2; m_clrprotoflags(m); /* Avoid confusing lower layers. */ (*ifp->if_output)(ifp, m, &sa, NULL); ARPSTAT_INC(txreplies); return; drop: m_freem(m); } #endif /* * Checks received arp data against existing @la. * Updates lle state/performs notification if necessary. */ static void arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp, int bridged, struct llentry *la) { struct sockaddr sa; struct mbuf *m_hold, *m_hold_next; LLE_WLOCK_ASSERT(la); /* the following is not an error when doing bridging */ if (!bridged && la->lle_tbl->llt_ifp != ifp) { if (log_arp_wrong_iface) ARP_LOG(LOG_WARNING, "%s is on %s " "but got reply from %*D on %s\n", inet_ntoa(isaddr), la->lle_tbl->llt_ifp->if_xname, ifp->if_addrlen, (u_char *)ar_sha(ah), ":", ifp->if_xname); LLE_WUNLOCK(la); return; } if ((la->la_flags & LLE_VALID) && bcmp(ar_sha(ah), &la->ll_addr, ifp->if_addrlen)) { if (la->la_flags & LLE_STATIC) { LLE_WUNLOCK(la); if (log_arp_permanent_modify) ARP_LOG(LOG_ERR, "%*D attempts to modify " "permanent entry for %s on %s\n", ifp->if_addrlen, (u_char *)ar_sha(ah), ":", inet_ntoa(isaddr), ifp->if_xname); return; } if (log_arp_movements) { ARP_LOG(LOG_INFO, "%s moved from %*D " "to %*D on %s\n", inet_ntoa(isaddr), ifp->if_addrlen, (u_char *)&la->ll_addr, ":", ifp->if_addrlen, (u_char *)ar_sha(ah), ":", ifp->if_xname); } } /* Check if something has changed */ if (memcmp(&la->ll_addr, ar_sha(ah), ifp->if_addrlen) != 0 || (la->la_flags & LLE_VALID) == 0) { /* Perform real LLE update */ /* use afdata WLOCK to update fields */ LLE_ADDREF(la); LLE_WUNLOCK(la); IF_AFDATA_WLOCK(ifp); LLE_WLOCK(la); /* * Since we droppped LLE lock, other thread might have deleted * this lle. Check and return */ if ((la->la_flags & LLE_DELETED) != 0) { IF_AFDATA_WUNLOCK(ifp); LLE_FREE_LOCKED(la); return; } /* Update data */ lltable_set_entry_addr(ifp, la, ar_sha(ah)); IF_AFDATA_WUNLOCK(ifp); LLE_REMREF(la); /* Clear fast path feedback request if set */ la->r_skip_req = 0; } arp_mark_lle_reachable(la); /* * The packets are all freed within the call to the output * routine. * * NB: The lock MUST be released before the call to the * output routine. */ if (la->la_hold != NULL) { m_hold = la->la_hold; la->la_hold = NULL; la->la_numheld = 0; lltable_fill_sa_entry(la, &sa); LLE_WUNLOCK(la); for (; m_hold != NULL; m_hold = m_hold_next) { m_hold_next = m_hold->m_nextpkt; m_hold->m_nextpkt = NULL; /* Avoid confusing lower layers. */ m_clrprotoflags(m_hold); (*ifp->if_output)(ifp, m_hold, &sa, NULL); } } else LLE_WUNLOCK(la); } static void arp_mark_lle_reachable(struct llentry *la) { int canceled, wtime; LLE_WLOCK_ASSERT(la); la->ln_state = ARP_LLINFO_REACHABLE; EVENTHANDLER_INVOKE(lle_event, la, LLENTRY_RESOLVED); if (!(la->la_flags & LLE_STATIC)) { LLE_ADDREF(la); la->la_expire = time_uptime + V_arpt_keep; wtime = V_arpt_keep - V_arp_maxtries * V_arpt_rexmit; if (wtime < 0) wtime = V_arpt_keep; canceled = callout_reset(&la->lle_timer, hz * wtime, arptimer, la); if (canceled) LLE_REMREF(la); } la->la_asked = 0; la->la_preempt = V_arp_maxtries; } /* * Add pernament link-layer record for given interface address. */ static __noinline void arp_add_ifa_lle(struct ifnet *ifp, const struct sockaddr *dst) { struct llentry *lle, *lle_tmp; /* * Interface address LLE record is considered static * because kernel code relies on LLE_STATIC flag to check * if these entries can be rewriten by arp updates. */ lle = lltable_alloc_entry(LLTABLE(ifp), LLE_IFADDR | LLE_STATIC, dst); if (lle == NULL) { log(LOG_INFO, "arp_ifinit: cannot create arp " "entry for interface address\n"); return; } IF_AFDATA_WLOCK(ifp); LLE_WLOCK(lle); /* Unlink any entry if exists */ lle_tmp = lla_lookup(LLTABLE(ifp), LLE_EXCLUSIVE, dst); if (lle_tmp != NULL) lltable_unlink_entry(LLTABLE(ifp), lle_tmp); lltable_link_entry(LLTABLE(ifp), lle); IF_AFDATA_WUNLOCK(ifp); if (lle_tmp != NULL) EVENTHANDLER_INVOKE(lle_event, lle_tmp, LLENTRY_EXPIRED); EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_RESOLVED); LLE_WUNLOCK(lle); if (lle_tmp != NULL) lltable_free_entry(LLTABLE(ifp), lle_tmp); } void arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa) { const struct sockaddr_in *dst_in; const struct sockaddr *dst; if (ifa->ifa_carp != NULL) return; dst = ifa->ifa_addr; dst_in = (const struct sockaddr_in *)dst; if (ntohl(dst_in->sin_addr.s_addr) == INADDR_ANY) return; - arp_announce_addr(ifp, &dst_in->sin_addr, IF_LLADDR(ifp)); + arp_announce_ifaddr(ifp, dst_in->sin_addr, IF_LLADDR(ifp)); arp_add_ifa_lle(ifp, dst); } -void __noinline -arp_announce_addr(struct ifnet *ifp, const struct in_addr *addr, u_char *enaddr) +void +arp_announce_ifaddr(struct ifnet *ifp, struct in_addr addr, u_char *enaddr) { - if (ntohl(addr->s_addr) != INADDR_ANY) - arprequest(ifp, addr, addr, enaddr); + if (ntohl(addr.s_addr) != INADDR_ANY) + arprequest(ifp, &addr, &addr, enaddr); } /* - * Send gratuitous ARPs for all interfaces addresses to notify other nodes of - * changes. - * - * This is a noop if the interface isn't up or has been flagged for no ARP. + * Sends gratuitous ARPs for each ifaddr to notify other + * nodes about the address change. */ -void __noinline -arp_announce(struct ifnet *ifp) +static __noinline void +arp_handle_ifllchange(struct ifnet *ifp) { - int i, cnt, entries; - u_char *lladdr; struct ifaddr *ifa; - struct in_addr *addr, *head; - if (!(ifp->if_flags & IFF_UP) || (ifp->if_flags & IFF_NOARP) || - ifp->if_addr == NULL) - return; - - entries = 8; - cnt = 0; - head = malloc(sizeof(*addr) * entries, M_TEMP, M_NOWAIT); - if (head == NULL) { - log(LOG_INFO, "arp_announce: malloc %d entries failed\n", - entries); - return; - } - - /* Take a copy then process to avoid locking issues. */ - IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { - if (ifa->ifa_addr->sa_family != AF_INET) - continue; - - if (cnt == entries) { - addr = (struct in_addr *)realloc(head, sizeof(*addr) * - (entries + 8), M_TEMP, M_NOWAIT); - if (addr == NULL) { - log(LOG_INFO, "arp_announce: realloc to %d " - "entries failed\n", entries + 8); - /* Process what we have. */ - break; - } - entries += 8; - head = addr; - } - - addr = head + cnt; - bcopy(IFA_IN(ifa), addr, sizeof(*addr)); - cnt++; + if (ifa->ifa_addr->sa_family == AF_INET) + arp_ifinit(ifp, ifa); } - IF_ADDR_RUNLOCK(ifp); - - if (cnt > 0) { - lladdr = IF_LLADDR(ifp); - for (i = 0; i < cnt; i++) { - arp_announce_addr(ifp, head + i, lladdr); - } - } - free(head, M_TEMP); } /* - * A handler for interface linkstate change events. + * A handler for interface link layer address change event. */ -static void -arp_ifnet_link_event(void *arg __unused, struct ifnet *ifp, int linkstate) -{ - - if (linkstate == LINK_STATE_UP && V_arp_on_link) - arp_announce(ifp); -} - -/* - * A handler for interface link layer address change events. - */ static __noinline void arp_iflladdr(void *arg __unused, struct ifnet *ifp) { - arp_announce(ifp); + if ((ifp->if_flags & IFF_UP) != 0) + arp_handle_ifllchange(ifp); } static void arp_init(void) { netisr_register(&arp_nh); - - if (IS_DEFAULT_VNET(curvnet)) { + if (IS_DEFAULT_VNET(curvnet)) iflladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event, arp_iflladdr, NULL, EVENTHANDLER_PRI_ANY); - ifnet_link_event_tag = EVENTHANDLER_REGISTER(ifnet_link_event, - arp_ifnet_link_event, 0, EVENTHANDLER_PRI_ANY); - } } SYSINIT(arp, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, arp_init, 0); Index: user/alc/PQ_LAUNDRY/sys/netinet/if_ether.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/netinet/if_ether.h (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/netinet/if_ether.h (revision 292449) @@ -1,126 +1,125 @@ /*- * 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. * 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. * * @(#)if_ether.h 8.3 (Berkeley) 5/2/95 * $FreeBSD$ */ #ifndef _NETINET_IF_ETHER_H_ #define _NETINET_IF_ETHER_H_ #include #include /* * Macro to map an IP multicast address to an Ethernet multicast address. * The high-order 25 bits of the Ethernet address are statically assigned, * and the low-order 23 bits are taken from the low end of the IP address. */ #define ETHER_MAP_IP_MULTICAST(ipaddr, enaddr) \ /* struct in_addr *ipaddr; */ \ /* u_char enaddr[ETHER_ADDR_LEN]; */ \ { \ (enaddr)[0] = 0x01; \ (enaddr)[1] = 0x00; \ (enaddr)[2] = 0x5e; \ (enaddr)[3] = ((const u_char *)ipaddr)[1] & 0x7f; \ (enaddr)[4] = ((const u_char *)ipaddr)[2]; \ (enaddr)[5] = ((const u_char *)ipaddr)[3]; \ } /* * Macro to map an IP6 multicast address to an Ethernet multicast address. * The high-order 16 bits of the Ethernet address are statically assigned, * and the low-order 32 bits are taken from the low end of the IP6 address. */ #define ETHER_MAP_IPV6_MULTICAST(ip6addr, enaddr) \ /* struct in6_addr *ip6addr; */ \ /* u_char enaddr[ETHER_ADDR_LEN]; */ \ { \ (enaddr)[0] = 0x33; \ (enaddr)[1] = 0x33; \ (enaddr)[2] = ((const u_char *)ip6addr)[12]; \ (enaddr)[3] = ((const u_char *)ip6addr)[13]; \ (enaddr)[4] = ((const u_char *)ip6addr)[14]; \ (enaddr)[5] = ((const u_char *)ip6addr)[15]; \ } /* * Ethernet Address Resolution Protocol. * * See RFC 826 for protocol description. Structure below is adapted * to resolving internet addresses. Field names used correspond to * RFC 826. */ struct ether_arp { struct arphdr ea_hdr; /* fixed-size header */ u_char arp_sha[ETHER_ADDR_LEN]; /* sender hardware address */ u_char arp_spa[4]; /* sender protocol address */ u_char arp_tha[ETHER_ADDR_LEN]; /* target hardware address */ u_char arp_tpa[4]; /* target protocol address */ }; #define arp_hrd ea_hdr.ar_hrd #define arp_pro ea_hdr.ar_pro #define arp_hln ea_hdr.ar_hln #define arp_pln ea_hdr.ar_pln #define arp_op ea_hdr.ar_op #ifndef BURN_BRIDGES /* Can be used by third party software. */ struct sockaddr_inarp { u_char sin_len; u_char sin_family; u_short sin_port; struct in_addr sin_addr; struct in_addr sin_srcaddr; u_short sin_tos; u_short sin_other; #define SIN_PROXY 1 }; #endif /* !BURN_BRIDGES */ /* * IP and ethernet specific routing flags */ #define RTF_USETRAILERS RTF_PROTO1 /* use trailers */ #define RTF_ANNOUNCE RTF_PROTO2 /* announce new arp entry */ #ifdef _KERNEL extern u_char ether_ipmulticast_min[ETHER_ADDR_LEN]; extern u_char ether_ipmulticast_max[ETHER_ADDR_LEN]; struct ifaddr; int arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m, const struct sockaddr *dst, u_char *desten, uint32_t *pflags); void arprequest(struct ifnet *, const struct in_addr *, const struct in_addr *, u_char *); void arp_ifinit(struct ifnet *, struct ifaddr *); -void arp_announce(struct ifnet *); -void arp_announce_addr(struct ifnet *, const struct in_addr *addr, u_char *); +void arp_announce_ifaddr(struct ifnet *, struct in_addr addr, u_char *); #endif #endif Index: user/alc/PQ_LAUNDRY/sys/netinet/in_var.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/netinet/in_var.h (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/netinet/in_var.h (revision 292449) @@ -1,402 +1,399 @@ /*- * Copyright (c) 1985, 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. * 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. * * @(#)in_var.h 8.2 (Berkeley) 1/9/95 * $FreeBSD$ */ #ifndef _NETINET_IN_VAR_H_ #define _NETINET_IN_VAR_H_ /* * Argument structure for SIOCAIFADDR. */ struct in_aliasreq { char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ struct sockaddr_in ifra_addr; struct sockaddr_in ifra_broadaddr; #define ifra_dstaddr ifra_broadaddr struct sockaddr_in ifra_mask; int ifra_vhid; }; #ifdef _KERNEL #include #include #include struct igmp_ifsoftc; struct in_multi; struct lltable; /* * IPv4 per-interface state. */ struct in_ifinfo { struct lltable *ii_llt; /* ARP state */ struct igmp_ifsoftc *ii_igmp; /* IGMP state */ struct in_multi *ii_allhosts; /* 224.0.0.1 membership */ }; /* * Interface address, Internet version. One of these structures * is allocated for each Internet address on an interface. * The ifaddr structure contains the protocol-independent part * of the structure and is assumed to be first. */ struct in_ifaddr { struct ifaddr ia_ifa; /* protocol-independent info */ #define ia_ifp ia_ifa.ifa_ifp #define ia_flags ia_ifa.ifa_flags /* ia_subnet{,mask} in host order */ u_long ia_subnet; /* subnet address */ u_long ia_subnetmask; /* mask of subnet */ LIST_ENTRY(in_ifaddr) ia_hash; /* entry in bucket of inet addresses */ TAILQ_ENTRY(in_ifaddr) ia_link; /* list of internet addresses */ struct sockaddr_in ia_addr; /* reserve space for interface name */ struct sockaddr_in ia_dstaddr; /* reserve space for broadcast addr */ #define ia_broadaddr ia_dstaddr struct sockaddr_in ia_sockmask; /* reserve space for general netmask */ }; /* * Given a pointer to an in_ifaddr (ifaddr), * return a pointer to the addr as a sockaddr_in. */ #define IA_SIN(ia) (&(((struct in_ifaddr *)(ia))->ia_addr)) #define IA_DSTSIN(ia) (&(((struct in_ifaddr *)(ia))->ia_dstaddr)) #define IA_MASKSIN(ia) (&(((struct in_ifaddr *)(ia))->ia_sockmask)) #define IN_LNAOF(in, ifa) \ ((ntohl((in).s_addr) & ~((struct in_ifaddr *)(ifa)->ia_subnetmask)) extern u_char inetctlerrmap[]; #define LLTABLE(ifp) \ ((struct in_ifinfo *)(ifp)->if_afdata[AF_INET])->ii_llt /* * Hash table for IP addresses. */ TAILQ_HEAD(in_ifaddrhead, in_ifaddr); LIST_HEAD(in_ifaddrhashhead, in_ifaddr); VNET_DECLARE(struct in_ifaddrhashhead *, in_ifaddrhashtbl); VNET_DECLARE(struct in_ifaddrhead, in_ifaddrhead); VNET_DECLARE(u_long, in_ifaddrhmask); /* mask for hash table */ #define V_in_ifaddrhashtbl VNET(in_ifaddrhashtbl) #define V_in_ifaddrhead VNET(in_ifaddrhead) #define V_in_ifaddrhmask VNET(in_ifaddrhmask) #define INADDR_NHASH_LOG2 9 #define INADDR_NHASH (1 << INADDR_NHASH_LOG2) #define INADDR_HASHVAL(x) fnv_32_buf((&(x)), sizeof(x), FNV1_32_INIT) #define INADDR_HASH(x) \ (&V_in_ifaddrhashtbl[INADDR_HASHVAL(x) & V_in_ifaddrhmask]) extern struct rmlock in_ifaddr_lock; #define IN_IFADDR_LOCK_ASSERT() rm_assert(&in_ifaddr_lock, RA_LOCKED) #define IN_IFADDR_RLOCK(t) rm_rlock(&in_ifaddr_lock, (t)) #define IN_IFADDR_RLOCK_ASSERT() rm_assert(&in_ifaddr_lock, RA_RLOCKED) #define IN_IFADDR_RUNLOCK(t) rm_runlock(&in_ifaddr_lock, (t)) #define IN_IFADDR_WLOCK() rm_wlock(&in_ifaddr_lock) #define IN_IFADDR_WLOCK_ASSERT() rm_assert(&in_ifaddr_lock, RA_WLOCKED) #define IN_IFADDR_WUNLOCK() rm_wunlock(&in_ifaddr_lock) -#define IFA_IN(ifa) \ - (&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr) - /* * Macro for finding the internet address structure (in_ifaddr) * corresponding to one of our IP addresses (in_addr). */ #define INADDR_TO_IFADDR(addr, ia) \ /* struct in_addr addr; */ \ /* struct in_ifaddr *ia; */ \ do { \ \ LIST_FOREACH(ia, INADDR_HASH((addr).s_addr), ia_hash) \ if (IA_SIN(ia)->sin_addr.s_addr == (addr).s_addr) \ break; \ } while (0) /* * Macro for finding the interface (ifnet structure) corresponding to one * of our IP addresses. */ #define INADDR_TO_IFP(addr, ifp) \ /* struct in_addr addr; */ \ /* struct ifnet *ifp; */ \ { \ struct in_ifaddr *ia; \ \ INADDR_TO_IFADDR(addr, ia); \ (ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \ } /* * Macro for finding the internet address structure (in_ifaddr) corresponding * to a given interface (ifnet structure). */ #define IFP_TO_IA(ifp, ia, t) \ /* struct ifnet *ifp; */ \ /* struct in_ifaddr *ia; */ \ /* struct rm_priotracker *t; */ \ do { \ IN_IFADDR_RLOCK((t)); \ for ((ia) = TAILQ_FIRST(&V_in_ifaddrhead); \ (ia) != NULL && (ia)->ia_ifp != (ifp); \ (ia) = TAILQ_NEXT((ia), ia_link)) \ continue; \ if ((ia) != NULL) \ ifa_ref(&(ia)->ia_ifa); \ IN_IFADDR_RUNLOCK((t)); \ } while (0) /* * Legacy IPv4 IGMP per-link structure. */ struct router_info { struct ifnet *rti_ifp; int rti_type; /* type of router which is querier on this interface */ int rti_time; /* # of slow timeouts since last old query */ SLIST_ENTRY(router_info) rti_list; }; /* * IPv4 multicast IGMP-layer source entry. */ struct ip_msource { RB_ENTRY(ip_msource) ims_link; /* RB tree links */ in_addr_t ims_haddr; /* host byte order */ struct ims_st { uint16_t ex; /* # of exclusive members */ uint16_t in; /* # of inclusive members */ } ims_st[2]; /* state at t0, t1 */ uint8_t ims_stp; /* pending query */ }; /* * IPv4 multicast PCB-layer source entry. */ struct in_msource { RB_ENTRY(ip_msource) ims_link; /* RB tree links */ in_addr_t ims_haddr; /* host byte order */ uint8_t imsl_st[2]; /* state before/at commit */ }; RB_HEAD(ip_msource_tree, ip_msource); /* define struct ip_msource_tree */ static __inline int ip_msource_cmp(const struct ip_msource *a, const struct ip_msource *b) { if (a->ims_haddr < b->ims_haddr) return (-1); if (a->ims_haddr == b->ims_haddr) return (0); return (1); } RB_PROTOTYPE(ip_msource_tree, ip_msource, ims_link, ip_msource_cmp); /* * IPv4 multicast PCB-layer group filter descriptor. */ struct in_mfilter { struct ip_msource_tree imf_sources; /* source list for (S,G) */ u_long imf_nsrc; /* # of source entries */ uint8_t imf_st[2]; /* state before/at commit */ }; /* * IPv4 group descriptor. * * For every entry on an ifnet's if_multiaddrs list which represents * an IP multicast group, there is one of these structures. * * If any source filters are present, then a node will exist in the RB-tree * to permit fast lookup by source whenever an operation takes place. * This permits pre-order traversal when we issue reports. * Source filter trees are kept separately from the socket layer to * greatly simplify locking. * * When IGMPv3 is active, inm_timer is the response to group query timer. * The state-change timer inm_sctimer is separate; whenever state changes * for the group the state change record is generated and transmitted, * and kept if retransmissions are necessary. * * FUTURE: inm_link is now only used when groups are being purged * on a detaching ifnet. It could be demoted to a SLIST_ENTRY, but * because it is at the very start of the struct, we can't do this * w/o breaking the ABI for ifmcstat. */ struct in_multi { LIST_ENTRY(in_multi) inm_link; /* to-be-released by in_ifdetach */ struct in_addr inm_addr; /* IP multicast address, convenience */ struct ifnet *inm_ifp; /* back pointer to ifnet */ struct ifmultiaddr *inm_ifma; /* back pointer to ifmultiaddr */ u_int inm_timer; /* IGMPv1/v2 group / v3 query timer */ u_int inm_state; /* state of the membership */ void *inm_rti; /* unused, legacy field */ u_int inm_refcount; /* reference count */ /* New fields for IGMPv3 follow. */ struct igmp_ifsoftc *inm_igi; /* IGMP info */ SLIST_ENTRY(in_multi) inm_nrele; /* to-be-released by IGMP */ struct ip_msource_tree inm_srcs; /* tree of sources */ u_long inm_nsrc; /* # of tree entries */ struct mbufq inm_scq; /* queue of pending * state-change packets */ struct timeval inm_lastgsrtv; /* Time of last G-S-R query */ uint16_t inm_sctimer; /* state-change timer */ uint16_t inm_scrv; /* state-change rexmit count */ /* * SSM state counters which track state at T0 (the time the last * state-change report's RV timer went to zero) and T1 * (time of pending report, i.e. now). * Used for computing IGMPv3 state-change reports. Several refcounts * are maintained here to optimize for common use-cases. */ struct inm_st { uint16_t iss_fmode; /* IGMP filter mode */ uint16_t iss_asm; /* # of ASM listeners */ uint16_t iss_ex; /* # of exclusive members */ uint16_t iss_in; /* # of inclusive members */ uint16_t iss_rec; /* # of recorded sources */ } inm_st[2]; /* state at t0, t1 */ }; /* * Helper function to derive the filter mode on a source entry * from its internal counters. Predicates are: * A source is only excluded if all listeners exclude it. * A source is only included if no listeners exclude it, * and at least one listener includes it. * May be used by ifmcstat(8). */ static __inline uint8_t ims_get_mode(const struct in_multi *inm, const struct ip_msource *ims, uint8_t t) { t = !!t; if (inm->inm_st[t].iss_ex > 0 && inm->inm_st[t].iss_ex == ims->ims_st[t].ex) return (MCAST_EXCLUDE); else if (ims->ims_st[t].in > 0 && ims->ims_st[t].ex == 0) return (MCAST_INCLUDE); return (MCAST_UNDEFINED); } #ifdef SYSCTL_DECL SYSCTL_DECL(_net_inet); SYSCTL_DECL(_net_inet_ip); SYSCTL_DECL(_net_inet_raw); #endif /* * Lock macros for IPv4 layer multicast address lists. IPv4 lock goes * before link layer multicast locks in the lock order. In most cases, * consumers of IN_*_MULTI() macros should acquire the locks before * calling them; users of the in_{add,del}multi() functions should not. */ extern struct mtx in_multi_mtx; #define IN_MULTI_LOCK() mtx_lock(&in_multi_mtx) #define IN_MULTI_UNLOCK() mtx_unlock(&in_multi_mtx) #define IN_MULTI_LOCK_ASSERT() mtx_assert(&in_multi_mtx, MA_OWNED) #define IN_MULTI_UNLOCK_ASSERT() mtx_assert(&in_multi_mtx, MA_NOTOWNED) /* Acquire an in_multi record. */ static __inline void inm_acquire_locked(struct in_multi *inm) { IN_MULTI_LOCK_ASSERT(); ++inm->inm_refcount; } /* * Return values for imo_multi_filter(). */ #define MCAST_PASS 0 /* Pass */ #define MCAST_NOTGMEMBER 1 /* This host not a member of group */ #define MCAST_NOTSMEMBER 2 /* This host excluded source */ #define MCAST_MUTED 3 /* [deprecated] */ struct rtentry; struct route; struct ip_moptions; struct radix_node_head; struct in_multi *inm_lookup_locked(struct ifnet *, const struct in_addr); struct in_multi *inm_lookup(struct ifnet *, const struct in_addr); int imo_multi_filter(const struct ip_moptions *, const struct ifnet *, const struct sockaddr *, const struct sockaddr *); void inm_commit(struct in_multi *); void inm_clear_recorded(struct in_multi *); void inm_print(const struct in_multi *); int inm_record_source(struct in_multi *inm, const in_addr_t); void inm_release(struct in_multi *); void inm_release_locked(struct in_multi *); struct in_multi * in_addmulti(struct in_addr *, struct ifnet *); void in_delmulti(struct in_multi *); int in_joingroup(struct ifnet *, const struct in_addr *, /*const*/ struct in_mfilter *, struct in_multi **); int in_joingroup_locked(struct ifnet *, const struct in_addr *, /*const*/ struct in_mfilter *, struct in_multi **); int in_leavegroup(struct in_multi *, /*const*/ struct in_mfilter *); int in_leavegroup_locked(struct in_multi *, /*const*/ struct in_mfilter *); int in_control(struct socket *, u_long, caddr_t, struct ifnet *, struct thread *); int in_addprefix(struct in_ifaddr *, int); int in_scrubprefix(struct in_ifaddr *, u_int); void ip_input(struct mbuf *); void ip_direct_input(struct mbuf *); void in_ifadown(struct ifaddr *ifa, int); struct mbuf *ip_tryforward(struct mbuf *); void *in_domifattach(struct ifnet *); void in_domifdetach(struct ifnet *, void *); /* XXX */ void in_rtalloc_ign(struct route *ro, u_long ignflags, u_int fibnum); void in_rtalloc(struct route *ro, u_int fibnum); struct rtentry *in_rtalloc1(struct sockaddr *, int, u_long, u_int); void in_rtredirect(struct sockaddr *, struct sockaddr *, struct sockaddr *, int, struct sockaddr *, u_int); #endif /* _KERNEL */ /* INET6 stuff */ #include #endif /* _NETINET_IN_VAR_H_ */ Index: user/alc/PQ_LAUNDRY/sys/netinet/ip_carp.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/netinet/ip_carp.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/netinet/ip_carp.c (revision 292449) @@ -1,2167 +1,2170 @@ /*- * Copyright (c) 2002 Michael Shalayeff. * Copyright (c) 2003 Ryan McBride. * Copyright (c) 2011 Gleb Smirnoff * 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 OR HIS RELATIVES 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 MIND, 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 __FBSDID("$FreeBSD$"); #include "opt_bpf.h" #include "opt_inet.h" #include "opt_inet6.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(INET) || defined(INET6) #include #include #include #include #include #endif #ifdef INET #include #include #endif #ifdef INET6 #include #include #include #include #include #include #endif #include static MALLOC_DEFINE(M_CARP, "CARP", "CARP addresses"); struct carp_softc { struct ifnet *sc_carpdev; /* Pointer to parent ifnet. */ struct ifaddr **sc_ifas; /* Our ifaddrs. */ struct sockaddr_dl sc_addr; /* Our link level address. */ struct callout sc_ad_tmo; /* Advertising timeout. */ #ifdef INET struct callout sc_md_tmo; /* Master down timeout. */ #endif #ifdef INET6 struct callout sc_md6_tmo; /* XXX: Master down timeout. */ #endif struct mtx sc_mtx; int sc_vhid; int sc_advskew; int sc_advbase; int sc_naddrs; int sc_naddrs6; int sc_ifasiz; enum { INIT = 0, BACKUP, MASTER } sc_state; int sc_suppress; int sc_sendad_errors; #define CARP_SENDAD_MAX_ERRORS 3 int sc_sendad_success; #define CARP_SENDAD_MIN_SUCCESS 3 int sc_init_counter; uint64_t sc_counter; /* authentication */ #define CARP_HMAC_PAD 64 unsigned char sc_key[CARP_KEY_LEN]; unsigned char sc_pad[CARP_HMAC_PAD]; SHA1_CTX sc_sha1; TAILQ_ENTRY(carp_softc) sc_list; /* On the carp_if list. */ LIST_ENTRY(carp_softc) sc_next; /* On the global list. */ }; struct carp_if { #ifdef INET int cif_naddrs; #endif #ifdef INET6 int cif_naddrs6; #endif TAILQ_HEAD(, carp_softc) cif_vrs; #ifdef INET struct ip_moptions cif_imo; #endif #ifdef INET6 struct ip6_moptions cif_im6o; #endif struct ifnet *cif_ifp; struct mtx cif_mtx; uint32_t cif_flags; #define CIF_PROMISC 0x00000001 }; #define CARP_INET 0 #define CARP_INET6 1 static int proto_reg[] = {-1, -1}; /* * Brief design of carp(4). * * Any carp-capable ifnet may have a list of carp softcs hanging off * its ifp->if_carp pointer. Each softc represents one unique virtual * host id, or vhid. The softc has a back pointer to the ifnet. All * softcs are joined in a global list, which has quite limited use. * * Any interface address that takes part in CARP negotiation has a * pointer to the softc of its vhid, ifa->ifa_carp. That could be either * AF_INET or AF_INET6 address. * * Although, one can get the softc's backpointer to ifnet and traverse * through its ifp->if_addrhead queue to find all interface addresses * involved in CARP, we keep a growable array of ifaddr pointers. This * allows us to avoid grabbing the IF_ADDR_LOCK() in many traversals that * do calls into the network stack, thus avoiding LORs. * * Locking: * * Each softc has a lock sc_mtx. It is used to synchronise carp_input_c(), * callout-driven events and ioctl()s. * * To traverse the list of softcs on an ifnet we use CIF_LOCK(), to * traverse the global list we use the mutex carp_mtx. * * Known issues with locking: * * - Sending ad, we put the pointer to the softc in an mtag, and no reference * counting is done on the softc. * - On module unload we may race (?) with packet processing thread * dereferencing our function pointers. */ /* Accept incoming CARP packets. */ static VNET_DEFINE(int, carp_allow) = 1; #define V_carp_allow VNET(carp_allow) /* Preempt slower nodes. */ static VNET_DEFINE(int, carp_preempt) = 0; #define V_carp_preempt VNET(carp_preempt) /* Log level. */ static VNET_DEFINE(int, carp_log) = 1; #define V_carp_log VNET(carp_log) /* Global advskew demotion. */ static VNET_DEFINE(int, carp_demotion) = 0; #define V_carp_demotion VNET(carp_demotion) /* Send error demotion factor. */ static VNET_DEFINE(int, carp_senderr_adj) = CARP_MAXSKEW; #define V_carp_senderr_adj VNET(carp_senderr_adj) /* Iface down demotion factor. */ static VNET_DEFINE(int, carp_ifdown_adj) = CARP_MAXSKEW; #define V_carp_ifdown_adj VNET(carp_ifdown_adj) static int carp_demote_adj_sysctl(SYSCTL_HANDLER_ARGS); SYSCTL_NODE(_net_inet, IPPROTO_CARP, carp, CTLFLAG_RW, 0, "CARP"); SYSCTL_INT(_net_inet_carp, OID_AUTO, allow, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(carp_allow), 0, "Accept incoming CARP packets"); SYSCTL_INT(_net_inet_carp, OID_AUTO, preempt, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(carp_preempt), 0, "High-priority backup preemption mode"); SYSCTL_INT(_net_inet_carp, OID_AUTO, log, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(carp_log), 0, "CARP log level"); SYSCTL_PROC(_net_inet_carp, OID_AUTO, demotion, CTLFLAG_VNET | CTLTYPE_INT | CTLFLAG_RW, 0, 0, carp_demote_adj_sysctl, "I", "Adjust demotion factor (skew of advskew)"); SYSCTL_INT(_net_inet_carp, OID_AUTO, senderr_demotion_factor, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(carp_senderr_adj), 0, "Send error demotion factor adjustment"); SYSCTL_INT(_net_inet_carp, OID_AUTO, ifdown_demotion_factor, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(carp_ifdown_adj), 0, "Interface down demotion factor adjustment"); VNET_PCPUSTAT_DEFINE(struct carpstats, carpstats); VNET_PCPUSTAT_SYSINIT(carpstats); VNET_PCPUSTAT_SYSUNINIT(carpstats); #define CARPSTATS_ADD(name, val) \ counter_u64_add(VNET(carpstats)[offsetof(struct carpstats, name) / \ sizeof(uint64_t)], (val)) #define CARPSTATS_INC(name) CARPSTATS_ADD(name, 1) SYSCTL_VNET_PCPUSTAT(_net_inet_carp, OID_AUTO, stats, struct carpstats, carpstats, "CARP statistics (struct carpstats, netinet/ip_carp.h)"); #define CARP_LOCK_INIT(sc) mtx_init(&(sc)->sc_mtx, "carp_softc", \ NULL, MTX_DEF) #define CARP_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx) #define CARP_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED) #define CARP_LOCK(sc) mtx_lock(&(sc)->sc_mtx) #define CARP_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) #define CIF_LOCK_INIT(cif) mtx_init(&(cif)->cif_mtx, "carp_if", \ NULL, MTX_DEF) #define CIF_LOCK_DESTROY(cif) mtx_destroy(&(cif)->cif_mtx) #define CIF_LOCK_ASSERT(cif) mtx_assert(&(cif)->cif_mtx, MA_OWNED) #define CIF_LOCK(cif) mtx_lock(&(cif)->cif_mtx) #define CIF_UNLOCK(cif) mtx_unlock(&(cif)->cif_mtx) #define CIF_FREE(cif) do { \ CIF_LOCK(cif); \ if (TAILQ_EMPTY(&(cif)->cif_vrs)) \ carp_free_if(cif); \ else \ CIF_UNLOCK(cif); \ } while (0) #define CARP_LOG(...) do { \ if (V_carp_log > 0) \ log(LOG_INFO, "carp: " __VA_ARGS__); \ } while (0) #define CARP_DEBUG(...) do { \ if (V_carp_log > 1) \ log(LOG_DEBUG, __VA_ARGS__); \ } while (0) #define IFNET_FOREACH_IFA(ifp, ifa) \ IF_ADDR_LOCK_ASSERT(ifp); \ TAILQ_FOREACH((ifa), &(ifp)->if_addrhead, ifa_link) \ if ((ifa)->ifa_carp != NULL) #define CARP_FOREACH_IFA(sc, ifa) \ CARP_LOCK_ASSERT(sc); \ for (int _i = 0; \ _i < (sc)->sc_naddrs + (sc)->sc_naddrs6 && \ ((ifa) = sc->sc_ifas[_i]) != NULL; \ ++_i) #define IFNET_FOREACH_CARP(ifp, sc) \ CIF_LOCK_ASSERT(ifp->if_carp); \ TAILQ_FOREACH((sc), &(ifp)->if_carp->cif_vrs, sc_list) #define DEMOTE_ADVSKEW(sc) \ (((sc)->sc_advskew + V_carp_demotion > CARP_MAXSKEW) ? \ CARP_MAXSKEW : ((sc)->sc_advskew + V_carp_demotion)) static void carp_input_c(struct mbuf *, struct carp_header *, sa_family_t); static struct carp_softc *carp_alloc(struct ifnet *); static void carp_destroy(struct carp_softc *); static struct carp_if *carp_alloc_if(struct ifnet *); static void carp_free_if(struct carp_if *); static void carp_set_state(struct carp_softc *, int, const char* reason); static void carp_sc_state(struct carp_softc *); static void carp_setrun(struct carp_softc *, sa_family_t); static void carp_master_down(void *); static void carp_master_down_locked(struct carp_softc *, const char* reason); static void carp_send_ad(void *); static void carp_send_ad_locked(struct carp_softc *); static void carp_addroute(struct carp_softc *); static void carp_ifa_addroute(struct ifaddr *); static void carp_delroute(struct carp_softc *); static void carp_ifa_delroute(struct ifaddr *); static void carp_send_ad_all(void *, int); static void carp_demote_adj(int, char *); static LIST_HEAD(, carp_softc) carp_list; static struct mtx carp_mtx; static struct sx carp_sx; static struct task carp_sendall_task = TASK_INITIALIZER(0, carp_send_ad_all, NULL); static void carp_hmac_prepare(struct carp_softc *sc) { uint8_t version = CARP_VERSION, type = CARP_ADVERTISEMENT; uint8_t vhid = sc->sc_vhid & 0xff; struct ifaddr *ifa; int i, found; #ifdef INET struct in_addr last, cur, in; #endif #ifdef INET6 struct in6_addr last6, cur6, in6; #endif CARP_LOCK_ASSERT(sc); /* Compute ipad from key. */ bzero(sc->sc_pad, sizeof(sc->sc_pad)); bcopy(sc->sc_key, sc->sc_pad, sizeof(sc->sc_key)); for (i = 0; i < sizeof(sc->sc_pad); i++) sc->sc_pad[i] ^= 0x36; /* Precompute first part of inner hash. */ SHA1Init(&sc->sc_sha1); SHA1Update(&sc->sc_sha1, sc->sc_pad, sizeof(sc->sc_pad)); SHA1Update(&sc->sc_sha1, (void *)&version, sizeof(version)); SHA1Update(&sc->sc_sha1, (void *)&type, sizeof(type)); SHA1Update(&sc->sc_sha1, (void *)&vhid, sizeof(vhid)); #ifdef INET cur.s_addr = 0; do { found = 0; last = cur; cur.s_addr = 0xffffffff; CARP_FOREACH_IFA(sc, ifa) { in.s_addr = ifatoia(ifa)->ia_addr.sin_addr.s_addr; if (ifa->ifa_addr->sa_family == AF_INET && ntohl(in.s_addr) > ntohl(last.s_addr) && ntohl(in.s_addr) < ntohl(cur.s_addr)) { cur.s_addr = in.s_addr; found++; } } if (found) SHA1Update(&sc->sc_sha1, (void *)&cur, sizeof(cur)); } while (found); #endif /* INET */ #ifdef INET6 memset(&cur6, 0, sizeof(cur6)); do { found = 0; last6 = cur6; memset(&cur6, 0xff, sizeof(cur6)); CARP_FOREACH_IFA(sc, ifa) { in6 = ifatoia6(ifa)->ia_addr.sin6_addr; if (IN6_IS_SCOPE_EMBED(&in6)) in6.s6_addr16[1] = 0; if (ifa->ifa_addr->sa_family == AF_INET6 && memcmp(&in6, &last6, sizeof(in6)) > 0 && memcmp(&in6, &cur6, sizeof(in6)) < 0) { cur6 = in6; found++; } } if (found) SHA1Update(&sc->sc_sha1, (void *)&cur6, sizeof(cur6)); } while (found); #endif /* INET6 */ /* convert ipad to opad */ for (i = 0; i < sizeof(sc->sc_pad); i++) sc->sc_pad[i] ^= 0x36 ^ 0x5c; } static void carp_hmac_generate(struct carp_softc *sc, uint32_t counter[2], unsigned char md[20]) { SHA1_CTX sha1ctx; CARP_LOCK_ASSERT(sc); /* fetch first half of inner hash */ bcopy(&sc->sc_sha1, &sha1ctx, sizeof(sha1ctx)); SHA1Update(&sha1ctx, (void *)counter, sizeof(sc->sc_counter)); SHA1Final(md, &sha1ctx); /* outer hash */ SHA1Init(&sha1ctx); SHA1Update(&sha1ctx, sc->sc_pad, sizeof(sc->sc_pad)); SHA1Update(&sha1ctx, md, 20); SHA1Final(md, &sha1ctx); } static int carp_hmac_verify(struct carp_softc *sc, uint32_t counter[2], unsigned char md[20]) { unsigned char md2[20]; CARP_LOCK_ASSERT(sc); carp_hmac_generate(sc, counter, md2); return (bcmp(md, md2, sizeof(md2))); } /* * process input packet. * we have rearranged checks order compared to the rfc, * but it seems more efficient this way or not possible otherwise. */ #ifdef INET int carp_input(struct mbuf **mp, int *offp, int proto) { struct mbuf *m = *mp; struct ip *ip = mtod(m, struct ip *); struct carp_header *ch; int iplen, len; iplen = *offp; *mp = NULL; CARPSTATS_INC(carps_ipackets); if (!V_carp_allow) { m_freem(m); return (IPPROTO_DONE); } /* verify that the IP TTL is 255. */ if (ip->ip_ttl != CARP_DFLTTL) { CARPSTATS_INC(carps_badttl); CARP_DEBUG("%s: received ttl %d != 255 on %s\n", __func__, ip->ip_ttl, m->m_pkthdr.rcvif->if_xname); m_freem(m); return (IPPROTO_DONE); } iplen = ip->ip_hl << 2; if (m->m_pkthdr.len < iplen + sizeof(*ch)) { CARPSTATS_INC(carps_badlen); CARP_DEBUG("%s: received len %zd < sizeof(struct carp_header) " "on %s\n", __func__, m->m_len - sizeof(struct ip), m->m_pkthdr.rcvif->if_xname); m_freem(m); return (IPPROTO_DONE); } if (iplen + sizeof(*ch) < m->m_len) { if ((m = m_pullup(m, iplen + sizeof(*ch))) == NULL) { CARPSTATS_INC(carps_hdrops); CARP_DEBUG("%s: pullup failed\n", __func__); return (IPPROTO_DONE); } ip = mtod(m, struct ip *); } ch = (struct carp_header *)((char *)ip + iplen); /* * verify that the received packet length is * equal to the CARP header */ len = iplen + sizeof(*ch); if (len > m->m_pkthdr.len) { CARPSTATS_INC(carps_badlen); CARP_DEBUG("%s: packet too short %d on %s\n", __func__, m->m_pkthdr.len, m->m_pkthdr.rcvif->if_xname); m_freem(m); return (IPPROTO_DONE); } if ((m = m_pullup(m, len)) == NULL) { CARPSTATS_INC(carps_hdrops); return (IPPROTO_DONE); } ip = mtod(m, struct ip *); ch = (struct carp_header *)((char *)ip + iplen); /* verify the CARP checksum */ m->m_data += iplen; if (in_cksum(m, len - iplen)) { CARPSTATS_INC(carps_badsum); CARP_DEBUG("%s: checksum failed on %s\n", __func__, m->m_pkthdr.rcvif->if_xname); m_freem(m); return (IPPROTO_DONE); } m->m_data -= iplen; carp_input_c(m, ch, AF_INET); return (IPPROTO_DONE); } #endif #ifdef INET6 int carp6_input(struct mbuf **mp, int *offp, int proto) { struct mbuf *m = *mp; struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); struct carp_header *ch; u_int len; CARPSTATS_INC(carps_ipackets6); if (!V_carp_allow) { m_freem(m); return (IPPROTO_DONE); } /* check if received on a valid carp interface */ if (m->m_pkthdr.rcvif->if_carp == NULL) { CARPSTATS_INC(carps_badif); CARP_DEBUG("%s: packet received on non-carp interface: %s\n", __func__, m->m_pkthdr.rcvif->if_xname); m_freem(m); return (IPPROTO_DONE); } /* verify that the IP TTL is 255 */ if (ip6->ip6_hlim != CARP_DFLTTL) { CARPSTATS_INC(carps_badttl); CARP_DEBUG("%s: received ttl %d != 255 on %s\n", __func__, ip6->ip6_hlim, m->m_pkthdr.rcvif->if_xname); m_freem(m); return (IPPROTO_DONE); } /* verify that we have a complete carp packet */ len = m->m_len; IP6_EXTHDR_GET(ch, struct carp_header *, m, *offp, sizeof(*ch)); if (ch == NULL) { CARPSTATS_INC(carps_badlen); CARP_DEBUG("%s: packet size %u too small\n", __func__, len); return (IPPROTO_DONE); } /* verify the CARP checksum */ m->m_data += *offp; if (in_cksum(m, sizeof(*ch))) { CARPSTATS_INC(carps_badsum); CARP_DEBUG("%s: checksum failed, on %s\n", __func__, m->m_pkthdr.rcvif->if_xname); m_freem(m); return (IPPROTO_DONE); } m->m_data -= *offp; carp_input_c(m, ch, AF_INET6); return (IPPROTO_DONE); } #endif /* INET6 */ static void carp_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af) { struct ifnet *ifp = m->m_pkthdr.rcvif; struct ifaddr *ifa; struct carp_softc *sc; uint64_t tmp_counter; struct timeval sc_tv, ch_tv; /* verify that the VHID is valid on the receiving interface */ IF_ADDR_RLOCK(ifp); IFNET_FOREACH_IFA(ifp, ifa) if (ifa->ifa_addr->sa_family == af && ifa->ifa_carp->sc_vhid == ch->carp_vhid) { ifa_ref(ifa); break; } IF_ADDR_RUNLOCK(ifp); if (ifa == NULL) { CARPSTATS_INC(carps_badvhid); m_freem(m); return; } /* verify the CARP version. */ if (ch->carp_version != CARP_VERSION) { CARPSTATS_INC(carps_badver); CARP_DEBUG("%s: invalid version %d\n", ifp->if_xname, ch->carp_version); ifa_free(ifa); m_freem(m); return; } sc = ifa->ifa_carp; CARP_LOCK(sc); ifa_free(ifa); if (carp_hmac_verify(sc, ch->carp_counter, ch->carp_md)) { CARPSTATS_INC(carps_badauth); CARP_DEBUG("%s: incorrect hash for VHID %u@%s\n", __func__, sc->sc_vhid, ifp->if_xname); goto out; } tmp_counter = ntohl(ch->carp_counter[0]); tmp_counter = tmp_counter<<32; tmp_counter += ntohl(ch->carp_counter[1]); /* XXX Replay protection goes here */ sc->sc_init_counter = 0; sc->sc_counter = tmp_counter; sc_tv.tv_sec = sc->sc_advbase; sc_tv.tv_usec = DEMOTE_ADVSKEW(sc) * 1000000 / 256; ch_tv.tv_sec = ch->carp_advbase; ch_tv.tv_usec = ch->carp_advskew * 1000000 / 256; switch (sc->sc_state) { case INIT: break; case MASTER: /* * If we receive an advertisement from a master who's going to * be more frequent than us, go into BACKUP state. */ if (timevalcmp(&sc_tv, &ch_tv, >) || timevalcmp(&sc_tv, &ch_tv, ==)) { callout_stop(&sc->sc_ad_tmo); carp_set_state(sc, BACKUP, "more frequent advertisement received"); carp_setrun(sc, 0); carp_delroute(sc); } break; case BACKUP: /* * If we're pre-empting masters who advertise slower than us, * and this one claims to be slower, treat him as down. */ if (V_carp_preempt && timevalcmp(&sc_tv, &ch_tv, <)) { carp_master_down_locked(sc, "preempting a slower master"); break; } /* * If the master is going to advertise at such a low frequency * that he's guaranteed to time out, we'd might as well just * treat him as timed out now. */ sc_tv.tv_sec = sc->sc_advbase * 3; if (timevalcmp(&sc_tv, &ch_tv, <)) { carp_master_down_locked(sc, "master will time out"); break; } /* * Otherwise, we reset the counter and wait for the next * advertisement. */ carp_setrun(sc, af); break; } out: CARP_UNLOCK(sc); m_freem(m); } static int carp_prepare_ad(struct mbuf *m, struct carp_softc *sc, struct carp_header *ch) { struct m_tag *mtag; if (sc->sc_init_counter) { /* this could also be seconds since unix epoch */ sc->sc_counter = arc4random(); sc->sc_counter = sc->sc_counter << 32; sc->sc_counter += arc4random(); } else sc->sc_counter++; ch->carp_counter[0] = htonl((sc->sc_counter>>32)&0xffffffff); ch->carp_counter[1] = htonl(sc->sc_counter&0xffffffff); carp_hmac_generate(sc, ch->carp_counter, ch->carp_md); /* Tag packet for carp_output */ if ((mtag = m_tag_get(PACKET_TAG_CARP, sizeof(struct carp_softc *), M_NOWAIT)) == NULL) { m_freem(m); CARPSTATS_INC(carps_onomem); return (ENOMEM); } bcopy(&sc, mtag + 1, sizeof(sc)); m_tag_prepend(m, mtag); return (0); } /* * To avoid LORs and possible recursions this function shouldn't * be called directly, but scheduled via taskqueue. */ static void carp_send_ad_all(void *ctx __unused, int pending __unused) { struct carp_softc *sc; mtx_lock(&carp_mtx); LIST_FOREACH(sc, &carp_list, sc_next) if (sc->sc_state == MASTER) { CARP_LOCK(sc); CURVNET_SET(sc->sc_carpdev->if_vnet); carp_send_ad_locked(sc); CURVNET_RESTORE(); CARP_UNLOCK(sc); } mtx_unlock(&carp_mtx); } /* Send a periodic advertisement, executed in callout context. */ static void carp_send_ad(void *v) { struct carp_softc *sc = v; CARP_LOCK_ASSERT(sc); CURVNET_SET(sc->sc_carpdev->if_vnet); carp_send_ad_locked(sc); CURVNET_RESTORE(); CARP_UNLOCK(sc); } static void carp_send_ad_error(struct carp_softc *sc, int error) { if (error) { if (sc->sc_sendad_errors < INT_MAX) sc->sc_sendad_errors++; if (sc->sc_sendad_errors == CARP_SENDAD_MAX_ERRORS) { static const char fmt[] = "send error %d on %s"; char msg[sizeof(fmt) + IFNAMSIZ]; sprintf(msg, fmt, error, sc->sc_carpdev->if_xname); carp_demote_adj(V_carp_senderr_adj, msg); } sc->sc_sendad_success = 0; } else { if (sc->sc_sendad_errors >= CARP_SENDAD_MAX_ERRORS && ++sc->sc_sendad_success >= CARP_SENDAD_MIN_SUCCESS) { static const char fmt[] = "send ok on %s"; char msg[sizeof(fmt) + IFNAMSIZ]; sprintf(msg, fmt, sc->sc_carpdev->if_xname); carp_demote_adj(-V_carp_senderr_adj, msg); sc->sc_sendad_errors = 0; } else sc->sc_sendad_errors = 0; } } static void carp_send_ad_locked(struct carp_softc *sc) { struct carp_header ch; struct timeval tv; struct sockaddr sa; struct ifaddr *ifa; struct carp_header *ch_ptr; struct mbuf *m; int len, advskew; CARP_LOCK_ASSERT(sc); advskew = DEMOTE_ADVSKEW(sc); tv.tv_sec = sc->sc_advbase; tv.tv_usec = advskew * 1000000 / 256; ch.carp_version = CARP_VERSION; ch.carp_type = CARP_ADVERTISEMENT; ch.carp_vhid = sc->sc_vhid; ch.carp_advbase = sc->sc_advbase; ch.carp_advskew = advskew; ch.carp_authlen = 7; /* XXX DEFINE */ ch.carp_pad1 = 0; /* must be zero */ ch.carp_cksum = 0; /* XXXGL: OpenBSD picks first ifaddr with needed family. */ #ifdef INET if (sc->sc_naddrs) { struct ip *ip; m = m_gethdr(M_NOWAIT, MT_DATA); if (m == NULL) { CARPSTATS_INC(carps_onomem); goto resched; } len = sizeof(*ip) + sizeof(ch); m->m_pkthdr.len = len; m->m_pkthdr.rcvif = NULL; m->m_len = len; M_ALIGN(m, m->m_len); m->m_flags |= M_MCAST; ip = mtod(m, struct ip *); ip->ip_v = IPVERSION; ip->ip_hl = sizeof(*ip) >> 2; ip->ip_tos = IPTOS_LOWDELAY; ip->ip_len = htons(len); ip->ip_off = htons(IP_DF); ip->ip_ttl = CARP_DFLTTL; ip->ip_p = IPPROTO_CARP; ip->ip_sum = 0; ip_fillid(ip); bzero(&sa, sizeof(sa)); sa.sa_family = AF_INET; ifa = ifaof_ifpforaddr(&sa, sc->sc_carpdev); if (ifa != NULL) { ip->ip_src.s_addr = ifatoia(ifa)->ia_addr.sin_addr.s_addr; ifa_free(ifa); } else ip->ip_src.s_addr = 0; ip->ip_dst.s_addr = htonl(INADDR_CARP_GROUP); ch_ptr = (struct carp_header *)(&ip[1]); bcopy(&ch, ch_ptr, sizeof(ch)); if (carp_prepare_ad(m, sc, ch_ptr)) goto resched; m->m_data += sizeof(*ip); ch_ptr->carp_cksum = in_cksum(m, len - sizeof(*ip)); m->m_data -= sizeof(*ip); CARPSTATS_INC(carps_opackets); carp_send_ad_error(sc, ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_carpdev->if_carp->cif_imo, NULL)); } #endif /* INET */ #ifdef INET6 if (sc->sc_naddrs6) { struct ip6_hdr *ip6; m = m_gethdr(M_NOWAIT, MT_DATA); if (m == NULL) { CARPSTATS_INC(carps_onomem); goto resched; } len = sizeof(*ip6) + sizeof(ch); m->m_pkthdr.len = len; m->m_pkthdr.rcvif = NULL; m->m_len = len; M_ALIGN(m, m->m_len); m->m_flags |= M_MCAST; ip6 = mtod(m, struct ip6_hdr *); bzero(ip6, sizeof(*ip6)); ip6->ip6_vfc |= IPV6_VERSION; ip6->ip6_hlim = CARP_DFLTTL; ip6->ip6_nxt = IPPROTO_CARP; bzero(&sa, sizeof(sa)); /* set the source address */ sa.sa_family = AF_INET6; ifa = ifaof_ifpforaddr(&sa, sc->sc_carpdev); if (ifa != NULL) { bcopy(IFA_IN6(ifa), &ip6->ip6_src, sizeof(struct in6_addr)); ifa_free(ifa); } else /* This should never happen with IPv6. */ bzero(&ip6->ip6_src, sizeof(struct in6_addr)); /* Set the multicast destination. */ ip6->ip6_dst.s6_addr16[0] = htons(0xff02); ip6->ip6_dst.s6_addr8[15] = 0x12; if (in6_setscope(&ip6->ip6_dst, sc->sc_carpdev, NULL) != 0) { m_freem(m); CARP_DEBUG("%s: in6_setscope failed\n", __func__); goto resched; } ch_ptr = (struct carp_header *)(&ip6[1]); bcopy(&ch, ch_ptr, sizeof(ch)); if (carp_prepare_ad(m, sc, ch_ptr)) goto resched; m->m_data += sizeof(*ip6); ch_ptr->carp_cksum = in_cksum(m, len - sizeof(*ip6)); m->m_data -= sizeof(*ip6); CARPSTATS_INC(carps_opackets6); carp_send_ad_error(sc, ip6_output(m, NULL, NULL, 0, &sc->sc_carpdev->if_carp->cif_im6o, NULL, NULL)); } #endif /* INET6 */ resched: callout_reset(&sc->sc_ad_tmo, tvtohz(&tv), carp_send_ad, sc); } static void carp_addroute(struct carp_softc *sc) { struct ifaddr *ifa; CARP_FOREACH_IFA(sc, ifa) carp_ifa_addroute(ifa); } static void carp_ifa_addroute(struct ifaddr *ifa) { switch (ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: in_addprefix(ifatoia(ifa), RTF_UP); ifa_add_loopback_route(ifa, (struct sockaddr *)&ifatoia(ifa)->ia_addr); break; #endif #ifdef INET6 case AF_INET6: ifa_add_loopback_route(ifa, (struct sockaddr *)&ifatoia6(ifa)->ia_addr); nd6_add_ifa_lle(ifatoia6(ifa)); break; #endif } } static void carp_delroute(struct carp_softc *sc) { struct ifaddr *ifa; CARP_FOREACH_IFA(sc, ifa) carp_ifa_delroute(ifa); } static void carp_ifa_delroute(struct ifaddr *ifa) { switch (ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: ifa_del_loopback_route(ifa, (struct sockaddr *)&ifatoia(ifa)->ia_addr); in_scrubprefix(ifatoia(ifa), LLE_STATIC); break; #endif #ifdef INET6 case AF_INET6: ifa_del_loopback_route(ifa, (struct sockaddr *)&ifatoia6(ifa)->ia_addr); nd6_rem_ifa_lle(ifatoia6(ifa), 1); break; #endif } } int carp_master(struct ifaddr *ifa) { struct carp_softc *sc = ifa->ifa_carp; return (sc->sc_state == MASTER); } #ifdef INET /* * Broadcast a gratuitous ARP request containing * the virtual router MAC address for each IP address * associated with the virtual router. */ static void carp_send_arp(struct carp_softc *sc) { struct ifaddr *ifa; + struct in_addr addr; CARP_FOREACH_IFA(sc, ifa) { if (ifa->ifa_addr->sa_family != AF_INET) continue; - arp_announce_addr(sc->sc_carpdev, IFA_IN(ifa), - LLADDR(&sc->sc_addr)); + addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; + arp_announce_ifaddr(sc->sc_carpdev, addr, LLADDR(&sc->sc_addr)); } } int carp_iamatch(struct ifaddr *ifa, uint8_t **enaddr) { struct carp_softc *sc = ifa->ifa_carp; if (sc->sc_state == MASTER) { *enaddr = LLADDR(&sc->sc_addr); return (1); } return (0); } #endif #ifdef INET6 static void carp_send_na(struct carp_softc *sc) { + static struct in6_addr mcast = IN6ADDR_LINKLOCAL_ALLNODES_INIT; struct ifaddr *ifa; + struct in6_addr *in6; CARP_FOREACH_IFA(sc, ifa) { - if (ifa->ifa_addr->sa_family != AF_INET6 || - IFA_ND6_NA_UNSOLICITED_SKIP(ifa)) + if (ifa->ifa_addr->sa_family != AF_INET6) continue; - nd6_na_output_unsolicited_addr(sc->sc_carpdev, IFA_IN6(ifa), - IFA_ND6_NA_BASE_FLAGS(sc->sc_carpdev, ifa)); - DELAY(nd6_na_unsolicited_addr_delay(ifa)); + in6 = IFA_IN6(ifa); + nd6_na_output(sc->sc_carpdev, &mcast, in6, + ND_NA_FLAG_OVERRIDE, 1, NULL); + DELAY(1000); /* XXX */ } } /* * Returns ifa in case it's a carp address and it is MASTER, or if the address * matches and is not a carp address. Returns NULL otherwise. */ struct ifaddr * carp_iamatch6(struct ifnet *ifp, struct in6_addr *taddr) { struct ifaddr *ifa; ifa = NULL; IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; if (!IN6_ARE_ADDR_EQUAL(taddr, IFA_IN6(ifa))) continue; if (ifa->ifa_carp && ifa->ifa_carp->sc_state != MASTER) ifa = NULL; else ifa_ref(ifa); break; } IF_ADDR_RUNLOCK(ifp); return (ifa); } caddr_t carp_macmatch6(struct ifnet *ifp, struct mbuf *m, const struct in6_addr *taddr) { struct ifaddr *ifa; IF_ADDR_RLOCK(ifp); IFNET_FOREACH_IFA(ifp, ifa) if (ifa->ifa_addr->sa_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(taddr, IFA_IN6(ifa))) { struct carp_softc *sc = ifa->ifa_carp; struct m_tag *mtag; IF_ADDR_RUNLOCK(ifp); mtag = m_tag_get(PACKET_TAG_CARP, sizeof(struct carp_softc *), M_NOWAIT); if (mtag == NULL) /* Better a bit than nothing. */ return (LLADDR(&sc->sc_addr)); bcopy(&sc, mtag + 1, sizeof(sc)); m_tag_prepend(m, mtag); return (LLADDR(&sc->sc_addr)); } IF_ADDR_RUNLOCK(ifp); return (NULL); } #endif /* INET6 */ int carp_forus(struct ifnet *ifp, u_char *dhost) { struct carp_softc *sc; uint8_t *ena = dhost; if (ena[0] || ena[1] || ena[2] != 0x5e || ena[3] || ena[4] != 1) return (0); CIF_LOCK(ifp->if_carp); IFNET_FOREACH_CARP(ifp, sc) { CARP_LOCK(sc); if (sc->sc_state == MASTER && !bcmp(dhost, LLADDR(&sc->sc_addr), ETHER_ADDR_LEN)) { CARP_UNLOCK(sc); CIF_UNLOCK(ifp->if_carp); return (1); } CARP_UNLOCK(sc); } CIF_UNLOCK(ifp->if_carp); return (0); } /* Master down timeout event, executed in callout context. */ static void carp_master_down(void *v) { struct carp_softc *sc = v; CARP_LOCK_ASSERT(sc); CURVNET_SET(sc->sc_carpdev->if_vnet); if (sc->sc_state == BACKUP) { carp_master_down_locked(sc, "master timed out"); } CURVNET_RESTORE(); CARP_UNLOCK(sc); } static void carp_master_down_locked(struct carp_softc *sc, const char *reason) { CARP_LOCK_ASSERT(sc); switch (sc->sc_state) { case BACKUP: carp_set_state(sc, MASTER, reason); carp_send_ad_locked(sc); #ifdef INET carp_send_arp(sc); #endif #ifdef INET6 carp_send_na(sc); #endif carp_setrun(sc, 0); carp_addroute(sc); break; case INIT: case MASTER: #ifdef INVARIANTS panic("carp: VHID %u@%s: master_down event in %s state\n", sc->sc_vhid, sc->sc_carpdev->if_xname, sc->sc_state ? "MASTER" : "INIT"); #endif break; } } /* * When in backup state, af indicates whether to reset the master down timer * for v4 or v6. If it's set to zero, reset the ones which are already pending. */ static void carp_setrun(struct carp_softc *sc, sa_family_t af) { struct timeval tv; CARP_LOCK_ASSERT(sc); if ((sc->sc_carpdev->if_flags & IFF_UP) == 0 || sc->sc_carpdev->if_link_state != LINK_STATE_UP || (sc->sc_naddrs == 0 && sc->sc_naddrs6 == 0)) return; switch (sc->sc_state) { case INIT: carp_set_state(sc, BACKUP, "initialization complete"); carp_setrun(sc, 0); break; case BACKUP: callout_stop(&sc->sc_ad_tmo); tv.tv_sec = 3 * sc->sc_advbase; tv.tv_usec = sc->sc_advskew * 1000000 / 256; switch (af) { #ifdef INET case AF_INET: callout_reset(&sc->sc_md_tmo, tvtohz(&tv), carp_master_down, sc); break; #endif #ifdef INET6 case AF_INET6: callout_reset(&sc->sc_md6_tmo, tvtohz(&tv), carp_master_down, sc); break; #endif default: #ifdef INET if (sc->sc_naddrs) callout_reset(&sc->sc_md_tmo, tvtohz(&tv), carp_master_down, sc); #endif #ifdef INET6 if (sc->sc_naddrs6) callout_reset(&sc->sc_md6_tmo, tvtohz(&tv), carp_master_down, sc); #endif break; } break; case MASTER: tv.tv_sec = sc->sc_advbase; tv.tv_usec = sc->sc_advskew * 1000000 / 256; callout_reset(&sc->sc_ad_tmo, tvtohz(&tv), carp_send_ad, sc); break; } } /* * Setup multicast structures. */ static int carp_multicast_setup(struct carp_if *cif, sa_family_t sa) { struct ifnet *ifp = cif->cif_ifp; int error = 0; switch (sa) { #ifdef INET case AF_INET: { struct ip_moptions *imo = &cif->cif_imo; struct in_addr addr; if (imo->imo_membership) return (0); imo->imo_membership = (struct in_multi **)malloc( (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_CARP, M_WAITOK); imo->imo_mfilters = NULL; imo->imo_max_memberships = IP_MIN_MEMBERSHIPS; imo->imo_multicast_vif = -1; addr.s_addr = htonl(INADDR_CARP_GROUP); if ((error = in_joingroup(ifp, &addr, NULL, &imo->imo_membership[0])) != 0) { free(imo->imo_membership, M_CARP); break; } imo->imo_num_memberships++; imo->imo_multicast_ifp = ifp; imo->imo_multicast_ttl = CARP_DFLTTL; imo->imo_multicast_loop = 0; break; } #endif #ifdef INET6 case AF_INET6: { struct ip6_moptions *im6o = &cif->cif_im6o; struct in6_addr in6; struct in6_multi *in6m; if (im6o->im6o_membership) return (0); im6o->im6o_membership = (struct in6_multi **)malloc( (sizeof(struct in6_multi *) * IPV6_MIN_MEMBERSHIPS), M_CARP, M_ZERO | M_WAITOK); im6o->im6o_mfilters = NULL; im6o->im6o_max_memberships = IPV6_MIN_MEMBERSHIPS; im6o->im6o_multicast_hlim = CARP_DFLTTL; im6o->im6o_multicast_ifp = ifp; /* Join IPv6 CARP multicast group. */ bzero(&in6, sizeof(in6)); in6.s6_addr16[0] = htons(0xff02); in6.s6_addr8[15] = 0x12; if ((error = in6_setscope(&in6, ifp, NULL)) != 0) { free(im6o->im6o_membership, M_CARP); break; } in6m = NULL; if ((error = in6_mc_join(ifp, &in6, NULL, &in6m, 0)) != 0) { free(im6o->im6o_membership, M_CARP); break; } im6o->im6o_membership[0] = in6m; im6o->im6o_num_memberships++; /* Join solicited multicast address. */ bzero(&in6, sizeof(in6)); in6.s6_addr16[0] = htons(0xff02); in6.s6_addr32[1] = 0; in6.s6_addr32[2] = htonl(1); in6.s6_addr32[3] = 0; in6.s6_addr8[12] = 0xff; if ((error = in6_setscope(&in6, ifp, NULL)) != 0) { in6_mc_leave(im6o->im6o_membership[0], NULL); free(im6o->im6o_membership, M_CARP); break; } in6m = NULL; if ((error = in6_mc_join(ifp, &in6, NULL, &in6m, 0)) != 0) { in6_mc_leave(im6o->im6o_membership[0], NULL); free(im6o->im6o_membership, M_CARP); break; } im6o->im6o_membership[1] = in6m; im6o->im6o_num_memberships++; break; } #endif } return (error); } /* * Free multicast structures. */ static void carp_multicast_cleanup(struct carp_if *cif, sa_family_t sa) { sx_assert(&carp_sx, SA_XLOCKED); switch (sa) { #ifdef INET case AF_INET: if (cif->cif_naddrs == 0) { struct ip_moptions *imo = &cif->cif_imo; in_leavegroup(imo->imo_membership[0], NULL); KASSERT(imo->imo_mfilters == NULL, ("%s: imo_mfilters != NULL", __func__)); free(imo->imo_membership, M_CARP); imo->imo_membership = NULL; } break; #endif #ifdef INET6 case AF_INET6: if (cif->cif_naddrs6 == 0) { struct ip6_moptions *im6o = &cif->cif_im6o; in6_mc_leave(im6o->im6o_membership[0], NULL); in6_mc_leave(im6o->im6o_membership[1], NULL); KASSERT(im6o->im6o_mfilters == NULL, ("%s: im6o_mfilters != NULL", __func__)); free(im6o->im6o_membership, M_CARP); im6o->im6o_membership = NULL; } break; #endif } } int carp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa) { struct m_tag *mtag; struct carp_softc *sc; if (!sa) return (0); switch (sa->sa_family) { #ifdef INET case AF_INET: break; #endif #ifdef INET6 case AF_INET6: break; #endif default: return (0); } mtag = m_tag_find(m, PACKET_TAG_CARP, NULL); if (mtag == NULL) return (0); bcopy(mtag + 1, &sc, sizeof(sc)); /* Set the source MAC address to the Virtual Router MAC Address. */ switch (ifp->if_type) { case IFT_ETHER: case IFT_BRIDGE: case IFT_L2VLAN: { struct ether_header *eh; eh = mtod(m, struct ether_header *); eh->ether_shost[0] = 0; eh->ether_shost[1] = 0; eh->ether_shost[2] = 0x5e; eh->ether_shost[3] = 0; eh->ether_shost[4] = 1; eh->ether_shost[5] = sc->sc_vhid; } break; case IFT_FDDI: { struct fddi_header *fh; fh = mtod(m, struct fddi_header *); fh->fddi_shost[0] = 0; fh->fddi_shost[1] = 0; fh->fddi_shost[2] = 0x5e; fh->fddi_shost[3] = 0; fh->fddi_shost[4] = 1; fh->fddi_shost[5] = sc->sc_vhid; } break; case IFT_ISO88025: { struct iso88025_header *th; th = mtod(m, struct iso88025_header *); th->iso88025_shost[0] = 3; th->iso88025_shost[1] = 0; th->iso88025_shost[2] = 0x40 >> (sc->sc_vhid - 1); th->iso88025_shost[3] = 0x40000 >> (sc->sc_vhid - 1); th->iso88025_shost[4] = 0; th->iso88025_shost[5] = 0; } break; default: printf("%s: carp is not supported for the %d interface type\n", ifp->if_xname, ifp->if_type); return (EOPNOTSUPP); } return (0); } static struct carp_softc* carp_alloc(struct ifnet *ifp) { struct carp_softc *sc; struct carp_if *cif; if ((cif = ifp->if_carp) == NULL) cif = carp_alloc_if(ifp); sc = malloc(sizeof(*sc), M_CARP, M_WAITOK|M_ZERO); sc->sc_advbase = CARP_DFLTINTV; sc->sc_vhid = -1; /* required setting */ sc->sc_init_counter = 1; sc->sc_state = INIT; sc->sc_ifasiz = sizeof(struct ifaddr *); sc->sc_ifas = malloc(sc->sc_ifasiz, M_CARP, M_WAITOK|M_ZERO); sc->sc_carpdev = ifp; CARP_LOCK_INIT(sc); #ifdef INET callout_init_mtx(&sc->sc_md_tmo, &sc->sc_mtx, CALLOUT_RETURNUNLOCKED); #endif #ifdef INET6 callout_init_mtx(&sc->sc_md6_tmo, &sc->sc_mtx, CALLOUT_RETURNUNLOCKED); #endif callout_init_mtx(&sc->sc_ad_tmo, &sc->sc_mtx, CALLOUT_RETURNUNLOCKED); CIF_LOCK(cif); TAILQ_INSERT_TAIL(&cif->cif_vrs, sc, sc_list); CIF_UNLOCK(cif); mtx_lock(&carp_mtx); LIST_INSERT_HEAD(&carp_list, sc, sc_next); mtx_unlock(&carp_mtx); return (sc); } static void carp_grow_ifas(struct carp_softc *sc) { struct ifaddr **new; new = malloc(sc->sc_ifasiz * 2, M_CARP, M_WAITOK | M_ZERO); CARP_LOCK(sc); bcopy(sc->sc_ifas, new, sc->sc_ifasiz); free(sc->sc_ifas, M_CARP); sc->sc_ifas = new; sc->sc_ifasiz *= 2; CARP_UNLOCK(sc); } static void carp_destroy(struct carp_softc *sc) { struct ifnet *ifp = sc->sc_carpdev; struct carp_if *cif = ifp->if_carp; sx_assert(&carp_sx, SA_XLOCKED); if (sc->sc_suppress) carp_demote_adj(-V_carp_ifdown_adj, "vhid removed"); CARP_UNLOCK(sc); CIF_LOCK(cif); TAILQ_REMOVE(&cif->cif_vrs, sc, sc_list); CIF_UNLOCK(cif); mtx_lock(&carp_mtx); LIST_REMOVE(sc, sc_next); mtx_unlock(&carp_mtx); callout_drain(&sc->sc_ad_tmo); #ifdef INET callout_drain(&sc->sc_md_tmo); #endif #ifdef INET6 callout_drain(&sc->sc_md6_tmo); #endif CARP_LOCK_DESTROY(sc); free(sc->sc_ifas, M_CARP); free(sc, M_CARP); } static struct carp_if* carp_alloc_if(struct ifnet *ifp) { struct carp_if *cif; int error; cif = malloc(sizeof(*cif), M_CARP, M_WAITOK|M_ZERO); if ((error = ifpromisc(ifp, 1)) != 0) printf("%s: ifpromisc(%s) failed: %d\n", __func__, ifp->if_xname, error); else cif->cif_flags |= CIF_PROMISC; CIF_LOCK_INIT(cif); cif->cif_ifp = ifp; TAILQ_INIT(&cif->cif_vrs); IF_ADDR_WLOCK(ifp); ifp->if_carp = cif; if_ref(ifp); IF_ADDR_WUNLOCK(ifp); return (cif); } static void carp_free_if(struct carp_if *cif) { struct ifnet *ifp = cif->cif_ifp; CIF_LOCK_ASSERT(cif); KASSERT(TAILQ_EMPTY(&cif->cif_vrs), ("%s: softc list not empty", __func__)); IF_ADDR_WLOCK(ifp); ifp->if_carp = NULL; IF_ADDR_WUNLOCK(ifp); CIF_LOCK_DESTROY(cif); if (cif->cif_flags & CIF_PROMISC) ifpromisc(ifp, 0); if_rele(ifp); free(cif, M_CARP); } static void carp_carprcp(struct carpreq *carpr, struct carp_softc *sc, int priv) { CARP_LOCK(sc); carpr->carpr_state = sc->sc_state; carpr->carpr_vhid = sc->sc_vhid; carpr->carpr_advbase = sc->sc_advbase; carpr->carpr_advskew = sc->sc_advskew; if (priv) bcopy(sc->sc_key, carpr->carpr_key, sizeof(carpr->carpr_key)); else bzero(carpr->carpr_key, sizeof(carpr->carpr_key)); CARP_UNLOCK(sc); } int carp_ioctl(struct ifreq *ifr, u_long cmd, struct thread *td) { struct carpreq carpr; struct ifnet *ifp; struct carp_softc *sc = NULL; int error = 0, locked = 0; if ((error = copyin(ifr->ifr_data, &carpr, sizeof carpr))) return (error); ifp = ifunit_ref(ifr->ifr_name); if (ifp == NULL) return (ENXIO); switch (ifp->if_type) { case IFT_ETHER: case IFT_L2VLAN: case IFT_BRIDGE: case IFT_FDDI: case IFT_ISO88025: break; default: error = EOPNOTSUPP; goto out; } if ((ifp->if_flags & IFF_MULTICAST) == 0) { error = EADDRNOTAVAIL; goto out; } sx_xlock(&carp_sx); switch (cmd) { case SIOCSVH: if ((error = priv_check(td, PRIV_NETINET_CARP))) break; if (carpr.carpr_vhid <= 0 || carpr.carpr_vhid > CARP_MAXVHID || carpr.carpr_advbase < 0 || carpr.carpr_advskew < 0) { error = EINVAL; break; } if (ifp->if_carp) { CIF_LOCK(ifp->if_carp); IFNET_FOREACH_CARP(ifp, sc) if (sc->sc_vhid == carpr.carpr_vhid) break; CIF_UNLOCK(ifp->if_carp); } if (sc == NULL) { sc = carp_alloc(ifp); CARP_LOCK(sc); sc->sc_vhid = carpr.carpr_vhid; LLADDR(&sc->sc_addr)[0] = 0; LLADDR(&sc->sc_addr)[1] = 0; LLADDR(&sc->sc_addr)[2] = 0x5e; LLADDR(&sc->sc_addr)[3] = 0; LLADDR(&sc->sc_addr)[4] = 1; LLADDR(&sc->sc_addr)[5] = sc->sc_vhid; } else CARP_LOCK(sc); locked = 1; if (carpr.carpr_advbase > 0) { if (carpr.carpr_advbase > 255 || carpr.carpr_advbase < CARP_DFLTINTV) { error = EINVAL; break; } sc->sc_advbase = carpr.carpr_advbase; } if (carpr.carpr_advskew >= 255) { error = EINVAL; break; } sc->sc_advskew = carpr.carpr_advskew; if (carpr.carpr_key[0] != '\0') { bcopy(carpr.carpr_key, sc->sc_key, sizeof(sc->sc_key)); carp_hmac_prepare(sc); } if (sc->sc_state != INIT && carpr.carpr_state != sc->sc_state) { switch (carpr.carpr_state) { case BACKUP: callout_stop(&sc->sc_ad_tmo); carp_set_state(sc, BACKUP, "user requested via ifconfig"); carp_setrun(sc, 0); carp_delroute(sc); break; case MASTER: carp_master_down_locked(sc, "user requested via ifconfig"); break; default: break; } } break; case SIOCGVH: { int priveleged; if (carpr.carpr_vhid < 0 || carpr.carpr_vhid > CARP_MAXVHID) { error = EINVAL; break; } if (carpr.carpr_count < 1) { error = EMSGSIZE; break; } if (ifp->if_carp == NULL) { error = ENOENT; break; } priveleged = (priv_check(td, PRIV_NETINET_CARP) == 0); if (carpr.carpr_vhid != 0) { CIF_LOCK(ifp->if_carp); IFNET_FOREACH_CARP(ifp, sc) if (sc->sc_vhid == carpr.carpr_vhid) break; CIF_UNLOCK(ifp->if_carp); if (sc == NULL) { error = ENOENT; break; } carp_carprcp(&carpr, sc, priveleged); error = copyout(&carpr, ifr->ifr_data, sizeof(carpr)); } else { int i, count; count = 0; CIF_LOCK(ifp->if_carp); IFNET_FOREACH_CARP(ifp, sc) count++; if (count > carpr.carpr_count) { CIF_UNLOCK(ifp->if_carp); error = EMSGSIZE; break; } i = 0; IFNET_FOREACH_CARP(ifp, sc) { carp_carprcp(&carpr, sc, priveleged); carpr.carpr_count = count; error = copyout(&carpr, ifr->ifr_data + (i * sizeof(carpr)), sizeof(carpr)); if (error) { CIF_UNLOCK(ifp->if_carp); break; } i++; } CIF_UNLOCK(ifp->if_carp); } break; } default: error = EINVAL; } sx_xunlock(&carp_sx); out: if (locked) CARP_UNLOCK(sc); if_rele(ifp); return (error); } static int carp_get_vhid(struct ifaddr *ifa) { if (ifa == NULL || ifa->ifa_carp == NULL) return (0); return (ifa->ifa_carp->sc_vhid); } int carp_attach(struct ifaddr *ifa, int vhid) { struct ifnet *ifp = ifa->ifa_ifp; struct carp_if *cif = ifp->if_carp; struct carp_softc *sc; int index, error; KASSERT(ifa->ifa_carp == NULL, ("%s: ifa %p attached", __func__, ifa)); switch (ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: #endif #ifdef INET6 case AF_INET6: #endif break; default: return (EPROTOTYPE); } sx_xlock(&carp_sx); if (ifp->if_carp == NULL) { sx_xunlock(&carp_sx); return (ENOPROTOOPT); } CIF_LOCK(cif); IFNET_FOREACH_CARP(ifp, sc) if (sc->sc_vhid == vhid) break; CIF_UNLOCK(cif); if (sc == NULL) { sx_xunlock(&carp_sx); return (ENOENT); } error = carp_multicast_setup(cif, ifa->ifa_addr->sa_family); if (error) { CIF_FREE(cif); sx_xunlock(&carp_sx); return (error); } index = sc->sc_naddrs + sc->sc_naddrs6 + 1; if (index > sc->sc_ifasiz / sizeof(struct ifaddr *)) carp_grow_ifas(sc); switch (ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: cif->cif_naddrs++; sc->sc_naddrs++; break; #endif #ifdef INET6 case AF_INET6: cif->cif_naddrs6++; sc->sc_naddrs6++; break; #endif } ifa_ref(ifa); CARP_LOCK(sc); sc->sc_ifas[index - 1] = ifa; ifa->ifa_carp = sc; carp_hmac_prepare(sc); carp_sc_state(sc); CARP_UNLOCK(sc); sx_xunlock(&carp_sx); return (0); } void carp_detach(struct ifaddr *ifa) { struct ifnet *ifp = ifa->ifa_ifp; struct carp_if *cif = ifp->if_carp; struct carp_softc *sc = ifa->ifa_carp; int i, index; KASSERT(sc != NULL, ("%s: %p not attached", __func__, ifa)); sx_xlock(&carp_sx); CARP_LOCK(sc); /* Shift array. */ index = sc->sc_naddrs + sc->sc_naddrs6; for (i = 0; i < index; i++) if (sc->sc_ifas[i] == ifa) break; KASSERT(i < index, ("%s: %p no backref", __func__, ifa)); for (; i < index - 1; i++) sc->sc_ifas[i] = sc->sc_ifas[i+1]; sc->sc_ifas[index - 1] = NULL; switch (ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: cif->cif_naddrs--; sc->sc_naddrs--; break; #endif #ifdef INET6 case AF_INET6: cif->cif_naddrs6--; sc->sc_naddrs6--; break; #endif } carp_ifa_delroute(ifa); carp_multicast_cleanup(cif, ifa->ifa_addr->sa_family); ifa->ifa_carp = NULL; ifa_free(ifa); carp_hmac_prepare(sc); carp_sc_state(sc); if (sc->sc_naddrs == 0 && sc->sc_naddrs6 == 0) carp_destroy(sc); else CARP_UNLOCK(sc); CIF_FREE(cif); sx_xunlock(&carp_sx); } static void carp_set_state(struct carp_softc *sc, int state, const char *reason) { CARP_LOCK_ASSERT(sc); if (sc->sc_state != state) { const char *carp_states[] = { CARP_STATES }; char subsys[IFNAMSIZ+5]; snprintf(subsys, IFNAMSIZ+5, "%u@%s", sc->sc_vhid, sc->sc_carpdev->if_xname); CARP_LOG("%s: %s -> %s (%s)\n", subsys, carp_states[sc->sc_state], carp_states[state], reason); sc->sc_state = state; devctl_notify("CARP", subsys, carp_states[state], NULL); } } static void carp_linkstate(struct ifnet *ifp) { struct carp_softc *sc; CIF_LOCK(ifp->if_carp); IFNET_FOREACH_CARP(ifp, sc) { CARP_LOCK(sc); carp_sc_state(sc); CARP_UNLOCK(sc); } CIF_UNLOCK(ifp->if_carp); } static void carp_sc_state(struct carp_softc *sc) { CARP_LOCK_ASSERT(sc); if (sc->sc_carpdev->if_link_state != LINK_STATE_UP || !(sc->sc_carpdev->if_flags & IFF_UP)) { callout_stop(&sc->sc_ad_tmo); #ifdef INET callout_stop(&sc->sc_md_tmo); #endif #ifdef INET6 callout_stop(&sc->sc_md6_tmo); #endif carp_set_state(sc, INIT, "hardware interface down"); carp_setrun(sc, 0); if (!sc->sc_suppress) carp_demote_adj(V_carp_ifdown_adj, "interface down"); sc->sc_suppress = 1; } else { carp_set_state(sc, INIT, "hardware interface up"); carp_setrun(sc, 0); if (sc->sc_suppress) carp_demote_adj(-V_carp_ifdown_adj, "interface up"); sc->sc_suppress = 0; } } static void carp_demote_adj(int adj, char *reason) { atomic_add_int(&V_carp_demotion, adj); CARP_LOG("demoted by %d to %d (%s)\n", adj, V_carp_demotion, reason); taskqueue_enqueue(taskqueue_swi, &carp_sendall_task); } static int carp_demote_adj_sysctl(SYSCTL_HANDLER_ARGS) { int new, error; new = V_carp_demotion; error = sysctl_handle_int(oidp, &new, 0, req); if (error || !req->newptr) return (error); carp_demote_adj(new, "sysctl"); return (0); } #ifdef INET extern struct domain inetdomain; static struct protosw in_carp_protosw = { .pr_type = SOCK_RAW, .pr_domain = &inetdomain, .pr_protocol = IPPROTO_CARP, .pr_flags = PR_ATOMIC|PR_ADDR, .pr_input = carp_input, .pr_output = rip_output, .pr_ctloutput = rip_ctloutput, .pr_usrreqs = &rip_usrreqs }; #endif #ifdef INET6 extern struct domain inet6domain; static struct protosw in6_carp_protosw = { .pr_type = SOCK_RAW, .pr_domain = &inet6domain, .pr_protocol = IPPROTO_CARP, .pr_flags = PR_ATOMIC|PR_ADDR, .pr_input = carp6_input, .pr_output = rip6_output, .pr_ctloutput = rip6_ctloutput, .pr_usrreqs = &rip6_usrreqs }; #endif static void carp_mod_cleanup(void) { #ifdef INET if (proto_reg[CARP_INET] == 0) { (void)ipproto_unregister(IPPROTO_CARP); pf_proto_unregister(PF_INET, IPPROTO_CARP, SOCK_RAW); proto_reg[CARP_INET] = -1; } carp_iamatch_p = NULL; #endif #ifdef INET6 if (proto_reg[CARP_INET6] == 0) { (void)ip6proto_unregister(IPPROTO_CARP); pf_proto_unregister(PF_INET6, IPPROTO_CARP, SOCK_RAW); proto_reg[CARP_INET6] = -1; } carp_iamatch6_p = NULL; carp_macmatch6_p = NULL; #endif carp_ioctl_p = NULL; carp_attach_p = NULL; carp_detach_p = NULL; carp_get_vhid_p = NULL; carp_linkstate_p = NULL; carp_forus_p = NULL; carp_output_p = NULL; carp_demote_adj_p = NULL; carp_master_p = NULL; mtx_unlock(&carp_mtx); taskqueue_drain(taskqueue_swi, &carp_sendall_task); mtx_destroy(&carp_mtx); sx_destroy(&carp_sx); } static int carp_mod_load(void) { int err; mtx_init(&carp_mtx, "carp_mtx", NULL, MTX_DEF); sx_init(&carp_sx, "carp_sx"); LIST_INIT(&carp_list); carp_get_vhid_p = carp_get_vhid; carp_forus_p = carp_forus; carp_output_p = carp_output; carp_linkstate_p = carp_linkstate; carp_ioctl_p = carp_ioctl; carp_attach_p = carp_attach; carp_detach_p = carp_detach; carp_demote_adj_p = carp_demote_adj; carp_master_p = carp_master; #ifdef INET6 carp_iamatch6_p = carp_iamatch6; carp_macmatch6_p = carp_macmatch6; proto_reg[CARP_INET6] = pf_proto_register(PF_INET6, (struct protosw *)&in6_carp_protosw); if (proto_reg[CARP_INET6]) { printf("carp: error %d attaching to PF_INET6\n", proto_reg[CARP_INET6]); carp_mod_cleanup(); return (proto_reg[CARP_INET6]); } err = ip6proto_register(IPPROTO_CARP); if (err) { printf("carp: error %d registering with INET6\n", err); carp_mod_cleanup(); return (err); } #endif #ifdef INET carp_iamatch_p = carp_iamatch; proto_reg[CARP_INET] = pf_proto_register(PF_INET, &in_carp_protosw); if (proto_reg[CARP_INET]) { printf("carp: error %d attaching to PF_INET\n", proto_reg[CARP_INET]); carp_mod_cleanup(); return (proto_reg[CARP_INET]); } err = ipproto_register(IPPROTO_CARP); if (err) { printf("carp: error %d registering with INET\n", err); carp_mod_cleanup(); return (err); } #endif return (0); } static int carp_modevent(module_t mod, int type, void *data) { switch (type) { case MOD_LOAD: return carp_mod_load(); /* NOTREACHED */ case MOD_UNLOAD: mtx_lock(&carp_mtx); if (LIST_EMPTY(&carp_list)) carp_mod_cleanup(); else { mtx_unlock(&carp_mtx); return (EBUSY); } break; default: return (EINVAL); } return (0); } static moduledata_t carp_mod = { "carp", carp_modevent, 0 }; DECLARE_MODULE(carp, carp_mod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY); Index: user/alc/PQ_LAUNDRY/sys/netinet6/in6.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/netinet6/in6.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/netinet6/in6.c (revision 292449) @@ -1,2523 +1,2523 @@ /*- * 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. * * $KAME: in6.c,v 1.259 2002/01/21 11:37:50 keiichi Exp $ */ /*- * Copyright (c) 1982, 1986, 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. * 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. * * @(#)in.c 8.2 (Berkeley) 11/15/93 */ #include __FBSDID("$FreeBSD$"); #include "opt_compat.h" #include "opt_inet.h" #include "opt_inet6.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include VNET_DECLARE(int, icmp6_nodeinfo_oldmcprefix); #define V_icmp6_nodeinfo_oldmcprefix VNET(icmp6_nodeinfo_oldmcprefix) /* - * Definitions of some constant IP6 addresses. + * Definitions of some costant IP6 addresses. */ const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; const struct in6_addr in6addr_nodelocal_allnodes = IN6ADDR_NODELOCAL_ALLNODES_INIT; const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT; const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT; const struct in6_addr in6addr_linklocal_allv2routers = IN6ADDR_LINKLOCAL_ALLV2ROUTERS_INIT; const struct in6_addr in6mask0 = IN6MASK0; const struct in6_addr in6mask32 = IN6MASK32; const struct in6_addr in6mask64 = IN6MASK64; const struct in6_addr in6mask96 = IN6MASK96; const struct in6_addr in6mask128 = IN6MASK128; const struct sockaddr_in6 sa6_any = { sizeof(sa6_any), AF_INET6, 0, 0, IN6ADDR_ANY_INIT, 0 }; static int in6_notify_ifa(struct ifnet *, struct in6_ifaddr *, struct in6_aliasreq *, int); static void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *); static int in6_validate_ifra(struct ifnet *, struct in6_aliasreq *, struct in6_ifaddr *, int); static struct in6_ifaddr *in6_alloc_ifa(struct ifnet *, struct in6_aliasreq *, int flags); static int in6_update_ifa_internal(struct ifnet *, struct in6_aliasreq *, struct in6_ifaddr *, int, int); static int in6_broadcast_ifa(struct ifnet *, struct in6_aliasreq *, struct in6_ifaddr *, int); #define ifa2ia6(ifa) ((struct in6_ifaddr *)(ifa)) #define ia62ifa(ia6) (&((ia6)->ia_ifa)) void in6_newaddrmsg(struct in6_ifaddr *ia, int cmd) { struct sockaddr_dl gateway; struct sockaddr_in6 mask, addr; struct rtentry rt; /* * initialize for rtmsg generation */ bzero(&gateway, sizeof(gateway)); gateway.sdl_len = sizeof(gateway); gateway.sdl_family = AF_LINK; bzero(&rt, sizeof(rt)); rt.rt_gateway = (struct sockaddr *)&gateway; memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask)); memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr)); rt_mask(&rt) = (struct sockaddr *)&mask; rt_key(&rt) = (struct sockaddr *)&addr; rt.rt_flags = RTF_HOST | RTF_STATIC; if (cmd == RTM_ADD) rt.rt_flags |= RTF_UP; /* Announce arrival of local address to all FIBs. */ rt_newaddrmsg(cmd, &ia->ia_ifa, 0, &rt); } int in6_mask2len(struct in6_addr *mask, u_char *lim0) { int x = 0, y; u_char *lim = lim0, *p; /* ignore the scope_id part */ if (lim0 == NULL || lim0 - (u_char *)mask > sizeof(*mask)) lim = (u_char *)mask + sizeof(*mask); for (p = (u_char *)mask; p < lim; x++, p++) { if (*p != 0xff) break; } y = 0; if (p < lim) { for (y = 0; y < 8; y++) { if ((*p & (0x80 >> y)) == 0) break; } } /* * when the limit pointer is given, do a stricter check on the * remaining bits. */ if (p < lim) { if (y != 0 && (*p & (0x00ff >> y)) != 0) return (-1); for (p = p + 1; p < lim; p++) if (*p != 0) return (-1); } return x * 8 + y; } #ifdef COMPAT_FREEBSD32 struct in6_ndifreq32 { char ifname[IFNAMSIZ]; uint32_t ifindex; }; #define SIOCGDEFIFACE32_IN6 _IOWR('i', 86, struct in6_ndifreq32) #endif int in6_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td) { struct in6_ifreq *ifr = (struct in6_ifreq *)data; struct in6_ifaddr *ia = NULL; struct in6_aliasreq *ifra = (struct in6_aliasreq *)data; struct sockaddr_in6 *sa6; int carp_attached = 0; int error; u_long ocmd = cmd; /* * Compat to make pre-10.x ifconfig(8) operable. */ if (cmd == OSIOCAIFADDR_IN6) cmd = SIOCAIFADDR_IN6; switch (cmd) { case SIOCGETSGCNT_IN6: case SIOCGETMIFCNT_IN6: /* * XXX mrt_ioctl has a 3rd, unused, FIB argument in route.c. * We cannot see how that would be needed, so do not adjust the * KPI blindly; more likely should clean up the IPv4 variant. */ return (mrt6_ioctl ? mrt6_ioctl(cmd, data) : EOPNOTSUPP); } switch (cmd) { case SIOCAADDRCTL_POLICY: case SIOCDADDRCTL_POLICY: if (td != NULL) { error = priv_check(td, PRIV_NETINET_ADDRCTRL6); if (error) return (error); } return (in6_src_ioctl(cmd, data)); } if (ifp == NULL) return (EOPNOTSUPP); switch (cmd) { case SIOCSNDFLUSH_IN6: case SIOCSPFXFLUSH_IN6: case SIOCSRTRFLUSH_IN6: case SIOCSDEFIFACE_IN6: case SIOCSIFINFO_FLAGS: case SIOCSIFINFO_IN6: if (td != NULL) { error = priv_check(td, PRIV_NETINET_ND6); if (error) return (error); } /* FALLTHROUGH */ case OSIOCGIFINFO_IN6: case SIOCGIFINFO_IN6: case SIOCGNBRINFO_IN6: case SIOCGDEFIFACE_IN6: return (nd6_ioctl(cmd, data, ifp)); #ifdef COMPAT_FREEBSD32 case SIOCGDEFIFACE32_IN6: { struct in6_ndifreq ndif; struct in6_ndifreq32 *ndif32; error = nd6_ioctl(SIOCGDEFIFACE_IN6, (caddr_t)&ndif, ifp); if (error) return (error); ndif32 = (struct in6_ndifreq32 *)data; ndif32->ifindex = ndif.ifindex; return (0); } #endif } switch (cmd) { case SIOCSIFPREFIX_IN6: case SIOCDIFPREFIX_IN6: case SIOCAIFPREFIX_IN6: case SIOCCIFPREFIX_IN6: case SIOCSGIFPREFIX_IN6: case SIOCGIFPREFIX_IN6: log(LOG_NOTICE, "prefix ioctls are now invalidated. " "please use ifconfig.\n"); return (EOPNOTSUPP); } switch (cmd) { case SIOCSSCOPE6: if (td != NULL) { error = priv_check(td, PRIV_NETINET_SCOPE6); if (error) return (error); } /* FALLTHROUGH */ case SIOCGSCOPE6: case SIOCGSCOPE6DEF: return (scope6_ioctl(cmd, data, ifp)); } /* * Find address for this interface, if it exists. * * In netinet code, we have checked ifra_addr in SIOCSIF*ADDR operation * only, and used the first interface address as the target of other * operations (without checking ifra_addr). This was because netinet * code/API assumed at most 1 interface address per interface. * Since IPv6 allows a node to assign multiple addresses * on a single interface, we almost always look and check the * presence of ifra_addr, and reject invalid ones here. * It also decreases duplicated code among SIOC*_IN6 operations. */ switch (cmd) { case SIOCAIFADDR_IN6: case SIOCSIFPHYADDR_IN6: sa6 = &ifra->ifra_addr; break; case SIOCSIFADDR_IN6: case SIOCGIFADDR_IN6: case SIOCSIFDSTADDR_IN6: case SIOCSIFNETMASK_IN6: case SIOCGIFDSTADDR_IN6: case SIOCGIFNETMASK_IN6: case SIOCDIFADDR_IN6: case SIOCGIFPSRCADDR_IN6: case SIOCGIFPDSTADDR_IN6: case SIOCGIFAFLAG_IN6: case SIOCSNDFLUSH_IN6: case SIOCSPFXFLUSH_IN6: case SIOCSRTRFLUSH_IN6: case SIOCGIFALIFETIME_IN6: case SIOCSIFALIFETIME_IN6: case SIOCGIFSTAT_IN6: case SIOCGIFSTAT_ICMP6: sa6 = &ifr->ifr_addr; break; case SIOCSIFADDR: case SIOCSIFBRDADDR: case SIOCSIFDSTADDR: case SIOCSIFNETMASK: /* * Although we should pass any non-INET6 ioctl requests * down to driver, we filter some legacy INET requests. * Drivers trust SIOCSIFADDR et al to come from an already * privileged layer, and do not perform any credentials * checks or input validation. */ return (EINVAL); default: sa6 = NULL; break; } if (sa6 && sa6->sin6_family == AF_INET6) { if (sa6->sin6_scope_id != 0) error = sa6_embedscope(sa6, 0); else error = in6_setscope(&sa6->sin6_addr, ifp, NULL); if (error != 0) return (error); if (td != NULL && (error = prison_check_ip6(td->td_ucred, &sa6->sin6_addr)) != 0) return (error); ia = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr); } else ia = NULL; switch (cmd) { case SIOCSIFADDR_IN6: case SIOCSIFDSTADDR_IN6: case SIOCSIFNETMASK_IN6: /* * Since IPv6 allows a node to assign multiple addresses * on a single interface, SIOCSIFxxx ioctls are deprecated. */ /* we decided to obsolete this command (20000704) */ error = EINVAL; goto out; case SIOCDIFADDR_IN6: /* * for IPv4, we look for existing in_ifaddr here to allow * "ifconfig if0 delete" to remove the first IPv4 address on * the interface. For IPv6, as the spec allows multiple * interface address from the day one, we consider "remove the * first one" semantics to be not preferable. */ if (ia == NULL) { error = EADDRNOTAVAIL; goto out; } /* FALLTHROUGH */ case SIOCAIFADDR_IN6: /* * We always require users to specify a valid IPv6 address for * the corresponding operation. */ if (ifra->ifra_addr.sin6_family != AF_INET6 || ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6)) { error = EAFNOSUPPORT; goto out; } if (td != NULL) { error = priv_check(td, (cmd == SIOCDIFADDR_IN6) ? PRIV_NET_DELIFADDR : PRIV_NET_ADDIFADDR); if (error) goto out; } /* FALLTHROUGH */ case SIOCGIFSTAT_IN6: case SIOCGIFSTAT_ICMP6: if (ifp->if_afdata[AF_INET6] == NULL) { error = EPFNOSUPPORT; goto out; } break; case SIOCGIFADDR_IN6: /* This interface is basically deprecated. use SIOCGIFCONF. */ /* FALLTHROUGH */ case SIOCGIFAFLAG_IN6: case SIOCGIFNETMASK_IN6: case SIOCGIFDSTADDR_IN6: case SIOCGIFALIFETIME_IN6: /* must think again about its semantics */ if (ia == NULL) { error = EADDRNOTAVAIL; goto out; } break; case SIOCSIFALIFETIME_IN6: { struct in6_addrlifetime *lt; if (td != NULL) { error = priv_check(td, PRIV_NETINET_ALIFETIME6); if (error) goto out; } if (ia == NULL) { error = EADDRNOTAVAIL; goto out; } /* sanity for overflow - beware unsigned */ lt = &ifr->ifr_ifru.ifru_lifetime; if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME && lt->ia6t_vltime + time_uptime < time_uptime) { error = EINVAL; goto out; } if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME && lt->ia6t_pltime + time_uptime < time_uptime) { error = EINVAL; goto out; } break; } } switch (cmd) { case SIOCGIFADDR_IN6: ifr->ifr_addr = ia->ia_addr; if ((error = sa6_recoverscope(&ifr->ifr_addr)) != 0) goto out; break; case SIOCGIFDSTADDR_IN6: if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { error = EINVAL; goto out; } /* * XXX: should we check if ifa_dstaddr is NULL and return * an error? */ ifr->ifr_dstaddr = ia->ia_dstaddr; if ((error = sa6_recoverscope(&ifr->ifr_dstaddr)) != 0) goto out; break; case SIOCGIFNETMASK_IN6: ifr->ifr_addr = ia->ia_prefixmask; break; case SIOCGIFAFLAG_IN6: ifr->ifr_ifru.ifru_flags6 = ia->ia6_flags; break; case SIOCGIFSTAT_IN6: COUNTER_ARRAY_COPY(((struct in6_ifextra *) ifp->if_afdata[AF_INET6])->in6_ifstat, &ifr->ifr_ifru.ifru_stat, sizeof(struct in6_ifstat) / sizeof(uint64_t)); break; case SIOCGIFSTAT_ICMP6: COUNTER_ARRAY_COPY(((struct in6_ifextra *) ifp->if_afdata[AF_INET6])->icmp6_ifstat, &ifr->ifr_ifru.ifru_icmp6stat, sizeof(struct icmp6_ifstat) / sizeof(uint64_t)); break; case SIOCGIFALIFETIME_IN6: ifr->ifr_ifru.ifru_lifetime = ia->ia6_lifetime; if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) { time_t maxexpire; struct in6_addrlifetime *retlt = &ifr->ifr_ifru.ifru_lifetime; /* * XXX: adjust expiration time assuming time_t is * signed. */ maxexpire = (-1) & ~((time_t)1 << ((sizeof(maxexpire) * 8) - 1)); if (ia->ia6_lifetime.ia6t_vltime < maxexpire - ia->ia6_updatetime) { retlt->ia6t_expire = ia->ia6_updatetime + ia->ia6_lifetime.ia6t_vltime; } else retlt->ia6t_expire = maxexpire; } if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) { time_t maxexpire; struct in6_addrlifetime *retlt = &ifr->ifr_ifru.ifru_lifetime; /* * XXX: adjust expiration time assuming time_t is * signed. */ maxexpire = (-1) & ~((time_t)1 << ((sizeof(maxexpire) * 8) - 1)); if (ia->ia6_lifetime.ia6t_pltime < maxexpire - ia->ia6_updatetime) { retlt->ia6t_preferred = ia->ia6_updatetime + ia->ia6_lifetime.ia6t_pltime; } else retlt->ia6t_preferred = maxexpire; } break; case SIOCSIFALIFETIME_IN6: ia->ia6_lifetime = ifr->ifr_ifru.ifru_lifetime; /* for sanity */ if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) { ia->ia6_lifetime.ia6t_expire = time_uptime + ia->ia6_lifetime.ia6t_vltime; } else ia->ia6_lifetime.ia6t_expire = 0; if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) { ia->ia6_lifetime.ia6t_preferred = time_uptime + ia->ia6_lifetime.ia6t_pltime; } else ia->ia6_lifetime.ia6t_preferred = 0; break; case SIOCAIFADDR_IN6: { struct nd_prefixctl pr0; struct nd_prefix *pr; /* * first, make or update the interface address structure, * and link it to the list. */ if ((error = in6_update_ifa(ifp, ifra, ia, 0)) != 0) goto out; if (ia != NULL) ifa_free(&ia->ia_ifa); if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr)) == NULL) { /* * this can happen when the user specify the 0 valid * lifetime. */ break; } if (cmd == ocmd && ifra->ifra_vhid > 0) { if (carp_attach_p != NULL) error = (*carp_attach_p)(&ia->ia_ifa, ifra->ifra_vhid); else error = EPROTONOSUPPORT; if (error) goto out; else carp_attached = 1; } /* * then, make the prefix on-link on the interface. * XXX: we'd rather create the prefix before the address, but * we need at least one address to install the corresponding * interface route, so we configure the address first. */ /* * convert mask to prefix length (prefixmask has already * been validated in in6_update_ifa(). */ bzero(&pr0, sizeof(pr0)); pr0.ndpr_ifp = ifp; pr0.ndpr_plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr, NULL); if (pr0.ndpr_plen == 128) { /* we don't need to install a host route. */ goto aifaddr_out; } pr0.ndpr_prefix = ifra->ifra_addr; /* apply the mask for safety. */ IN6_MASK_ADDR(&pr0.ndpr_prefix.sin6_addr, &ifra->ifra_prefixmask.sin6_addr); /* * XXX: since we don't have an API to set prefix (not address) * lifetimes, we just use the same lifetimes as addresses. * The (temporarily) installed lifetimes can be overridden by * later advertised RAs (when accept_rtadv is non 0), which is * an intended behavior. */ pr0.ndpr_raf_onlink = 1; /* should be configurable? */ pr0.ndpr_raf_auto = ((ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0); pr0.ndpr_vltime = ifra->ifra_lifetime.ia6t_vltime; pr0.ndpr_pltime = ifra->ifra_lifetime.ia6t_pltime; /* add the prefix if not yet. */ if ((pr = nd6_prefix_lookup(&pr0)) == NULL) { /* * nd6_prelist_add will install the corresponding * interface route. */ if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0) { if (carp_attached) (*carp_detach_p)(&ia->ia_ifa); goto out; } if (pr == NULL) { if (carp_attached) (*carp_detach_p)(&ia->ia_ifa); log(LOG_ERR, "nd6_prelist_add succeeded but " "no prefix\n"); error = EINVAL; goto out; } } /* relate the address to the prefix */ if (ia->ia6_ndpr == NULL) { ia->ia6_ndpr = pr; pr->ndpr_refcnt++; /* * If this is the first autoconf address from the * prefix, create a temporary address as well * (when required). */ if ((ia->ia6_flags & IN6_IFF_AUTOCONF) && V_ip6_use_tempaddr && pr->ndpr_refcnt == 1) { int e; if ((e = in6_tmpifadd(ia, 1, 0)) != 0) { log(LOG_NOTICE, "in6_control: failed " "to create a temporary address, " "errno=%d\n", e); } } } /* * this might affect the status of autoconfigured addresses, * that is, this address might make other addresses detached. */ pfxlist_onlink_check(); aifaddr_out: if (error != 0 || ia == NULL) break; /* * Try to clear the flag when a new IPv6 address is added * onto an IFDISABLED interface and it succeeds. */ if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) { struct in6_ndireq nd; memset(&nd, 0, sizeof(nd)); nd.ndi.flags = ND_IFINFO(ifp)->flags; nd.ndi.flags &= ~ND6_IFF_IFDISABLED; if (nd6_ioctl(SIOCSIFINFO_FLAGS, (caddr_t)&nd, ifp) < 0) log(LOG_NOTICE, "SIOCAIFADDR_IN6: " "SIOCSIFINFO_FLAGS for -ifdisabled " "failed."); /* * Ignore failure of clearing the flag intentionally. * The failure means address duplication was detected. */ } EVENTHANDLER_INVOKE(ifaddr_event, ifp); break; } case SIOCDIFADDR_IN6: { struct nd_prefix *pr; /* * If the address being deleted is the only one that owns * the corresponding prefix, expire the prefix as well. * XXX: theoretically, we don't have to worry about such * relationship, since we separate the address management * and the prefix management. We do this, however, to provide * as much backward compatibility as possible in terms of * the ioctl operation. * Note that in6_purgeaddr() will decrement ndpr_refcnt. */ pr = ia->ia6_ndpr; in6_purgeaddr(&ia->ia_ifa); if (pr && pr->ndpr_refcnt == 0) prelist_remove(pr); EVENTHANDLER_INVOKE(ifaddr_event, ifp); break; } default: if (ifp->if_ioctl == NULL) { error = EOPNOTSUPP; goto out; } error = (*ifp->if_ioctl)(ifp, cmd, data); goto out; } error = 0; out: if (ia != NULL) ifa_free(&ia->ia_ifa); return (error); } /* * Join necessary multicast groups. Factored out from in6_update_ifa(). * This entire work should only be done once, for the default FIB. */ static int in6_update_ifa_join_mc(struct ifnet *ifp, struct in6_aliasreq *ifra, struct in6_ifaddr *ia, int flags, struct in6_multi **in6m_sol) { char ip6buf[INET6_ADDRSTRLEN]; struct in6_addr mltaddr; struct in6_multi_mship *imm; int delay, error; KASSERT(in6m_sol != NULL, ("%s: in6m_sol is NULL", __func__)); /* Join solicited multicast addr for new host id. */ bzero(&mltaddr, sizeof(struct in6_addr)); mltaddr.s6_addr32[0] = IPV6_ADDR_INT32_MLL; mltaddr.s6_addr32[2] = htonl(1); mltaddr.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3]; mltaddr.s6_addr8[12] = 0xff; if ((error = in6_setscope(&mltaddr, ifp, NULL)) != 0) { /* XXX: should not happen */ log(LOG_ERR, "%s: in6_setscope failed\n", __func__); goto cleanup; } delay = error = 0; if ((flags & IN6_IFAUPDATE_DADDELAY)) { /* * We need a random delay for DAD on the address being * configured. It also means delaying transmission of the * corresponding MLD report to avoid report collision. * [RFC 4861, Section 6.3.7] */ delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz); } imm = in6_joingroup(ifp, &mltaddr, &error, delay); if (imm == NULL) { nd6log((LOG_WARNING, "%s: in6_joingroup failed for %s on %s " "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &mltaddr), if_name(ifp), error)); goto cleanup; } LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); *in6m_sol = imm->i6mm_maddr; /* * Join link-local all-nodes address. */ mltaddr = in6addr_linklocal_allnodes; if ((error = in6_setscope(&mltaddr, ifp, NULL)) != 0) goto cleanup; /* XXX: should not fail */ imm = in6_joingroup(ifp, &mltaddr, &error, 0); if (imm == NULL) { nd6log((LOG_WARNING, "%s: in6_joingroup failed for %s on %s " "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &mltaddr), if_name(ifp), error)); goto cleanup; } LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); /* * Join node information group address. */ delay = 0; if ((flags & IN6_IFAUPDATE_DADDELAY)) { /* * The spec does not say anything about delay for this group, * but the same logic should apply. */ delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz); } if (in6_nigroup(ifp, NULL, -1, &mltaddr) == 0) { /* XXX jinmei */ imm = in6_joingroup(ifp, &mltaddr, &error, delay); if (imm == NULL) nd6log((LOG_WARNING, "%s: in6_joingroup failed for %s on %s " "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &mltaddr), if_name(ifp), error)); /* XXX not very fatal, go on... */ else LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); } if (V_icmp6_nodeinfo_oldmcprefix && in6_nigroup_oldmcprefix(ifp, NULL, -1, &mltaddr) == 0) { imm = in6_joingroup(ifp, &mltaddr, &error, delay); if (imm == NULL) nd6log((LOG_WARNING, "%s: in6_joingroup failed for %s on %s " "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &mltaddr), if_name(ifp), error)); /* XXX not very fatal, go on... */ else LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); } /* * Join interface-local all-nodes address. * (ff01::1%ifN, and ff01::%ifN/32) */ mltaddr = in6addr_nodelocal_allnodes; if ((error = in6_setscope(&mltaddr, ifp, NULL)) != 0) goto cleanup; /* XXX: should not fail */ imm = in6_joingroup(ifp, &mltaddr, &error, 0); if (imm == NULL) { nd6log((LOG_WARNING, "%s: in6_joingroup failed for %s on %s " "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, &mltaddr), if_name(ifp), error)); goto cleanup; } LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); cleanup: return (error); } /* * Update parameters of an IPv6 interface address. * If necessary, a new entry is created and linked into address chains. * This function is separated from in6_control(). */ int in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra, struct in6_ifaddr *ia, int flags) { int error, hostIsNew = 0; if ((error = in6_validate_ifra(ifp, ifra, ia, flags)) != 0) return (error); if (ia == NULL) { hostIsNew = 1; if ((ia = in6_alloc_ifa(ifp, ifra, flags)) == NULL) return (ENOBUFS); } error = in6_update_ifa_internal(ifp, ifra, ia, hostIsNew, flags); if (error != 0) { if (hostIsNew != 0) { in6_unlink_ifa(ia, ifp); ifa_free(&ia->ia_ifa); } return (error); } if (hostIsNew) error = in6_broadcast_ifa(ifp, ifra, ia, flags); return (error); } /* * Fill in basic IPv6 address request info. */ void in6_prepare_ifra(struct in6_aliasreq *ifra, const struct in6_addr *addr, const struct in6_addr *mask) { memset(ifra, 0, sizeof(struct in6_aliasreq)); ifra->ifra_addr.sin6_family = AF_INET6; ifra->ifra_addr.sin6_len = sizeof(struct sockaddr_in6); if (addr != NULL) ifra->ifra_addr.sin6_addr = *addr; ifra->ifra_prefixmask.sin6_family = AF_INET6; ifra->ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6); if (mask != NULL) ifra->ifra_prefixmask.sin6_addr = *mask; } static int in6_validate_ifra(struct ifnet *ifp, struct in6_aliasreq *ifra, struct in6_ifaddr *ia, int flags) { int plen = -1; struct sockaddr_in6 dst6; struct in6_addrlifetime *lt; char ip6buf[INET6_ADDRSTRLEN]; /* Validate parameters */ if (ifp == NULL || ifra == NULL) /* this maybe redundant */ return (EINVAL); /* * The destination address for a p2p link must have a family * of AF_UNSPEC or AF_INET6. */ if ((ifp->if_flags & IFF_POINTOPOINT) != 0 && ifra->ifra_dstaddr.sin6_family != AF_INET6 && ifra->ifra_dstaddr.sin6_family != AF_UNSPEC) return (EAFNOSUPPORT); /* * Validate address */ if (ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6) || ifra->ifra_addr.sin6_family != AF_INET6) return (EINVAL); /* * validate ifra_prefixmask. don't check sin6_family, netmask * does not carry fields other than sin6_len. */ if (ifra->ifra_prefixmask.sin6_len > sizeof(struct sockaddr_in6)) return (EINVAL); /* * Because the IPv6 address architecture is classless, we require * users to specify a (non 0) prefix length (mask) for a new address. * We also require the prefix (when specified) mask is valid, and thus * reject a non-consecutive mask. */ if (ia == NULL && ifra->ifra_prefixmask.sin6_len == 0) return (EINVAL); if (ifra->ifra_prefixmask.sin6_len != 0) { plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr, (u_char *)&ifra->ifra_prefixmask + ifra->ifra_prefixmask.sin6_len); if (plen <= 0) return (EINVAL); } else { /* * In this case, ia must not be NULL. We just use its prefix * length. */ plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); } /* * If the destination address on a p2p interface is specified, * and the address is a scoped one, validate/set the scope * zone identifier. */ dst6 = ifra->ifra_dstaddr; if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) != 0 && (dst6.sin6_family == AF_INET6)) { struct in6_addr in6_tmp; u_int32_t zoneid; in6_tmp = dst6.sin6_addr; if (in6_setscope(&in6_tmp, ifp, &zoneid)) return (EINVAL); /* XXX: should be impossible */ if (dst6.sin6_scope_id != 0) { if (dst6.sin6_scope_id != zoneid) return (EINVAL); } else /* user omit to specify the ID. */ dst6.sin6_scope_id = zoneid; /* convert into the internal form */ if (sa6_embedscope(&dst6, 0)) return (EINVAL); /* XXX: should be impossible */ } /* Modify original ifra_dstaddr to reflect changes */ ifra->ifra_dstaddr = dst6; /* * The destination address can be specified only for a p2p or a * loopback interface. If specified, the corresponding prefix length * must be 128. */ if (ifra->ifra_dstaddr.sin6_family == AF_INET6) { if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) == 0) { /* XXX: noisy message */ nd6log((LOG_INFO, "in6_update_ifa: a destination can " "be specified for a p2p or a loopback IF only\n")); return (EINVAL); } if (plen != 128) { nd6log((LOG_INFO, "in6_update_ifa: prefixlen should " "be 128 when dstaddr is specified\n")); return (EINVAL); } } /* lifetime consistency check */ lt = &ifra->ifra_lifetime; if (lt->ia6t_pltime > lt->ia6t_vltime) return (EINVAL); if (lt->ia6t_vltime == 0) { /* * the following log might be noisy, but this is a typical * configuration mistake or a tool's bug. */ nd6log((LOG_INFO, "in6_update_ifa: valid lifetime is 0 for %s\n", ip6_sprintf(ip6buf, &ifra->ifra_addr.sin6_addr))); if (ia == NULL) return (0); /* there's nothing to do */ } /* Check prefix mask */ if (ia != NULL && ifra->ifra_prefixmask.sin6_len != 0) { /* * We prohibit changing the prefix length of an existing * address, because * + such an operation should be rare in IPv6, and * + the operation would confuse prefix management. */ if (ia->ia_prefixmask.sin6_len != 0 && in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL) != plen) { nd6log((LOG_INFO, "in6_validate_ifa: the prefix length " "of an existing %s address should not be changed\n", ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr))); return (EINVAL); } } return (0); } /* * Allocate a new ifaddr and link it into chains. */ static struct in6_ifaddr * in6_alloc_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra, int flags) { struct in6_ifaddr *ia; /* * When in6_alloc_ifa() is called in a process of a received * RA, it is called under an interrupt context. So, we should * call malloc with M_NOWAIT. */ ia = (struct in6_ifaddr *)ifa_alloc(sizeof(*ia), M_NOWAIT); if (ia == NULL) return (NULL); LIST_INIT(&ia->ia6_memberships); /* Initialize the address and masks, and put time stamp */ ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; ia->ia_addr.sin6_family = AF_INET6; ia->ia_addr.sin6_len = sizeof(ia->ia_addr); /* XXX: Can we assign ,sin6_addr and skip the rest? */ ia->ia_addr = ifra->ifra_addr; ia->ia6_createtime = time_uptime; if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) != 0) { /* * Some functions expect that ifa_dstaddr is not * NULL for p2p interfaces. */ ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr; } else { ia->ia_ifa.ifa_dstaddr = NULL; } /* set prefix mask if any */ ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask; if (ifra->ifra_prefixmask.sin6_len != 0) { ia->ia_prefixmask.sin6_family = AF_INET6; ia->ia_prefixmask.sin6_len = ifra->ifra_prefixmask.sin6_len; ia->ia_prefixmask.sin6_addr = ifra->ifra_prefixmask.sin6_addr; } ia->ia_ifp = ifp; ifa_ref(&ia->ia_ifa); /* if_addrhead */ IF_ADDR_WLOCK(ifp); TAILQ_INSERT_TAIL(&ifp->if_addrhead, &ia->ia_ifa, ifa_link); IF_ADDR_WUNLOCK(ifp); ifa_ref(&ia->ia_ifa); /* in6_ifaddrhead */ IN6_IFADDR_WLOCK(); TAILQ_INSERT_TAIL(&V_in6_ifaddrhead, ia, ia_link); LIST_INSERT_HEAD(IN6ADDR_HASH(&ia->ia_addr.sin6_addr), ia, ia6_hash); IN6_IFADDR_WUNLOCK(); return (ia); } /* * Update/configure interface address parameters: * * 1) Update lifetime * 2) Update interface metric ad flags * 3) Notify other subsystems */ static int in6_update_ifa_internal(struct ifnet *ifp, struct in6_aliasreq *ifra, struct in6_ifaddr *ia, int hostIsNew, int flags) { int error; /* update timestamp */ ia->ia6_updatetime = time_uptime; /* * Set lifetimes. We do not refer to ia6t_expire and ia6t_preferred * to see if the address is deprecated or invalidated, but initialize * these members for applications. */ ia->ia6_lifetime = ifra->ifra_lifetime; if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) { ia->ia6_lifetime.ia6t_expire = time_uptime + ia->ia6_lifetime.ia6t_vltime; } else ia->ia6_lifetime.ia6t_expire = 0; if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) { ia->ia6_lifetime.ia6t_preferred = time_uptime + ia->ia6_lifetime.ia6t_pltime; } else ia->ia6_lifetime.ia6t_preferred = 0; /* * backward compatibility - if IN6_IFF_DEPRECATED is set from the * userland, make it deprecated. */ if ((ifra->ifra_flags & IN6_IFF_DEPRECATED) != 0) { ia->ia6_lifetime.ia6t_pltime = 0; ia->ia6_lifetime.ia6t_preferred = time_uptime; } /* * configure address flags. */ ia->ia6_flags = ifra->ifra_flags; /* * Make the address tentative before joining multicast addresses, * so that corresponding MLD responses would not have a tentative * source address. */ ia->ia6_flags &= ~IN6_IFF_DUPLICATED; /* safety */ /* * DAD should be performed for an new address or addresses on * an interface with ND6_IFF_IFDISABLED. */ if (in6if_do_dad(ifp) && (hostIsNew || (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED))) ia->ia6_flags |= IN6_IFF_TENTATIVE; /* notify other subsystems */ error = in6_notify_ifa(ifp, ia, ifra, hostIsNew); return (error); } /* * Do link-level ifa job: * 1) Add lle entry for added address * 2) Notifies routing socket users about new address * 3) join appropriate multicast group * 4) start DAD if enabled */ static int in6_broadcast_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra, struct in6_ifaddr *ia, int flags) { struct in6_multi *in6m_sol; int error = 0; /* Add local address to lltable, if necessary (ex. on p2p link). */ if ((error = nd6_add_ifa_lle(ia)) != 0) { in6_purgeaddr(&ia->ia_ifa); ifa_free(&ia->ia_ifa); return (error); } /* Join necessary multicast groups. */ in6m_sol = NULL; if ((ifp->if_flags & IFF_MULTICAST) != 0) { error = in6_update_ifa_join_mc(ifp, ifra, ia, flags, &in6m_sol); if (error != 0) { in6_purgeaddr(&ia->ia_ifa); ifa_free(&ia->ia_ifa); return (error); } } /* Perform DAD, if the address is TENTATIVE. */ if ((ia->ia6_flags & IN6_IFF_TENTATIVE)) { int delay, mindelay, maxdelay; delay = 0; if ((flags & IN6_IFAUPDATE_DADDELAY)) { /* * We need to impose a delay before sending an NS * for DAD. Check if we also needed a delay for the * corresponding MLD message. If we did, the delay * should be larger than the MLD delay (this could be * relaxed a bit, but this simple logic is at least * safe). * XXX: Break data hiding guidelines and look at * state for the solicited multicast group. */ mindelay = 0; if (in6m_sol != NULL && in6m_sol->in6m_state == MLD_REPORTING_MEMBER) { mindelay = in6m_sol->in6m_timer; } maxdelay = MAX_RTR_SOLICITATION_DELAY * hz; if (maxdelay - mindelay == 0) delay = 0; else { delay = (arc4random() % (maxdelay - mindelay)) + mindelay; } } nd6_dad_start((struct ifaddr *)ia, delay); } in6_newaddrmsg(ia, RTM_ADD); ifa_free(&ia->ia_ifa); return (error); } void in6_purgeaddr(struct ifaddr *ifa) { struct ifnet *ifp = ifa->ifa_ifp; struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa; struct in6_multi_mship *imm; int plen, error; if (ifa->ifa_carp) (*carp_detach_p)(ifa); /* * Remove the loopback route to the interface address. * The check for the current setting of "nd6_useloopback" * is not needed. */ if (ia->ia_flags & IFA_RTSELF) { error = ifa_del_loopback_route((struct ifaddr *)ia, (struct sockaddr *)&ia->ia_addr); if (error == 0) ia->ia_flags &= ~IFA_RTSELF; } /* stop DAD processing */ nd6_dad_stop(ifa); /* Leave multicast groups. */ while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) { LIST_REMOVE(imm, i6mm_chain); in6_leavegroup(imm); } plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */ if ((ia->ia_flags & IFA_ROUTE) && plen == 128) { error = rtinit(&(ia->ia_ifa), RTM_DELETE, ia->ia_flags | (ia->ia_dstaddr.sin6_family == AF_INET6) ? RTF_HOST : 0); if (error != 0) log(LOG_INFO, "%s: err=%d, destination address delete " "failed\n", __func__, error); ia->ia_flags &= ~IFA_ROUTE; } in6_newaddrmsg(ia, RTM_DELETE); in6_unlink_ifa(ia, ifp); } static void in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp) { char ip6buf[INET6_ADDRSTRLEN]; int remove_lle; IF_ADDR_WLOCK(ifp); TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link); IF_ADDR_WUNLOCK(ifp); ifa_free(&ia->ia_ifa); /* if_addrhead */ /* * Defer the release of what might be the last reference to the * in6_ifaddr so that it can't be freed before the remainder of the * cleanup. */ IN6_IFADDR_WLOCK(); TAILQ_REMOVE(&V_in6_ifaddrhead, ia, ia_link); LIST_REMOVE(ia, ia6_hash); IN6_IFADDR_WUNLOCK(); /* * Release the reference to the base prefix. There should be a * positive reference. */ remove_lle = 0; if (ia->ia6_ndpr == NULL) { nd6log((LOG_NOTICE, "in6_unlink_ifa: autoconf'ed address " "%s has no prefix\n", ip6_sprintf(ip6buf, IA6_IN6(ia)))); } else { ia->ia6_ndpr->ndpr_refcnt--; /* Do not delete lles within prefix if refcont != 0 */ if (ia->ia6_ndpr->ndpr_refcnt == 0) remove_lle = 1; ia->ia6_ndpr = NULL; } nd6_rem_ifa_lle(ia, remove_lle); /* * Also, if the address being removed is autoconf'ed, call * pfxlist_onlink_check() since the release might affect the status of * other (detached) addresses. */ if ((ia->ia6_flags & IN6_IFF_AUTOCONF)) { pfxlist_onlink_check(); } ifa_free(&ia->ia_ifa); /* in6_ifaddrhead */ } /* * Notifies other subsystems about address change/arrival: * 1) Notifies device handler on the first IPv6 address assignment * 2) Handle routing table changes for P2P links and route * 3) Handle routing table changes for address host route */ static int in6_notify_ifa(struct ifnet *ifp, struct in6_ifaddr *ia, struct in6_aliasreq *ifra, int hostIsNew) { int error = 0, plen, ifacount = 0; struct ifaddr *ifa; struct sockaddr_in6 *pdst; char ip6buf[INET6_ADDRSTRLEN]; /* * Give the interface a chance to initialize * if this is its first address, */ if (hostIsNew != 0) { IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; ifacount++; } IF_ADDR_RUNLOCK(ifp); } if (ifacount <= 1 && ifp->if_ioctl) { error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia); if (error) return (error); } /* * If a new destination address is specified, scrub the old one and * install the new destination. Note that the interface must be * p2p or loopback. */ pdst = &ifra->ifra_dstaddr; if (pdst->sin6_family == AF_INET6 && !IN6_ARE_ADDR_EQUAL(&pdst->sin6_addr, &ia->ia_dstaddr.sin6_addr)) { if ((ia->ia_flags & IFA_ROUTE) != 0 && (rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST) != 0)) { nd6log((LOG_ERR, "in6_update_ifa_internal: failed to " "remove a route to the old destination: %s\n", ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr))); /* proceed anyway... */ } else ia->ia_flags &= ~IFA_ROUTE; ia->ia_dstaddr = *pdst; } /* * If a new destination address is specified for a point-to-point * interface, install a route to the destination as an interface * direct route. * XXX: the logic below rejects assigning multiple addresses on a p2p * interface that share the same destination. */ plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */ if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 && ia->ia_dstaddr.sin6_family == AF_INET6) { int rtflags = RTF_UP | RTF_HOST; /* * Handle the case for ::1 . */ if (ifp->if_flags & IFF_LOOPBACK) ia->ia_flags |= IFA_RTSELF; error = rtinit(&ia->ia_ifa, RTM_ADD, ia->ia_flags | rtflags); if (error) return (error); ia->ia_flags |= IFA_ROUTE; } /* * add a loopback route to self if not exists */ if (!(ia->ia_flags & IFA_RTSELF) && V_nd6_useloopback) { error = ifa_add_loopback_route((struct ifaddr *)ia, (struct sockaddr *)&ia->ia_addr); if (error == 0) ia->ia_flags |= IFA_RTSELF; } return (error); } /* * Find an IPv6 interface link-local address specific to an interface. * ifaddr is returned referenced. */ struct in6_ifaddr * in6ifa_ifpforlinklocal(struct ifnet *ifp, int ignoreflags) { struct ifaddr *ifa; IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) { if ((((struct in6_ifaddr *)ifa)->ia6_flags & ignoreflags) != 0) continue; ifa_ref(ifa); break; } } IF_ADDR_RUNLOCK(ifp); return ((struct in6_ifaddr *)ifa); } /* * find the internet address corresponding to a given address. * ifaddr is returned referenced. */ struct in6_ifaddr * in6ifa_ifwithaddr(const struct in6_addr *addr, uint32_t zoneid) { struct rm_priotracker in6_ifa_tracker; struct in6_ifaddr *ia; IN6_IFADDR_RLOCK(&in6_ifa_tracker); LIST_FOREACH(ia, IN6ADDR_HASH(addr), ia6_hash) { if (IN6_ARE_ADDR_EQUAL(IA6_IN6(ia), addr)) { if (zoneid != 0 && zoneid != ia->ia_addr.sin6_scope_id) continue; ifa_ref(&ia->ia_ifa); break; } } IN6_IFADDR_RUNLOCK(&in6_ifa_tracker); return (ia); } /* * find the internet address corresponding to a given interface and address. * ifaddr is returned referenced. */ struct in6_ifaddr * in6ifa_ifpwithaddr(struct ifnet *ifp, const struct in6_addr *addr) { struct ifaddr *ifa; IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa))) { ifa_ref(ifa); break; } } IF_ADDR_RUNLOCK(ifp); return ((struct in6_ifaddr *)ifa); } /* * Find a link-local scoped address on ifp and return it if any. */ struct in6_ifaddr * in6ifa_llaonifp(struct ifnet *ifp) { struct sockaddr_in6 *sin6; struct ifaddr *ifa; if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) return (NULL); if_addr_rlock(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr) || IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr) || IN6_IS_ADDR_MC_NODELOCAL(&sin6->sin6_addr)) break; } if_addr_runlock(ifp); return ((struct in6_ifaddr *)ifa); } /* * Convert IP6 address to printable (loggable) representation. Caller * has to make sure that ip6buf is at least INET6_ADDRSTRLEN long. */ static char digits[] = "0123456789abcdef"; char * ip6_sprintf(char *ip6buf, const struct in6_addr *addr) { int i, cnt = 0, maxcnt = 0, idx = 0, index = 0; char *cp; const u_int16_t *a = (const u_int16_t *)addr; const u_int8_t *d; int dcolon = 0, zero = 0; cp = ip6buf; for (i = 0; i < 8; i++) { if (*(a + i) == 0) { cnt++; if (cnt == 1) idx = i; } else if (maxcnt < cnt) { maxcnt = cnt; index = idx; cnt = 0; } } if (maxcnt < cnt) { maxcnt = cnt; index = idx; } for (i = 0; i < 8; i++) { if (dcolon == 1) { if (*a == 0) { if (i == 7) *cp++ = ':'; a++; continue; } else dcolon = 2; } if (*a == 0) { if (dcolon == 0 && *(a + 1) == 0 && i == index) { if (i == 0) *cp++ = ':'; *cp++ = ':'; dcolon = 1; } else { *cp++ = '0'; *cp++ = ':'; } a++; continue; } d = (const u_char *)a; /* Try to eliminate leading zeros in printout like in :0001. */ zero = 1; *cp = digits[*d >> 4]; if (*cp != '0') { zero = 0; cp++; } *cp = digits[*d++ & 0xf]; if (zero == 0 || (*cp != '0')) { zero = 0; cp++; } *cp = digits[*d >> 4]; if (zero == 0 || (*cp != '0')) { zero = 0; cp++; } *cp++ = digits[*d & 0xf]; *cp++ = ':'; a++; } *--cp = '\0'; return (ip6buf); } int in6_localaddr(struct in6_addr *in6) { struct rm_priotracker in6_ifa_tracker; struct in6_ifaddr *ia; if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_ADDR_LINKLOCAL(in6)) return 1; IN6_IFADDR_RLOCK(&in6_ifa_tracker); TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) { if (IN6_ARE_MASKED_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr, &ia->ia_prefixmask.sin6_addr)) { IN6_IFADDR_RUNLOCK(&in6_ifa_tracker); return 1; } } IN6_IFADDR_RUNLOCK(&in6_ifa_tracker); return (0); } /* * Return 1 if an internet address is for the local host and configured * on one of its interfaces. */ int in6_localip(struct in6_addr *in6) { struct rm_priotracker in6_ifa_tracker; struct in6_ifaddr *ia; IN6_IFADDR_RLOCK(&in6_ifa_tracker); LIST_FOREACH(ia, IN6ADDR_HASH(in6), ia6_hash) { if (IN6_ARE_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr)) { IN6_IFADDR_RUNLOCK(&in6_ifa_tracker); return (1); } } IN6_IFADDR_RUNLOCK(&in6_ifa_tracker); return (0); } /* * Return 1 if an internet address is configured on an interface. */ int in6_ifhasaddr(struct ifnet *ifp, struct in6_addr *addr) { struct in6_addr in6; struct ifaddr *ifa; struct in6_ifaddr *ia6; in6 = *addr; if (in6_clearscope(&in6)) return (0); in6_setscope(&in6, ifp, NULL); IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; ia6 = (struct in6_ifaddr *)ifa; if (IN6_ARE_ADDR_EQUAL(&ia6->ia_addr.sin6_addr, &in6)) { IF_ADDR_RUNLOCK(ifp); return (1); } } IF_ADDR_RUNLOCK(ifp); return (0); } int in6_is_addr_deprecated(struct sockaddr_in6 *sa6) { struct rm_priotracker in6_ifa_tracker; struct in6_ifaddr *ia; IN6_IFADDR_RLOCK(&in6_ifa_tracker); LIST_FOREACH(ia, IN6ADDR_HASH(&sa6->sin6_addr), ia6_hash) { if (IN6_ARE_ADDR_EQUAL(IA6_IN6(ia), &sa6->sin6_addr)) { if (ia->ia6_flags & IN6_IFF_DEPRECATED) { IN6_IFADDR_RUNLOCK(&in6_ifa_tracker); return (1); /* true */ } break; } } IN6_IFADDR_RUNLOCK(&in6_ifa_tracker); return (0); /* false */ } /* * return length of part which dst and src are equal * hard coding... */ int in6_matchlen(struct in6_addr *src, struct in6_addr *dst) { int match = 0; u_char *s = (u_char *)src, *d = (u_char *)dst; u_char *lim = s + 16, r; while (s < lim) if ((r = (*d++ ^ *s++)) != 0) { while (r < 128) { match++; r <<= 1; } break; } else match += 8; return match; } /* XXX: to be scope conscious */ int in6_are_prefix_equal(struct in6_addr *p1, struct in6_addr *p2, int len) { int bytelen, bitlen; /* sanity check */ if (0 > len || len > 128) { log(LOG_ERR, "in6_are_prefix_equal: invalid prefix length(%d)\n", len); return (0); } bytelen = len / 8; bitlen = len % 8; if (bcmp(&p1->s6_addr, &p2->s6_addr, bytelen)) return (0); if (bitlen != 0 && p1->s6_addr[bytelen] >> (8 - bitlen) != p2->s6_addr[bytelen] >> (8 - bitlen)) return (0); return (1); } void in6_prefixlen2mask(struct in6_addr *maskp, int len) { u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; int bytelen, bitlen, i; /* sanity check */ if (0 > len || len > 128) { log(LOG_ERR, "in6_prefixlen2mask: invalid prefix length(%d)\n", len); return; } bzero(maskp, sizeof(*maskp)); bytelen = len / 8; bitlen = len % 8; for (i = 0; i < bytelen; i++) maskp->s6_addr[i] = 0xff; if (bitlen) maskp->s6_addr[bytelen] = maskarray[bitlen - 1]; } /* * return the best address out of the same scope. if no address was * found, return the first valid address from designated IF. */ struct in6_ifaddr * in6_ifawithifp(struct ifnet *ifp, struct in6_addr *dst) { int dst_scope = in6_addrscope(dst), blen = -1, tlen; struct ifaddr *ifa; struct in6_ifaddr *besta = 0; struct in6_ifaddr *dep[2]; /* last-resort: deprecated */ dep[0] = dep[1] = NULL; /* * We first look for addresses in the same scope. * If there is one, return it. * If two or more, return one which matches the dst longest. * If none, return one of global addresses assigned other ifs. */ IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST) continue; /* XXX: is there any case to allow anycast? */ if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY) continue; /* don't use this interface */ if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED) continue; if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) { if (V_ip6_use_deprecated) dep[0] = (struct in6_ifaddr *)ifa; continue; } if (dst_scope == in6_addrscope(IFA_IN6(ifa))) { /* * call in6_matchlen() as few as possible */ if (besta) { if (blen == -1) blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst); tlen = in6_matchlen(IFA_IN6(ifa), dst); if (tlen > blen) { blen = tlen; besta = (struct in6_ifaddr *)ifa; } } else besta = (struct in6_ifaddr *)ifa; } } if (besta) { ifa_ref(&besta->ia_ifa); IF_ADDR_RUNLOCK(ifp); return (besta); } TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST) continue; /* XXX: is there any case to allow anycast? */ if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY) continue; /* don't use this interface */ if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED) continue; if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) { if (V_ip6_use_deprecated) dep[1] = (struct in6_ifaddr *)ifa; continue; } if (ifa != NULL) ifa_ref(ifa); IF_ADDR_RUNLOCK(ifp); return (struct in6_ifaddr *)ifa; } /* use the last-resort values, that are, deprecated addresses */ if (dep[0]) { ifa_ref((struct ifaddr *)dep[0]); IF_ADDR_RUNLOCK(ifp); return dep[0]; } if (dep[1]) { ifa_ref((struct ifaddr *)dep[1]); IF_ADDR_RUNLOCK(ifp); return dep[1]; } IF_ADDR_RUNLOCK(ifp); return NULL; } /* * perform DAD when interface becomes IFF_UP. */ void in6_if_up(struct ifnet *ifp) { struct ifaddr *ifa; struct in6_ifaddr *ia; IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; ia = (struct in6_ifaddr *)ifa; if (ia->ia6_flags & IN6_IFF_TENTATIVE) { /* * The TENTATIVE flag was likely set by hand * beforehand, implicitly indicating the need for DAD. * We may be able to skip the random delay in this * case, but we impose delays just in case. */ nd6_dad_start(ifa, arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz)); } } IF_ADDR_RUNLOCK(ifp); /* * special cases, like 6to4, are handled in in6_ifattach */ in6_ifattach(ifp, NULL); } int in6if_do_dad(struct ifnet *ifp) { if ((ifp->if_flags & IFF_LOOPBACK) != 0) return (0); if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) || (ND_IFINFO(ifp)->flags & ND6_IFF_NO_DAD)) return (0); /* * Our DAD routine requires the interface up and running. * However, some interfaces can be up before the RUNNING * status. Additionaly, users may try to assign addresses * before the interface becomes up (or running). * This function returns EAGAIN in that case. * The caller should mark "tentative" on the address instead of * performing DAD immediately. */ if (!((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))) return (EAGAIN); return (1); } /* * Calculate max IPv6 MTU through all the interfaces and store it * to in6_maxmtu. */ void in6_setmaxmtu(void) { unsigned long maxmtu = 0; struct ifnet *ifp; IFNET_RLOCK_NOSLEEP(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { /* this function can be called during ifnet initialization */ if (!ifp->if_afdata[AF_INET6]) continue; if ((ifp->if_flags & IFF_LOOPBACK) == 0 && IN6_LINKMTU(ifp) > maxmtu) maxmtu = IN6_LINKMTU(ifp); } IFNET_RUNLOCK_NOSLEEP(); if (maxmtu) /* update only when maxmtu is positive */ V_in6_maxmtu = maxmtu; } /* * Provide the length of interface identifiers to be used for the link attached * to the given interface. The length should be defined in "IPv6 over * xxx-link" document. Note that address architecture might also define * the length for a particular set of address prefixes, regardless of the * link type. As clarified in rfc2462bis, those two definitions should be * consistent, and those really are as of August 2004. */ int in6_if2idlen(struct ifnet *ifp) { switch (ifp->if_type) { case IFT_ETHER: /* RFC2464 */ case IFT_PROPVIRTUAL: /* XXX: no RFC. treat it as ether */ case IFT_L2VLAN: /* ditto */ case IFT_IEEE80211: /* ditto */ case IFT_INFINIBAND: return (64); case IFT_FDDI: /* RFC2467 */ return (64); case IFT_ISO88025: /* RFC2470 (IPv6 over Token Ring) */ return (64); case IFT_PPP: /* RFC2472 */ return (64); case IFT_ARCNET: /* RFC2497 */ return (64); case IFT_FRELAY: /* RFC2590 */ return (64); case IFT_IEEE1394: /* RFC3146 */ return (64); case IFT_GIF: return (64); /* draft-ietf-v6ops-mech-v2-07 */ case IFT_LOOP: return (64); /* XXX: is this really correct? */ default: /* * Unknown link type: * It might be controversial to use the today's common constant * of 64 for these cases unconditionally. For full compliance, * we should return an error in this case. On the other hand, * if we simply miss the standard for the link type or a new * standard is defined for a new link type, the IFID length * is very likely to be the common constant. As a compromise, * we always use the constant, but make an explicit notice * indicating the "unknown" case. */ printf("in6_if2idlen: unknown link type (%d)\n", ifp->if_type); return (64); } } #include struct in6_llentry { struct llentry base; }; #define IN6_LLTBL_DEFAULT_HSIZE 32 #define IN6_LLTBL_HASH(k, h) \ (((((((k >> 8) ^ k) >> 8) ^ k) >> 8) ^ k) & ((h) - 1)) /* * Do actual deallocation of @lle. * Called by LLE_FREE_LOCKED when number of references * drops to zero. */ static void in6_lltable_destroy_lle(struct llentry *lle) { LLE_WUNLOCK(lle); LLE_LOCK_DESTROY(lle); LLE_REQ_DESTROY(lle); free(lle, M_LLTABLE); } static struct llentry * in6_lltable_new(const struct in6_addr *addr6, u_int flags) { struct in6_llentry *lle; lle = malloc(sizeof(struct in6_llentry), M_LLTABLE, M_NOWAIT | M_ZERO); if (lle == NULL) /* NB: caller generates msg */ return NULL; lle->base.r_l3addr.addr6 = *addr6; lle->base.lle_refcnt = 1; lle->base.lle_free = in6_lltable_destroy_lle; LLE_LOCK_INIT(&lle->base); LLE_REQ_INIT(&lle->base); callout_init(&lle->base.lle_timer, 1); return (&lle->base); } static int in6_lltable_match_prefix(const struct sockaddr *saddr, const struct sockaddr *smask, u_int flags, struct llentry *lle) { const struct in6_addr *addr, *mask, *lle_addr; addr = &((const struct sockaddr_in6 *)saddr)->sin6_addr; mask = &((const struct sockaddr_in6 *)smask)->sin6_addr; lle_addr = &lle->r_l3addr.addr6; if (IN6_ARE_MASKED_ADDR_EQUAL(lle_addr, addr, mask) == 0) return (0); if (lle->la_flags & LLE_IFADDR) { /* * Delete LLE_IFADDR records IFF address & flag matches. * Note that addr is the interface address within prefix * being matched. */ if (IN6_ARE_ADDR_EQUAL(addr, lle_addr) && (flags & LLE_STATIC) != 0) return (1); return (0); } /* flags & LLE_STATIC means deleting both dynamic and static entries */ if ((flags & LLE_STATIC) || !(lle->la_flags & LLE_STATIC)) return (1); return (0); } static void in6_lltable_free_entry(struct lltable *llt, struct llentry *lle) { struct ifnet *ifp; LLE_WLOCK_ASSERT(lle); KASSERT(llt != NULL, ("lltable is NULL")); /* Unlink entry from table */ if ((lle->la_flags & LLE_LINKED) != 0) { ifp = llt->llt_ifp; IF_AFDATA_WLOCK_ASSERT(ifp); lltable_unlink_entry(llt, lle); } if (callout_stop(&lle->lle_timer) > 0) LLE_REMREF(lle); llentry_free(lle); } static int in6_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr) { const struct sockaddr_in6 *sin6; struct nhop6_basic nh6; struct in6_addr dst; uint32_t scopeid; int error; char ip6buf[INET6_ADDRSTRLEN]; KASSERT(l3addr->sa_family == AF_INET6, ("sin_family %d", l3addr->sa_family)); /* Our local addresses are always only installed on the default FIB. */ sin6 = (const struct sockaddr_in6 *)l3addr; in6_splitscope(&sin6->sin6_addr, &dst, &scopeid); error = fib6_lookup_nh_basic(RT_DEFAULT_FIB, &dst, scopeid, 0, 0, &nh6); if (error != 0 || (nh6.nh_flags & NHF_GATEWAY) || nh6.nh_ifp != ifp) { struct ifaddr *ifa; /* * Create an ND6 cache for an IPv6 neighbor * that is not covered by our own prefix. */ ifa = ifaof_ifpforaddr(l3addr, ifp); if (ifa != NULL) { ifa_free(ifa); return 0; } log(LOG_INFO, "IPv6 address: \"%s\" is not on the network\n", ip6_sprintf(ip6buf, &sin6->sin6_addr)); return EINVAL; } return 0; } static inline uint32_t in6_lltable_hash_dst(const struct in6_addr *dst, uint32_t hsize) { return (IN6_LLTBL_HASH(dst->s6_addr32[3], hsize)); } static uint32_t in6_lltable_hash(const struct llentry *lle, uint32_t hsize) { return (in6_lltable_hash_dst(&lle->r_l3addr.addr6, hsize)); } static void in6_lltable_fill_sa_entry(const struct llentry *lle, struct sockaddr *sa) { struct sockaddr_in6 *sin6; sin6 = (struct sockaddr_in6 *)sa; bzero(sin6, sizeof(*sin6)); sin6->sin6_family = AF_INET6; sin6->sin6_len = sizeof(*sin6); sin6->sin6_addr = lle->r_l3addr.addr6; } static inline struct llentry * in6_lltable_find_dst(struct lltable *llt, const struct in6_addr *dst) { struct llentry *lle; struct llentries *lleh; u_int hashidx; hashidx = in6_lltable_hash_dst(dst, llt->llt_hsize); lleh = &llt->lle_head[hashidx]; LIST_FOREACH(lle, lleh, lle_next) { if (lle->la_flags & LLE_DELETED) continue; if (IN6_ARE_ADDR_EQUAL(&lle->r_l3addr.addr6, dst)) break; } return (lle); } static void in6_lltable_delete_entry(struct lltable *llt, struct llentry *lle) { lle->la_flags |= LLE_DELETED; EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_DELETED); #ifdef DIAGNOSTIC log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle); #endif llentry_free(lle); } static struct llentry * in6_lltable_alloc(struct lltable *llt, u_int flags, const struct sockaddr *l3addr) { const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr; struct ifnet *ifp = llt->llt_ifp; struct llentry *lle; KASSERT(l3addr->sa_family == AF_INET6, ("sin_family %d", l3addr->sa_family)); /* * A route that covers the given address must have * been installed 1st because we are doing a resolution, * verify this. */ if (!(flags & LLE_IFADDR) && in6_lltable_rtcheck(ifp, flags, l3addr) != 0) return (NULL); lle = in6_lltable_new(&sin6->sin6_addr, flags); if (lle == NULL) { log(LOG_INFO, "lla_lookup: new lle malloc failed\n"); return (NULL); } lle->la_flags = flags; if ((flags & LLE_IFADDR) == LLE_IFADDR) { lltable_set_entry_addr(ifp, lle, IF_LLADDR(ifp)); lle->la_flags |= LLE_STATIC; } if ((lle->la_flags & LLE_STATIC) != 0) lle->ln_state = ND6_LLINFO_REACHABLE; return (lle); } static struct llentry * in6_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr) { const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr; struct llentry *lle; IF_AFDATA_LOCK_ASSERT(llt->llt_ifp); KASSERT(l3addr->sa_family == AF_INET6, ("sin_family %d", l3addr->sa_family)); lle = in6_lltable_find_dst(llt, &sin6->sin6_addr); if (lle == NULL) return (NULL); KASSERT((flags & (LLE_UNLOCKED|LLE_EXCLUSIVE)) != (LLE_UNLOCKED|LLE_EXCLUSIVE),("wrong lle request flags: 0x%X", flags)); if (flags & LLE_UNLOCKED) return (lle); if (flags & LLE_EXCLUSIVE) LLE_WLOCK(lle); else LLE_RLOCK(lle); return (lle); } static int in6_lltable_dump_entry(struct lltable *llt, struct llentry *lle, struct sysctl_req *wr) { struct ifnet *ifp = llt->llt_ifp; /* XXX stack use */ struct { struct rt_msghdr rtm; struct sockaddr_in6 sin6; /* * ndp.c assumes that sdl is word aligned */ #ifdef __LP64__ uint32_t pad; #endif struct sockaddr_dl sdl; } ndpc; struct sockaddr_dl *sdl; int error; bzero(&ndpc, sizeof(ndpc)); /* skip deleted entries */ if ((lle->la_flags & LLE_DELETED) == LLE_DELETED) return (0); /* Skip if jailed and not a valid IP of the prison. */ lltable_fill_sa_entry(lle, (struct sockaddr *)&ndpc.sin6); if (prison_if(wr->td->td_ucred, (struct sockaddr *)&ndpc.sin6) != 0) return (0); /* * produce a msg made of: * struct rt_msghdr; * struct sockaddr_in6 (IPv6) * struct sockaddr_dl; */ ndpc.rtm.rtm_msglen = sizeof(ndpc); ndpc.rtm.rtm_version = RTM_VERSION; ndpc.rtm.rtm_type = RTM_GET; ndpc.rtm.rtm_flags = RTF_UP; ndpc.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY; if (V_deembed_scopeid) sa6_recoverscope(&ndpc.sin6); /* publish */ if (lle->la_flags & LLE_PUB) ndpc.rtm.rtm_flags |= RTF_ANNOUNCE; sdl = &ndpc.sdl; sdl->sdl_family = AF_LINK; sdl->sdl_len = sizeof(*sdl); sdl->sdl_alen = ifp->if_addrlen; sdl->sdl_index = ifp->if_index; sdl->sdl_type = ifp->if_type; bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen); if (lle->la_expire != 0) ndpc.rtm.rtm_rmx.rmx_expire = lle->la_expire + lle->lle_remtime / hz + time_second - time_uptime; ndpc.rtm.rtm_flags |= (RTF_HOST | RTF_LLDATA); if (lle->la_flags & LLE_STATIC) ndpc.rtm.rtm_flags |= RTF_STATIC; if (lle->la_flags & LLE_IFADDR) ndpc.rtm.rtm_flags |= RTF_PINNED; if (lle->ln_router != 0) ndpc.rtm.rtm_flags |= RTF_GATEWAY; ndpc.rtm.rtm_rmx.rmx_pksent = lle->la_asked; /* Store state in rmx_weight value */ ndpc.rtm.rtm_rmx.rmx_state = lle->ln_state; ndpc.rtm.rtm_index = ifp->if_index; error = SYSCTL_OUT(wr, &ndpc, sizeof(ndpc)); return (error); } static struct lltable * in6_lltattach(struct ifnet *ifp) { struct lltable *llt; llt = lltable_allocate_htbl(IN6_LLTBL_DEFAULT_HSIZE); llt->llt_af = AF_INET6; llt->llt_ifp = ifp; llt->llt_lookup = in6_lltable_lookup; llt->llt_alloc_entry = in6_lltable_alloc; llt->llt_delete_entry = in6_lltable_delete_entry; llt->llt_dump_entry = in6_lltable_dump_entry; llt->llt_hash = in6_lltable_hash; llt->llt_fill_sa_entry = in6_lltable_fill_sa_entry; llt->llt_free_entry = in6_lltable_free_entry; llt->llt_match_prefix = in6_lltable_match_prefix; lltable_link(llt); return (llt); } void * in6_domifattach(struct ifnet *ifp) { struct in6_ifextra *ext; /* There are not IPv6-capable interfaces. */ switch (ifp->if_type) { case IFT_PFLOG: case IFT_PFSYNC: case IFT_USB: return (NULL); } ext = (struct in6_ifextra *)malloc(sizeof(*ext), M_IFADDR, M_WAITOK); bzero(ext, sizeof(*ext)); ext->in6_ifstat = malloc(sizeof(counter_u64_t) * sizeof(struct in6_ifstat) / sizeof(uint64_t), M_IFADDR, M_WAITOK); COUNTER_ARRAY_ALLOC(ext->in6_ifstat, sizeof(struct in6_ifstat) / sizeof(uint64_t), M_WAITOK); ext->icmp6_ifstat = malloc(sizeof(counter_u64_t) * sizeof(struct icmp6_ifstat) / sizeof(uint64_t), M_IFADDR, M_WAITOK); COUNTER_ARRAY_ALLOC(ext->icmp6_ifstat, sizeof(struct icmp6_ifstat) / sizeof(uint64_t), M_WAITOK); ext->nd_ifinfo = nd6_ifattach(ifp); ext->scope6_id = scope6_ifattach(ifp); ext->lltable = in6_lltattach(ifp); ext->mld_ifinfo = mld_domifattach(ifp); return ext; } int in6_domifmtu(struct ifnet *ifp) { if (ifp->if_afdata[AF_INET6] == NULL) return ifp->if_mtu; return (IN6_LINKMTU(ifp)); } void in6_domifdetach(struct ifnet *ifp, void *aux) { struct in6_ifextra *ext = (struct in6_ifextra *)aux; mld_domifdetach(ifp); scope6_ifdetach(ext->scope6_id); nd6_ifdetach(ext->nd_ifinfo); lltable_free(ext->lltable); COUNTER_ARRAY_FREE(ext->in6_ifstat, sizeof(struct in6_ifstat) / sizeof(uint64_t)); free(ext->in6_ifstat, M_IFADDR); COUNTER_ARRAY_FREE(ext->icmp6_ifstat, sizeof(struct icmp6_ifstat) / sizeof(uint64_t)); free(ext->icmp6_ifstat, M_IFADDR); free(ext, M_IFADDR); } /* * Convert sockaddr_in6 to sockaddr_in. Original sockaddr_in6 must be * v4 mapped addr or v4 compat addr */ void in6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6) { bzero(sin, sizeof(*sin)); sin->sin_len = sizeof(struct sockaddr_in); sin->sin_family = AF_INET; sin->sin_port = sin6->sin6_port; sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3]; } /* Convert sockaddr_in to sockaddr_in6 in v4 mapped addr format. */ void in6_sin_2_v4mapsin6(struct sockaddr_in *sin, struct sockaddr_in6 *sin6) { bzero(sin6, sizeof(*sin6)); sin6->sin6_len = sizeof(struct sockaddr_in6); sin6->sin6_family = AF_INET6; sin6->sin6_port = sin->sin_port; sin6->sin6_addr.s6_addr32[0] = 0; sin6->sin6_addr.s6_addr32[1] = 0; sin6->sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP; sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr; } /* Convert sockaddr_in6 into sockaddr_in. */ void in6_sin6_2_sin_in_sock(struct sockaddr *nam) { struct sockaddr_in *sin_p; struct sockaddr_in6 sin6; /* * Save original sockaddr_in6 addr and convert it * to sockaddr_in. */ sin6 = *(struct sockaddr_in6 *)nam; sin_p = (struct sockaddr_in *)nam; in6_sin6_2_sin(sin_p, &sin6); } /* Convert sockaddr_in into sockaddr_in6 in v4 mapped addr format. */ void in6_sin_2_v4mapsin6_in_sock(struct sockaddr **nam) { struct sockaddr_in *sin_p; struct sockaddr_in6 *sin6_p; sin6_p = malloc(sizeof *sin6_p, M_SONAME, M_WAITOK); sin_p = (struct sockaddr_in *)*nam; in6_sin_2_v4mapsin6(sin_p, sin6_p); free(*nam, M_SONAME); *nam = (struct sockaddr *)sin6_p; } Index: user/alc/PQ_LAUNDRY/sys/netinet6/in6_var.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/netinet6/in6_var.h (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/netinet6/in6_var.h (revision 292449) @@ -1,842 +1,832 @@ /*- * 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. * * $KAME: in6_var.h,v 1.56 2001/03/29 05:34:31 itojun Exp $ */ /*- * Copyright (c) 1985, 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. * 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. * * @(#)in_var.h 8.1 (Berkeley) 6/10/93 * $FreeBSD$ */ #ifndef _NETINET6_IN6_VAR_H_ #define _NETINET6_IN6_VAR_H_ #include #include #ifdef _KERNEL #include #include #endif /* * Interface address, Internet version. One of these structures * is allocated for each interface with an Internet address. * The ifaddr structure contains the protocol-independent part * of the structure and is assumed to be first. */ /* * pltime/vltime are just for future reference (required to implements 2 * hour rule for hosts). they should never be modified by nd6_timeout or * anywhere else. * userland -> kernel: accept pltime/vltime * kernel -> userland: throw up everything * in kernel: modify preferred/expire only */ struct in6_addrlifetime { time_t ia6t_expire; /* valid lifetime expiration time */ time_t ia6t_preferred; /* preferred lifetime expiration time */ u_int32_t ia6t_vltime; /* valid lifetime */ u_int32_t ia6t_pltime; /* prefix lifetime */ }; struct nd_ifinfo; struct scope6_id; struct lltable; struct mld_ifsoftc; struct in6_ifextra { counter_u64_t *in6_ifstat; counter_u64_t *icmp6_ifstat; struct nd_ifinfo *nd_ifinfo; struct scope6_id *scope6_id; struct lltable *lltable; struct mld_ifsoftc *mld_ifinfo; }; #define LLTABLE6(ifp) (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->lltable) #ifdef _KERNEL struct in6_ifaddr { struct ifaddr ia_ifa; /* protocol-independent info */ #define ia_ifp ia_ifa.ifa_ifp #define ia_flags ia_ifa.ifa_flags struct sockaddr_in6 ia_addr; /* interface address */ struct sockaddr_in6 ia_net; /* network number of interface */ struct sockaddr_in6 ia_dstaddr; /* space for destination addr */ struct sockaddr_in6 ia_prefixmask; /* prefix mask */ u_int32_t ia_plen; /* prefix length */ TAILQ_ENTRY(in6_ifaddr) ia_link; /* list of IPv6 addresses */ int ia6_flags; struct in6_addrlifetime ia6_lifetime; time_t ia6_createtime; /* the creation time of this address, which is * currently used for temporary addresses only. */ time_t ia6_updatetime; /* back pointer to the ND prefix (for autoconfigured addresses only) */ struct nd_prefix *ia6_ndpr; /* multicast addresses joined from the kernel */ LIST_HEAD(, in6_multi_mship) ia6_memberships; /* entry in bucket of inet6 addresses */ LIST_ENTRY(in6_ifaddr) ia6_hash; }; /* List of in6_ifaddr's. */ TAILQ_HEAD(in6_ifaddrhead, in6_ifaddr); LIST_HEAD(in6_ifaddrlisthead, in6_ifaddr); #endif /* _KERNEL */ /* control structure to manage address selection policy */ struct in6_addrpolicy { struct sockaddr_in6 addr; /* prefix address */ struct sockaddr_in6 addrmask; /* prefix mask */ int preced; /* precedence */ int label; /* matching label */ u_quad_t use; /* statistics */ }; /* * IPv6 interface statistics, as defined in RFC2465 Ipv6IfStatsEntry (p12). */ struct in6_ifstat { uint64_t ifs6_in_receive; /* # of total input datagram */ uint64_t ifs6_in_hdrerr; /* # of datagrams with invalid hdr */ uint64_t ifs6_in_toobig; /* # of datagrams exceeded MTU */ uint64_t ifs6_in_noroute; /* # of datagrams with no route */ uint64_t ifs6_in_addrerr; /* # of datagrams with invalid dst */ uint64_t ifs6_in_protounknown; /* # of datagrams with unknown proto */ /* NOTE: increment on final dst if */ uint64_t ifs6_in_truncated; /* # of truncated datagrams */ uint64_t ifs6_in_discard; /* # of discarded datagrams */ /* NOTE: fragment timeout is not here */ uint64_t ifs6_in_deliver; /* # of datagrams delivered to ULP */ /* NOTE: increment on final dst if */ uint64_t ifs6_out_forward; /* # of datagrams forwarded */ /* NOTE: increment on outgoing if */ uint64_t ifs6_out_request; /* # of outgoing datagrams from ULP */ /* NOTE: does not include forwrads */ uint64_t ifs6_out_discard; /* # of discarded datagrams */ uint64_t ifs6_out_fragok; /* # of datagrams fragmented */ uint64_t ifs6_out_fragfail; /* # of datagrams failed on fragment */ uint64_t ifs6_out_fragcreat; /* # of fragment datagrams */ /* NOTE: this is # after fragment */ uint64_t ifs6_reass_reqd; /* # of incoming fragmented packets */ /* NOTE: increment on final dst if */ uint64_t ifs6_reass_ok; /* # of reassembled packets */ /* NOTE: this is # after reass */ /* NOTE: increment on final dst if */ uint64_t ifs6_reass_fail; /* # of reass failures */ /* NOTE: may not be packet count */ /* NOTE: increment on final dst if */ uint64_t ifs6_in_mcast; /* # of inbound multicast datagrams */ uint64_t ifs6_out_mcast; /* # of outbound multicast datagrams */ }; /* * ICMPv6 interface statistics, as defined in RFC2466 Ipv6IfIcmpEntry. * XXX: I'm not sure if this file is the right place for this structure... */ struct icmp6_ifstat { /* * Input statistics */ /* ipv6IfIcmpInMsgs, total # of input messages */ uint64_t ifs6_in_msg; /* ipv6IfIcmpInErrors, # of input error messages */ uint64_t ifs6_in_error; /* ipv6IfIcmpInDestUnreachs, # of input dest unreach errors */ uint64_t ifs6_in_dstunreach; /* ipv6IfIcmpInAdminProhibs, # of input administratively prohibited errs */ uint64_t ifs6_in_adminprohib; /* ipv6IfIcmpInTimeExcds, # of input time exceeded errors */ uint64_t ifs6_in_timeexceed; /* ipv6IfIcmpInParmProblems, # of input parameter problem errors */ uint64_t ifs6_in_paramprob; /* ipv6IfIcmpInPktTooBigs, # of input packet too big errors */ uint64_t ifs6_in_pkttoobig; /* ipv6IfIcmpInEchos, # of input echo requests */ uint64_t ifs6_in_echo; /* ipv6IfIcmpInEchoReplies, # of input echo replies */ uint64_t ifs6_in_echoreply; /* ipv6IfIcmpInRouterSolicits, # of input router solicitations */ uint64_t ifs6_in_routersolicit; /* ipv6IfIcmpInRouterAdvertisements, # of input router advertisements */ uint64_t ifs6_in_routeradvert; /* ipv6IfIcmpInNeighborSolicits, # of input neighbor solicitations */ uint64_t ifs6_in_neighborsolicit; /* ipv6IfIcmpInNeighborAdvertisements, # of input neighbor advertisements */ uint64_t ifs6_in_neighboradvert; /* ipv6IfIcmpInRedirects, # of input redirects */ uint64_t ifs6_in_redirect; /* ipv6IfIcmpInGroupMembQueries, # of input MLD queries */ uint64_t ifs6_in_mldquery; /* ipv6IfIcmpInGroupMembResponses, # of input MLD reports */ uint64_t ifs6_in_mldreport; /* ipv6IfIcmpInGroupMembReductions, # of input MLD done */ uint64_t ifs6_in_mlddone; /* * Output statistics. We should solve unresolved routing problem... */ /* ipv6IfIcmpOutMsgs, total # of output messages */ uint64_t ifs6_out_msg; /* ipv6IfIcmpOutErrors, # of output error messages */ uint64_t ifs6_out_error; /* ipv6IfIcmpOutDestUnreachs, # of output dest unreach errors */ uint64_t ifs6_out_dstunreach; /* ipv6IfIcmpOutAdminProhibs, # of output administratively prohibited errs */ uint64_t ifs6_out_adminprohib; /* ipv6IfIcmpOutTimeExcds, # of output time exceeded errors */ uint64_t ifs6_out_timeexceed; /* ipv6IfIcmpOutParmProblems, # of output parameter problem errors */ uint64_t ifs6_out_paramprob; /* ipv6IfIcmpOutPktTooBigs, # of output packet too big errors */ uint64_t ifs6_out_pkttoobig; /* ipv6IfIcmpOutEchos, # of output echo requests */ uint64_t ifs6_out_echo; /* ipv6IfIcmpOutEchoReplies, # of output echo replies */ uint64_t ifs6_out_echoreply; /* ipv6IfIcmpOutRouterSolicits, # of output router solicitations */ uint64_t ifs6_out_routersolicit; /* ipv6IfIcmpOutRouterAdvertisements, # of output router advertisements */ uint64_t ifs6_out_routeradvert; /* ipv6IfIcmpOutNeighborSolicits, # of output neighbor solicitations */ uint64_t ifs6_out_neighborsolicit; /* ipv6IfIcmpOutNeighborAdvertisements, # of output neighbor advertisements */ uint64_t ifs6_out_neighboradvert; /* ipv6IfIcmpOutRedirects, # of output redirects */ uint64_t ifs6_out_redirect; /* ipv6IfIcmpOutGroupMembQueries, # of output MLD queries */ uint64_t ifs6_out_mldquery; /* ipv6IfIcmpOutGroupMembResponses, # of output MLD reports */ uint64_t ifs6_out_mldreport; /* ipv6IfIcmpOutGroupMembReductions, # of output MLD done */ uint64_t ifs6_out_mlddone; }; struct in6_ifreq { char ifr_name[IFNAMSIZ]; union { struct sockaddr_in6 ifru_addr; struct sockaddr_in6 ifru_dstaddr; int ifru_flags; int ifru_flags6; int ifru_metric; caddr_t ifru_data; struct in6_addrlifetime ifru_lifetime; struct in6_ifstat ifru_stat; struct icmp6_ifstat ifru_icmp6stat; u_int32_t ifru_scope_id[16]; } ifr_ifru; }; struct in6_aliasreq { char ifra_name[IFNAMSIZ]; struct sockaddr_in6 ifra_addr; struct sockaddr_in6 ifra_dstaddr; struct sockaddr_in6 ifra_prefixmask; int ifra_flags; struct in6_addrlifetime ifra_lifetime; int ifra_vhid; }; /* pre-10.x compat */ struct oin6_aliasreq { char ifra_name[IFNAMSIZ]; struct sockaddr_in6 ifra_addr; struct sockaddr_in6 ifra_dstaddr; struct sockaddr_in6 ifra_prefixmask; int ifra_flags; struct in6_addrlifetime ifra_lifetime; }; /* prefix type macro */ #define IN6_PREFIX_ND 1 #define IN6_PREFIX_RR 2 /* * prefix related flags passed between kernel(NDP related part) and * user land command(ifconfig) and daemon(rtadvd). */ struct in6_prflags { struct prf_ra { u_char onlink : 1; u_char autonomous : 1; u_char reserved : 6; } prf_ra; u_char prf_reserved1; u_short prf_reserved2; /* want to put this on 4byte offset */ struct prf_rr { u_char decrvalid : 1; u_char decrprefd : 1; u_char reserved : 6; } prf_rr; u_char prf_reserved3; u_short prf_reserved4; }; struct in6_prefixreq { char ipr_name[IFNAMSIZ]; u_char ipr_origin; u_char ipr_plen; u_int32_t ipr_vltime; u_int32_t ipr_pltime; struct in6_prflags ipr_flags; struct sockaddr_in6 ipr_prefix; }; #define PR_ORIG_RA 0 #define PR_ORIG_RR 1 #define PR_ORIG_STATIC 2 #define PR_ORIG_KERNEL 3 #define ipr_raf_onlink ipr_flags.prf_ra.onlink #define ipr_raf_auto ipr_flags.prf_ra.autonomous #define ipr_statef_onlink ipr_flags.prf_state.onlink #define ipr_rrf_decrvalid ipr_flags.prf_rr.decrvalid #define ipr_rrf_decrprefd ipr_flags.prf_rr.decrprefd struct in6_rrenumreq { char irr_name[IFNAMSIZ]; u_char irr_origin; u_char irr_m_len; /* match len for matchprefix */ u_char irr_m_minlen; /* minlen for matching prefix */ u_char irr_m_maxlen; /* maxlen for matching prefix */ u_char irr_u_uselen; /* uselen for adding prefix */ u_char irr_u_keeplen; /* keeplen from matching prefix */ struct irr_raflagmask { u_char onlink : 1; u_char autonomous : 1; u_char reserved : 6; } irr_raflagmask; u_int32_t irr_vltime; u_int32_t irr_pltime; struct in6_prflags irr_flags; struct sockaddr_in6 irr_matchprefix; struct sockaddr_in6 irr_useprefix; }; #define irr_raf_mask_onlink irr_raflagmask.onlink #define irr_raf_mask_auto irr_raflagmask.autonomous #define irr_raf_mask_reserved irr_raflagmask.reserved #define irr_raf_onlink irr_flags.prf_ra.onlink #define irr_raf_auto irr_flags.prf_ra.autonomous #define irr_statef_onlink irr_flags.prf_state.onlink #define irr_rrf irr_flags.prf_rr #define irr_rrf_decrvalid irr_flags.prf_rr.decrvalid #define irr_rrf_decrprefd irr_flags.prf_rr.decrprefd /* * Given a pointer to an in6_ifaddr (ifaddr), * return a pointer to the addr as a sockaddr_in6 */ #define IA6_IN6(ia) (&((ia)->ia_addr.sin6_addr)) #define IA6_DSTIN6(ia) (&((ia)->ia_dstaddr.sin6_addr)) #define IA6_MASKIN6(ia) (&((ia)->ia_prefixmask.sin6_addr)) #define IA6_SIN6(ia) (&((ia)->ia_addr)) #define IA6_DSTSIN6(ia) (&((ia)->ia_dstaddr)) #define IFA_IN6(x) (&((struct sockaddr_in6 *)((x)->ifa_addr))->sin6_addr) -#define IFA_IN6_FLAGS(ifa) ((struct in6_ifaddr *)ifa)->ia6_flags -#define IFA_ND6_NA_BASE_FLAGS(ifp, ifa) \ - (IFA_IN6_FLAGS(ifa) & IN6_IFF_ANYCAST ? 0 : ND_NA_FLAG_OVERRIDE) | \ - ((V_ip6_forwarding && !(ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV && \ - V_ip6_norbit_raif)) ? ND_NA_FLAG_ROUTER : 0) -#define IFA_ND6_NA_UNSOLICITED_SKIP(ifa) \ - (IFA_IN6_FLAGS(ifa) & (IN6_IFF_DUPLICATED | IN6_IFF_DEPRECATED | \ - IN6_IFF_TENTATIVE)) != 0 -#define IN6_MAX_ANYCAST_DELAY_TIME_MS 1000000 -#define IN6_BROADCAST_DELAY_TIME_MS 1000 #define IFA_DSTIN6(x) (&((struct sockaddr_in6 *)((x)->ifa_dstaddr))->sin6_addr) #define IFPR_IN6(x) (&((struct sockaddr_in6 *)((x)->ifpr_prefix))->sin6_addr) #ifdef _KERNEL #define IN6_ARE_MASKED_ADDR_EQUAL(d, a, m) ( \ (((d)->s6_addr32[0] ^ (a)->s6_addr32[0]) & (m)->s6_addr32[0]) == 0 && \ (((d)->s6_addr32[1] ^ (a)->s6_addr32[1]) & (m)->s6_addr32[1]) == 0 && \ (((d)->s6_addr32[2] ^ (a)->s6_addr32[2]) & (m)->s6_addr32[2]) == 0 && \ (((d)->s6_addr32[3] ^ (a)->s6_addr32[3]) & (m)->s6_addr32[3]) == 0 ) #define IN6_MASK_ADDR(a, m) do { \ (a)->s6_addr32[0] &= (m)->s6_addr32[0]; \ (a)->s6_addr32[1] &= (m)->s6_addr32[1]; \ (a)->s6_addr32[2] &= (m)->s6_addr32[2]; \ (a)->s6_addr32[3] &= (m)->s6_addr32[3]; \ } while (0) #endif #define SIOCSIFADDR_IN6 _IOW('i', 12, struct in6_ifreq) #define SIOCGIFADDR_IN6 _IOWR('i', 33, struct in6_ifreq) #ifdef _KERNEL /* * SIOCSxxx ioctls should be unused (see comments in in6.c), but * we do not shift numbers for binary compatibility. */ #define SIOCSIFDSTADDR_IN6 _IOW('i', 14, struct in6_ifreq) #define SIOCSIFNETMASK_IN6 _IOW('i', 22, struct in6_ifreq) #endif #define SIOCGIFDSTADDR_IN6 _IOWR('i', 34, struct in6_ifreq) #define SIOCGIFNETMASK_IN6 _IOWR('i', 37, struct in6_ifreq) #define SIOCDIFADDR_IN6 _IOW('i', 25, struct in6_ifreq) #define OSIOCAIFADDR_IN6 _IOW('i', 26, struct oin6_aliasreq) #define SIOCAIFADDR_IN6 _IOW('i', 27, struct in6_aliasreq) #define SIOCSIFPHYADDR_IN6 _IOW('i', 70, struct in6_aliasreq) #define SIOCGIFPSRCADDR_IN6 _IOWR('i', 71, struct in6_ifreq) #define SIOCGIFPDSTADDR_IN6 _IOWR('i', 72, struct in6_ifreq) #define SIOCGIFAFLAG_IN6 _IOWR('i', 73, struct in6_ifreq) #ifdef _KERNEL #define OSIOCGIFINFO_IN6 _IOWR('i', 76, struct in6_ondireq) #endif #define SIOCGIFINFO_IN6 _IOWR('i', 108, struct in6_ndireq) #define SIOCSIFINFO_IN6 _IOWR('i', 109, struct in6_ndireq) #define SIOCSNDFLUSH_IN6 _IOWR('i', 77, struct in6_ifreq) #define SIOCGNBRINFO_IN6 _IOWR('i', 78, struct in6_nbrinfo) #define SIOCSPFXFLUSH_IN6 _IOWR('i', 79, struct in6_ifreq) #define SIOCSRTRFLUSH_IN6 _IOWR('i', 80, struct in6_ifreq) #define SIOCGIFALIFETIME_IN6 _IOWR('i', 81, struct in6_ifreq) #define SIOCSIFALIFETIME_IN6 _IOWR('i', 82, struct in6_ifreq) #define SIOCGIFSTAT_IN6 _IOWR('i', 83, struct in6_ifreq) #define SIOCGIFSTAT_ICMP6 _IOWR('i', 84, struct in6_ifreq) #define SIOCSDEFIFACE_IN6 _IOWR('i', 85, struct in6_ndifreq) #define SIOCGDEFIFACE_IN6 _IOWR('i', 86, struct in6_ndifreq) #define SIOCSIFINFO_FLAGS _IOWR('i', 87, struct in6_ndireq) /* XXX */ #define SIOCSSCOPE6 _IOW('i', 88, struct in6_ifreq) #define SIOCGSCOPE6 _IOWR('i', 89, struct in6_ifreq) #define SIOCGSCOPE6DEF _IOWR('i', 90, struct in6_ifreq) #define SIOCSIFPREFIX_IN6 _IOW('i', 100, struct in6_prefixreq) /* set */ #define SIOCGIFPREFIX_IN6 _IOWR('i', 101, struct in6_prefixreq) /* get */ #define SIOCDIFPREFIX_IN6 _IOW('i', 102, struct in6_prefixreq) /* del */ #define SIOCAIFPREFIX_IN6 _IOW('i', 103, struct in6_rrenumreq) /* add */ #define SIOCCIFPREFIX_IN6 _IOW('i', 104, \ struct in6_rrenumreq) /* change */ #define SIOCSGIFPREFIX_IN6 _IOW('i', 105, \ struct in6_rrenumreq) /* set global */ #define SIOCGETSGCNT_IN6 _IOWR('u', 106, \ struct sioc_sg_req6) /* get s,g pkt cnt */ #define SIOCGETMIFCNT_IN6 _IOWR('u', 107, \ struct sioc_mif_req6) /* get pkt cnt per if */ #define SIOCAADDRCTL_POLICY _IOW('u', 108, struct in6_addrpolicy) #define SIOCDADDRCTL_POLICY _IOW('u', 109, struct in6_addrpolicy) #define IN6_IFF_ANYCAST 0x01 /* anycast address */ #define IN6_IFF_TENTATIVE 0x02 /* tentative address */ #define IN6_IFF_DUPLICATED 0x04 /* DAD detected duplicate */ #define IN6_IFF_DETACHED 0x08 /* may be detached from the link */ #define IN6_IFF_DEPRECATED 0x10 /* deprecated address */ #define IN6_IFF_NODAD 0x20 /* don't perform DAD on this address * (obsolete) */ #define IN6_IFF_AUTOCONF 0x40 /* autoconfigurable address. */ #define IN6_IFF_TEMPORARY 0x80 /* temporary (anonymous) address. */ #define IN6_IFF_PREFER_SOURCE 0x0100 /* preferred address for SAS */ /* do not input/output */ #define IN6_IFF_NOTREADY (IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED) #ifdef _KERNEL #define IN6_ARE_SCOPE_CMP(a,b) ((a)-(b)) #define IN6_ARE_SCOPE_EQUAL(a,b) ((a)==(b)) #endif #ifdef _KERNEL VNET_DECLARE(struct in6_ifaddrhead, in6_ifaddrhead); VNET_DECLARE(struct in6_ifaddrlisthead *, in6_ifaddrhashtbl); VNET_DECLARE(u_long, in6_ifaddrhmask); #define V_in6_ifaddrhead VNET(in6_ifaddrhead) #define V_in6_ifaddrhashtbl VNET(in6_ifaddrhashtbl) #define V_in6_ifaddrhmask VNET(in6_ifaddrhmask) #define IN6ADDR_NHASH_LOG2 8 #define IN6ADDR_NHASH (1 << IN6ADDR_NHASH_LOG2) #define IN6ADDR_HASHVAL(x) (in6_addrhash(x)) #define IN6ADDR_HASH(x) \ (&V_in6_ifaddrhashtbl[IN6ADDR_HASHVAL(x) & V_in6_ifaddrhmask]) static __inline uint32_t in6_addrhash(const struct in6_addr *in6) { uint32_t x; x = in6->s6_addr32[0] ^ in6->s6_addr32[1] ^ in6->s6_addr32[2] ^ in6->s6_addr32[3]; return (fnv_32_buf(&x, sizeof(x), FNV1_32_INIT)); } extern struct rmlock in6_ifaddr_lock; #define IN6_IFADDR_LOCK_ASSERT() rm_assert(&in6_ifaddr_lock, RA_LOCKED) #define IN6_IFADDR_RLOCK(t) rm_rlock(&in6_ifaddr_lock, (t)) #define IN6_IFADDR_RLOCK_ASSERT() rm_assert(&in6_ifaddr_lock, RA_RLOCKED) #define IN6_IFADDR_RUNLOCK(t) rm_runlock(&in6_ifaddr_lock, (t)) #define IN6_IFADDR_WLOCK() rm_wlock(&in6_ifaddr_lock) #define IN6_IFADDR_WLOCK_ASSERT() rm_assert(&in6_ifaddr_lock, RA_WLOCKED) #define IN6_IFADDR_WUNLOCK() rm_wunlock(&in6_ifaddr_lock) #define in6_ifstat_inc(ifp, tag) \ do { \ if (ifp) \ counter_u64_add(((struct in6_ifextra *) \ ((ifp)->if_afdata[AF_INET6]))->in6_ifstat[ \ offsetof(struct in6_ifstat, tag) / sizeof(uint64_t)], 1);\ } while (/*CONSTCOND*/ 0) extern u_char inet6ctlerrmap[]; VNET_DECLARE(unsigned long, in6_maxmtu); #define V_in6_maxmtu VNET(in6_maxmtu) #endif /* _KERNEL */ /* * IPv6 multicast MLD-layer source entry. */ struct ip6_msource { RB_ENTRY(ip6_msource) im6s_link; /* RB tree links */ struct in6_addr im6s_addr; struct im6s_st { uint16_t ex; /* # of exclusive members */ uint16_t in; /* # of inclusive members */ } im6s_st[2]; /* state at t0, t1 */ uint8_t im6s_stp; /* pending query */ }; RB_HEAD(ip6_msource_tree, ip6_msource); /* * IPv6 multicast PCB-layer source entry. * * NOTE: overlapping use of struct ip6_msource fields at start. */ struct in6_msource { RB_ENTRY(ip6_msource) im6s_link; /* Common field */ struct in6_addr im6s_addr; /* Common field */ uint8_t im6sl_st[2]; /* state before/at commit */ }; #ifdef _KERNEL /* * IPv6 source tree comparison function. * * An ordered predicate is necessary; bcmp() is not documented to return * an indication of order, memcmp() is, and is an ISO C99 requirement. */ static __inline int ip6_msource_cmp(const struct ip6_msource *a, const struct ip6_msource *b) { return (memcmp(&a->im6s_addr, &b->im6s_addr, sizeof(struct in6_addr))); } RB_PROTOTYPE(ip6_msource_tree, ip6_msource, im6s_link, ip6_msource_cmp); /* * IPv6 multicast PCB-layer group filter descriptor. */ struct in6_mfilter { struct ip6_msource_tree im6f_sources; /* source list for (S,G) */ u_long im6f_nsrc; /* # of source entries */ uint8_t im6f_st[2]; /* state before/at commit */ }; /* * Legacy KAME IPv6 multicast membership descriptor. */ struct in6_multi_mship { struct in6_multi *i6mm_maddr; LIST_ENTRY(in6_multi_mship) i6mm_chain; }; /* * IPv6 group descriptor. * * For every entry on an ifnet's if_multiaddrs list which represents * an IP multicast group, there is one of these structures. * * If any source filters are present, then a node will exist in the RB-tree * to permit fast lookup by source whenever an operation takes place. * This permits pre-order traversal when we issue reports. * Source filter trees are kept separately from the socket layer to * greatly simplify locking. * * When MLDv2 is active, in6m_timer is the response to group query timer. * The state-change timer in6m_sctimer is separate; whenever state changes * for the group the state change record is generated and transmitted, * and kept if retransmissions are necessary. * * FUTURE: in6m_link is now only used when groups are being purged * on a detaching ifnet. It could be demoted to a SLIST_ENTRY, but * because it is at the very start of the struct, we can't do this * w/o breaking the ABI for ifmcstat. */ struct in6_multi { LIST_ENTRY(in6_multi) in6m_entry; /* list glue */ struct in6_addr in6m_addr; /* IPv6 multicast address */ struct ifnet *in6m_ifp; /* back pointer to ifnet */ struct ifmultiaddr *in6m_ifma; /* back pointer to ifmultiaddr */ u_int in6m_refcount; /* reference count */ u_int in6m_state; /* state of the membership */ u_int in6m_timer; /* MLD6 listener report timer */ /* New fields for MLDv2 follow. */ struct mld_ifsoftc *in6m_mli; /* MLD info */ SLIST_ENTRY(in6_multi) in6m_nrele; /* to-be-released by MLD */ struct ip6_msource_tree in6m_srcs; /* tree of sources */ u_long in6m_nsrc; /* # of tree entries */ struct mbufq in6m_scq; /* queue of pending * state-change packets */ struct timeval in6m_lastgsrtv; /* last G-S-R query */ uint16_t in6m_sctimer; /* state-change timer */ uint16_t in6m_scrv; /* state-change rexmit count */ /* * SSM state counters which track state at T0 (the time the last * state-change report's RV timer went to zero) and T1 * (time of pending report, i.e. now). * Used for computing MLDv2 state-change reports. Several refcounts * are maintained here to optimize for common use-cases. */ struct in6m_st { uint16_t iss_fmode; /* MLD filter mode */ uint16_t iss_asm; /* # of ASM listeners */ uint16_t iss_ex; /* # of exclusive members */ uint16_t iss_in; /* # of inclusive members */ uint16_t iss_rec; /* # of recorded sources */ } in6m_st[2]; /* state at t0, t1 */ }; /* * Helper function to derive the filter mode on a source entry * from its internal counters. Predicates are: * A source is only excluded if all listeners exclude it. * A source is only included if no listeners exclude it, * and at least one listener includes it. * May be used by ifmcstat(8). */ static __inline uint8_t im6s_get_mode(const struct in6_multi *inm, const struct ip6_msource *ims, uint8_t t) { t = !!t; if (inm->in6m_st[t].iss_ex > 0 && inm->in6m_st[t].iss_ex == ims->im6s_st[t].ex) return (MCAST_EXCLUDE); else if (ims->im6s_st[t].in > 0 && ims->im6s_st[t].ex == 0) return (MCAST_INCLUDE); return (MCAST_UNDEFINED); } /* * Lock macros for IPv6 layer multicast address lists. IPv6 lock goes * before link layer multicast locks in the lock order. In most cases, * consumers of IN_*_MULTI() macros should acquire the locks before * calling them; users of the in_{add,del}multi() functions should not. */ extern struct mtx in6_multi_mtx; #define IN6_MULTI_LOCK() mtx_lock(&in6_multi_mtx) #define IN6_MULTI_UNLOCK() mtx_unlock(&in6_multi_mtx) #define IN6_MULTI_LOCK_ASSERT() mtx_assert(&in6_multi_mtx, MA_OWNED) #define IN6_MULTI_UNLOCK_ASSERT() mtx_assert(&in6_multi_mtx, MA_NOTOWNED) /* * Look up an in6_multi record for an IPv6 multicast address * on the interface ifp. * If no record found, return NULL. * * SMPng: The IN6_MULTI_LOCK and IF_ADDR_LOCK on ifp must be held. */ static __inline struct in6_multi * in6m_lookup_locked(struct ifnet *ifp, const struct in6_addr *mcaddr) { struct ifmultiaddr *ifma; struct in6_multi *inm; IN6_MULTI_LOCK_ASSERT(); IF_ADDR_LOCK_ASSERT(ifp); inm = NULL; TAILQ_FOREACH(ifma, &((ifp)->if_multiaddrs), ifma_link) { if (ifma->ifma_addr->sa_family == AF_INET6) { inm = (struct in6_multi *)ifma->ifma_protospec; if (IN6_ARE_ADDR_EQUAL(&inm->in6m_addr, mcaddr)) break; inm = NULL; } } return (inm); } /* * Wrapper for in6m_lookup_locked(). * * SMPng: Assumes that neithr the IN6_MULTI_LOCK() or IF_ADDR_LOCK() are held. */ static __inline struct in6_multi * in6m_lookup(struct ifnet *ifp, const struct in6_addr *mcaddr) { struct in6_multi *inm; IN6_MULTI_LOCK(); IF_ADDR_RLOCK(ifp); inm = in6m_lookup_locked(ifp, mcaddr); IF_ADDR_RUNLOCK(ifp); IN6_MULTI_UNLOCK(); return (inm); } /* Acquire an in6_multi record. */ static __inline void in6m_acquire_locked(struct in6_multi *inm) { IN6_MULTI_LOCK_ASSERT(); ++inm->in6m_refcount; } struct ip6_moptions; struct sockopt; /* Multicast KPIs. */ int im6o_mc_filter(const struct ip6_moptions *, const struct ifnet *, const struct sockaddr *, const struct sockaddr *); int in6_mc_join(struct ifnet *, const struct in6_addr *, struct in6_mfilter *, struct in6_multi **, int); int in6_mc_join_locked(struct ifnet *, const struct in6_addr *, struct in6_mfilter *, struct in6_multi **, int); int in6_mc_leave(struct in6_multi *, struct in6_mfilter *); int in6_mc_leave_locked(struct in6_multi *, struct in6_mfilter *); void in6m_clear_recorded(struct in6_multi *); void in6m_commit(struct in6_multi *); void in6m_print(const struct in6_multi *); int in6m_record_source(struct in6_multi *, const struct in6_addr *); void in6m_release_locked(struct in6_multi *); void ip6_freemoptions(struct ip6_moptions *); int ip6_getmoptions(struct inpcb *, struct sockopt *); int ip6_setmoptions(struct inpcb *, struct sockopt *); /* Legacy KAME multicast KPIs. */ struct in6_multi_mship * in6_joingroup(struct ifnet *, struct in6_addr *, int *, int); int in6_leavegroup(struct in6_multi_mship *); /* flags to in6_update_ifa */ #define IN6_IFAUPDATE_DADDELAY 0x1 /* first time to configure an address */ int in6_mask2len(struct in6_addr *, u_char *); int in6_control(struct socket *, u_long, caddr_t, struct ifnet *, struct thread *); int in6_update_ifa(struct ifnet *, struct in6_aliasreq *, struct in6_ifaddr *, int); void in6_prepare_ifra(struct in6_aliasreq *, const struct in6_addr *, const struct in6_addr *); void in6_purgeaddr(struct ifaddr *); int in6if_do_dad(struct ifnet *); void in6_savemkludge(struct in6_ifaddr *); void *in6_domifattach(struct ifnet *); void in6_domifdetach(struct ifnet *, void *); int in6_domifmtu(struct ifnet *); void in6_setmaxmtu(void); int in6_if2idlen(struct ifnet *); struct in6_ifaddr *in6ifa_ifpforlinklocal(struct ifnet *, int); struct in6_ifaddr *in6ifa_ifpwithaddr(struct ifnet *, const struct in6_addr *); struct in6_ifaddr *in6ifa_ifwithaddr(const struct in6_addr *, uint32_t); struct in6_ifaddr *in6ifa_llaonifp(struct ifnet *); int in6_addr2zoneid(struct ifnet *, struct in6_addr *, u_int32_t *); int in6_matchlen(struct in6_addr *, struct in6_addr *); int in6_are_prefix_equal(struct in6_addr *, struct in6_addr *, int); void in6_prefixlen2mask(struct in6_addr *, int); int in6_prefix_ioctl(struct socket *, u_long, caddr_t, struct ifnet *); int in6_prefix_add_ifid(int, struct in6_ifaddr *); void in6_prefix_remove_ifid(int, struct in6_ifaddr *); void in6_purgeprefix(struct ifnet *); int in6_is_addr_deprecated(struct sockaddr_in6 *); int in6_src_ioctl(u_long, caddr_t); void in6_newaddrmsg(struct in6_ifaddr *, int); /* * Extended API for IPv6 FIB support. */ void in6_rtredirect(struct sockaddr *, struct sockaddr *, struct sockaddr *, int, struct sockaddr *, u_int); int in6_rtrequest(int, struct sockaddr *, struct sockaddr *, struct sockaddr *, int, struct rtentry **, u_int); void in6_rtalloc(struct route_in6 *, u_int); void in6_rtalloc_ign(struct route_in6 *, u_long, u_int); struct rtentry *in6_rtalloc1(struct sockaddr *, int, u_long, u_int); #endif /* _KERNEL */ #endif /* _NETINET6_IN6_VAR_H_ */ Index: user/alc/PQ_LAUNDRY/sys/netinet6/nd6.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/netinet6/nd6.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/netinet6/nd6.c (revision 292449) @@ -1,2593 +1,2569 @@ /*- * 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. * * $KAME: nd6.c,v 1.144 2001/05/24 07:44:00 itojun Exp $ */ #include __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" #include #include #include -#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ND6_SLOWTIMER_INTERVAL (60 * 60) /* 1 hour */ #define ND6_RECALC_REACHTM_INTERVAL (60 * 120) /* 2 hours */ #define SIN6(s) ((const struct sockaddr_in6 *)(s)) /* timer values */ VNET_DEFINE(int, nd6_prune) = 1; /* walk list every 1 seconds */ VNET_DEFINE(int, nd6_delay) = 5; /* delay first probe time 5 second */ VNET_DEFINE(int, nd6_umaxtries) = 3; /* maximum unicast query */ VNET_DEFINE(int, nd6_mmaxtries) = 3; /* maximum multicast query */ VNET_DEFINE(int, nd6_useloopback) = 1; /* use loopback interface for * local traffic */ VNET_DEFINE(int, nd6_gctimer) = (60 * 60 * 24); /* 1 day: garbage * collection timer */ /* preventing too many loops in ND option parsing */ static VNET_DEFINE(int, nd6_maxndopt) = 10; /* max # of ND options allowed */ VNET_DEFINE(int, nd6_maxnudhint) = 0; /* max # of subsequent upper * layer hints */ static VNET_DEFINE(int, nd6_maxqueuelen) = 1; /* max pkts cached in unresolved * ND entries */ - -static VNET_DEFINE(int, nd6_on_link) = 1; /* Send unsolicited ND's on link up */ - #define V_nd6_maxndopt VNET(nd6_maxndopt) #define V_nd6_maxqueuelen VNET(nd6_maxqueuelen) -#define V_nd6_on_link VNET(nd6_on_link) #ifdef ND6_DEBUG VNET_DEFINE(int, nd6_debug) = 1; #else VNET_DEFINE(int, nd6_debug) = 0; #endif static eventhandler_tag lle_event_eh; -static eventhandler_tag ifnet_link_event_eh; /* for debugging? */ #if 0 static int nd6_inuse, nd6_allocated; #endif VNET_DEFINE(struct nd_drhead, nd_defrouter); VNET_DEFINE(struct nd_prhead, nd_prefix); VNET_DEFINE(int, nd6_recalc_reachtm_interval) = ND6_RECALC_REACHTM_INTERVAL; #define V_nd6_recalc_reachtm_interval VNET(nd6_recalc_reachtm_interval) int (*send_sendso_input_hook)(struct mbuf *, struct ifnet *, int, int); static int nd6_is_new_addr_neighbor(const struct sockaddr_in6 *, struct ifnet *); static void nd6_setmtu0(struct ifnet *, struct nd_ifinfo *); static void nd6_slowtimo(void *); static int regen_tmpaddr(struct in6_ifaddr *); static void nd6_free(struct llentry *, int); static void nd6_free_redirect(const struct llentry *); static void nd6_llinfo_timer(void *); static void nd6_llinfo_settimer_locked(struct llentry *, long); static void clear_llinfo_pqueue(struct llentry *); static void nd6_rtrequest(int, struct rtentry *, struct rt_addrinfo *); static int nd6_resolve_slow(struct ifnet *, struct mbuf *, const struct sockaddr_in6 *, u_char *, uint32_t *); static int nd6_need_cache(struct ifnet *); static VNET_DEFINE(struct callout, nd6_slowtimo_ch); #define V_nd6_slowtimo_ch VNET(nd6_slowtimo_ch) VNET_DEFINE(struct callout, nd6_timer_ch); static void nd6_lle_event(void *arg __unused, struct llentry *lle, int evt) { struct rt_addrinfo rtinfo; struct sockaddr_in6 dst; struct sockaddr_dl gw; struct ifnet *ifp; int type; LLE_WLOCK_ASSERT(lle); if (lltable_get_af(lle->lle_tbl) != AF_INET6) return; switch (evt) { case LLENTRY_RESOLVED: type = RTM_ADD; KASSERT(lle->la_flags & LLE_VALID, ("%s: %p resolved but not valid?", __func__, lle)); break; case LLENTRY_EXPIRED: type = RTM_DELETE; break; default: return; } ifp = lltable_get_ifp(lle->lle_tbl); bzero(&dst, sizeof(dst)); bzero(&gw, sizeof(gw)); bzero(&rtinfo, sizeof(rtinfo)); lltable_fill_sa_entry(lle, (struct sockaddr *)&dst); dst.sin6_scope_id = in6_getscopezone(ifp, in6_addrscope(&dst.sin6_addr)); gw.sdl_len = sizeof(struct sockaddr_dl); gw.sdl_family = AF_LINK; gw.sdl_alen = ifp->if_addrlen; gw.sdl_index = ifp->if_index; gw.sdl_type = ifp->if_type; if (evt == LLENTRY_RESOLVED) bcopy(&lle->ll_addr, gw.sdl_data, ifp->if_addrlen); rtinfo.rti_info[RTAX_DST] = (struct sockaddr *)&dst; rtinfo.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&gw; rtinfo.rti_addrs = RTA_DST | RTA_GATEWAY; rt_missmsg_fib(type, &rtinfo, RTF_HOST | RTF_LLDATA | ( type == RTM_ADD ? RTF_UP: 0), 0, RT_DEFAULT_FIB); } -static void -nd6_ifnet_link_event(void *arg __unused, struct ifnet *ifp, int linkstate) -{ - - if (linkstate == LINK_STATE_UP && V_nd6_on_link) - nd6_na_output_unsolicited(ifp); -} - void nd6_init(void) { LIST_INIT(&V_nd_prefix); /* initialization of the default router list */ TAILQ_INIT(&V_nd_defrouter); /* start timer */ callout_init(&V_nd6_slowtimo_ch, 0); callout_reset(&V_nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz, nd6_slowtimo, curvnet); nd6_dad_init(); - if (IS_DEFAULT_VNET(curvnet)) { + if (IS_DEFAULT_VNET(curvnet)) lle_event_eh = EVENTHANDLER_REGISTER(lle_event, nd6_lle_event, NULL, EVENTHANDLER_PRI_ANY); - ifnet_link_event_eh = EVENTHANDLER_REGISTER(ifnet_link_event, - nd6_ifnet_link_event, NULL, EVENTHANDLER_PRI_ANY); - } } #ifdef VIMAGE void nd6_destroy() { callout_drain(&V_nd6_slowtimo_ch); callout_drain(&V_nd6_timer_ch); - if (IS_DEFAULT_VNET(curvnet)) { + if (IS_DEFAULT_VNET(curvnet)) EVENTHANDLER_DEREGISTER(lle_event, lle_event_eh); - EVENTHANDLER_DEREGISTER(ifnet_link_event, ifnet_link_event_eh); - } } #endif struct nd_ifinfo * nd6_ifattach(struct ifnet *ifp) { struct nd_ifinfo *nd; nd = (struct nd_ifinfo *)malloc(sizeof(*nd), M_IP6NDP, M_WAITOK|M_ZERO); nd->initialized = 1; nd->chlim = IPV6_DEFHLIM; nd->basereachable = REACHABLE_TIME; nd->reachable = ND_COMPUTE_RTIME(nd->basereachable); nd->retrans = RETRANS_TIMER; nd->flags = ND6_IFF_PERFORMNUD; /* A loopback interface always has ND6_IFF_AUTO_LINKLOCAL. * XXXHRS: Clear ND6_IFF_AUTO_LINKLOCAL on an IFT_BRIDGE interface by * default regardless of the V_ip6_auto_linklocal configuration to * give a reasonable default behavior. */ if ((V_ip6_auto_linklocal && ifp->if_type != IFT_BRIDGE) || (ifp->if_flags & IFF_LOOPBACK)) nd->flags |= ND6_IFF_AUTO_LINKLOCAL; /* * A loopback interface does not need to accept RTADV. * XXXHRS: Clear ND6_IFF_ACCEPT_RTADV on an IFT_BRIDGE interface by * default regardless of the V_ip6_accept_rtadv configuration to * prevent the interface from accepting RA messages arrived * on one of the member interfaces with ND6_IFF_ACCEPT_RTADV. */ if (V_ip6_accept_rtadv && !(ifp->if_flags & IFF_LOOPBACK) && (ifp->if_type != IFT_BRIDGE)) nd->flags |= ND6_IFF_ACCEPT_RTADV; if (V_ip6_no_radr && !(ifp->if_flags & IFF_LOOPBACK)) nd->flags |= ND6_IFF_NO_RADR; /* XXX: we cannot call nd6_setmtu since ifp is not fully initialized */ nd6_setmtu0(ifp, nd); return nd; } void nd6_ifdetach(struct nd_ifinfo *nd) { free(nd, M_IP6NDP); } /* * Reset ND level link MTU. This function is called when the physical MTU * changes, which means we might have to adjust the ND level MTU. */ void nd6_setmtu(struct ifnet *ifp) { if (ifp->if_afdata[AF_INET6] == NULL) return; nd6_setmtu0(ifp, ND_IFINFO(ifp)); } /* XXX todo: do not maintain copy of ifp->if_mtu in ndi->maxmtu */ void nd6_setmtu0(struct ifnet *ifp, struct nd_ifinfo *ndi) { u_int32_t omaxmtu; omaxmtu = ndi->maxmtu; switch (ifp->if_type) { case IFT_ARCNET: ndi->maxmtu = MIN(ARC_PHDS_MAXMTU, ifp->if_mtu); /* RFC2497 */ break; case IFT_FDDI: ndi->maxmtu = MIN(FDDIIPMTU, ifp->if_mtu); /* RFC2467 */ break; case IFT_ISO88025: ndi->maxmtu = MIN(ISO88025_MAX_MTU, ifp->if_mtu); break; default: ndi->maxmtu = ifp->if_mtu; break; } /* * Decreasing the interface MTU under IPV6 minimum MTU may cause * undesirable situation. We thus notify the operator of the change * explicitly. The check for omaxmtu is necessary to restrict the * log to the case of changing the MTU, not initializing it. */ if (omaxmtu >= IPV6_MMTU && ndi->maxmtu < IPV6_MMTU) { log(LOG_NOTICE, "nd6_setmtu0: " "new link MTU on %s (%lu) is too small for IPv6\n", if_name(ifp), (unsigned long)ndi->maxmtu); } if (ndi->maxmtu > V_in6_maxmtu) in6_setmaxmtu(); /* check all interfaces just in case */ } void nd6_option_init(void *opt, int icmp6len, union nd_opts *ndopts) { bzero(ndopts, sizeof(*ndopts)); ndopts->nd_opts_search = (struct nd_opt_hdr *)opt; ndopts->nd_opts_last = (struct nd_opt_hdr *)(((u_char *)opt) + icmp6len); if (icmp6len == 0) { ndopts->nd_opts_done = 1; ndopts->nd_opts_search = NULL; } } /* * Take one ND option. */ struct nd_opt_hdr * nd6_option(union nd_opts *ndopts) { struct nd_opt_hdr *nd_opt; int olen; KASSERT(ndopts != NULL, ("%s: ndopts == NULL", __func__)); KASSERT(ndopts->nd_opts_last != NULL, ("%s: uninitialized ndopts", __func__)); if (ndopts->nd_opts_search == NULL) return NULL; if (ndopts->nd_opts_done) return NULL; nd_opt = ndopts->nd_opts_search; /* make sure nd_opt_len is inside the buffer */ if ((caddr_t)&nd_opt->nd_opt_len >= (caddr_t)ndopts->nd_opts_last) { bzero(ndopts, sizeof(*ndopts)); return NULL; } olen = nd_opt->nd_opt_len << 3; if (olen == 0) { /* * Message validation requires that all included * options have a length that is greater than zero. */ bzero(ndopts, sizeof(*ndopts)); return NULL; } ndopts->nd_opts_search = (struct nd_opt_hdr *)((caddr_t)nd_opt + olen); if (ndopts->nd_opts_search > ndopts->nd_opts_last) { /* option overruns the end of buffer, invalid */ bzero(ndopts, sizeof(*ndopts)); return NULL; } else if (ndopts->nd_opts_search == ndopts->nd_opts_last) { /* reached the end of options chain */ ndopts->nd_opts_done = 1; ndopts->nd_opts_search = NULL; } return nd_opt; } /* * Parse multiple ND options. * This function is much easier to use, for ND routines that do not need * multiple options of the same type. */ int nd6_options(union nd_opts *ndopts) { struct nd_opt_hdr *nd_opt; int i = 0; KASSERT(ndopts != NULL, ("%s: ndopts == NULL", __func__)); KASSERT(ndopts->nd_opts_last != NULL, ("%s: uninitialized ndopts", __func__)); if (ndopts->nd_opts_search == NULL) return 0; while (1) { nd_opt = nd6_option(ndopts); if (nd_opt == NULL && ndopts->nd_opts_last == NULL) { /* * Message validation requires that all included * options have a length that is greater than zero. */ ICMP6STAT_INC(icp6s_nd_badopt); bzero(ndopts, sizeof(*ndopts)); return -1; } if (nd_opt == NULL) goto skip1; switch (nd_opt->nd_opt_type) { case ND_OPT_SOURCE_LINKADDR: case ND_OPT_TARGET_LINKADDR: case ND_OPT_MTU: case ND_OPT_REDIRECTED_HEADER: case ND_OPT_NONCE: if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) { nd6log((LOG_INFO, "duplicated ND6 option found (type=%d)\n", nd_opt->nd_opt_type)); /* XXX bark? */ } else { ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt; } break; case ND_OPT_PREFIX_INFORMATION: if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0) { ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt; } ndopts->nd_opts_pi_end = (struct nd_opt_prefix_info *)nd_opt; break; /* What about ND_OPT_ROUTE_INFO? RFC 4191 */ case ND_OPT_RDNSS: /* RFC 6106 */ case ND_OPT_DNSSL: /* RFC 6106 */ /* * Silently ignore options we know and do not care about * in the kernel. */ break; default: /* * Unknown options must be silently ignored, * to accomodate future extension to the protocol. */ nd6log((LOG_DEBUG, "nd6_options: unsupported option %d - " "option ignored\n", nd_opt->nd_opt_type)); } skip1: i++; if (i > V_nd6_maxndopt) { ICMP6STAT_INC(icp6s_nd_toomanyopt); nd6log((LOG_INFO, "too many loop in nd opt\n")); break; } if (ndopts->nd_opts_done) break; } return 0; } /* * ND6 timer routine to handle ND6 entries */ static void nd6_llinfo_settimer_locked(struct llentry *ln, long tick) { int canceled; LLE_WLOCK_ASSERT(ln); if (tick < 0) { ln->la_expire = 0; ln->ln_ntick = 0; canceled = callout_stop(&ln->lle_timer); } else { ln->la_expire = time_uptime + tick / hz; LLE_ADDREF(ln); if (tick > INT_MAX) { ln->ln_ntick = tick - INT_MAX; canceled = callout_reset(&ln->lle_timer, INT_MAX, nd6_llinfo_timer, ln); } else { ln->ln_ntick = 0; canceled = callout_reset(&ln->lle_timer, tick, nd6_llinfo_timer, ln); } } if (canceled > 0) LLE_REMREF(ln); } /* * Gets source address of the first packet in hold queue * and stores it in @src. * Returns pointer to @src (if hold queue is not empty) or NULL. * * Set noinline to be dtrace-friendly */ static __noinline struct in6_addr * nd6_llinfo_get_holdsrc(struct llentry *ln, struct in6_addr *src) { struct ip6_hdr hdr; struct mbuf *m; if (ln->la_hold == NULL) return (NULL); /* * assume every packet in la_hold has the same IP header */ m = ln->la_hold; if (sizeof(hdr) > m->m_len) return (NULL); m_copydata(m, 0, sizeof(hdr), (caddr_t)&hdr); *src = hdr.ip6_src; return (src); } /* * Checks if we need to switch from STALE state. * * RFC 4861 requires switching from STALE to DELAY state * on first packet matching entry, waiting V_nd6_delay and * transition to PROBE state (if upper layer confirmation was * not received). * * This code performs a bit differently: * On packet hit we don't change state (but desired state * can be guessed by control plane). However, after V_nd6_delay * seconds code will transition to PROBE state (so DELAY state * is kinda skipped in most situations). * * Typically, V_nd6_gctimer is bigger than V_nd6_delay, so * we perform the following upon entering STALE state: * * 1) Arm timer to run each V_nd6_delay seconds to make sure that * if packet was transmitted at the start of given interval, we * would be able to switch to PROBE state in V_nd6_delay seconds * as user expects. * * 2) Reschedule timer until original V_nd6_gctimer expires keeping * lle in STALE state (remaining timer value stored in lle_remtime). * * 3) Reschedule timer if packet was transmitted less that V_nd6_delay * seconds ago. * * Returns non-zero value if the entry is still STALE (storing * the next timer interval in @pdelay). * * Returns zero value if original timer expired or we need to switch to * PROBE (store that in @do_switch variable). */ static int nd6_is_stale(struct llentry *lle, long *pdelay, int *do_switch) { int nd_delay, nd_gctimer, r_skip_req; time_t lle_hittime; long delay; *do_switch = 0; nd_gctimer = V_nd6_gctimer; nd_delay = V_nd6_delay; LLE_REQ_LOCK(lle); r_skip_req = lle->r_skip_req; lle_hittime = lle->lle_hittime; LLE_REQ_UNLOCK(lle); if (r_skip_req > 0) { /* * Nonzero r_skip_req value was set upon entering * STALE state. Since value was not changed, no * packets were passed using this lle. Ask for * timer reschedule and keep STALE state. */ delay = (long)(MIN(nd_gctimer, nd_delay)); delay *= hz; if (lle->lle_remtime > delay) lle->lle_remtime -= delay; else { delay = lle->lle_remtime; lle->lle_remtime = 0; } if (delay == 0) { /* * The original ng6_gctime timeout ended, * no more rescheduling. */ return (0); } *pdelay = delay; return (1); } /* * Packet received. Verify timestamp */ delay = (long)(time_uptime - lle_hittime); if (delay < nd_delay) { /* * V_nd6_delay still not passed since the first * hit in STALE state. * Reshedule timer and return. */ *pdelay = (long)(nd_delay - delay) * hz; return (1); } /* Request switching to probe */ *do_switch = 1; return (0); } /* * Switch @lle state to new state optionally arming timers. * * Set noinline to be dtrace-friendly */ __noinline void nd6_llinfo_setstate(struct llentry *lle, int newstate) { struct ifnet *ifp; int nd_gctimer, nd_delay; long delay, remtime; delay = 0; remtime = 0; switch (newstate) { case ND6_LLINFO_INCOMPLETE: ifp = lle->lle_tbl->llt_ifp; delay = (long)ND_IFINFO(ifp)->retrans * hz / 1000; break; case ND6_LLINFO_REACHABLE: if (!ND6_LLINFO_PERMANENT(lle)) { ifp = lle->lle_tbl->llt_ifp; delay = (long)ND_IFINFO(ifp)->reachable * hz; } break; case ND6_LLINFO_STALE: /* * Notify fast path that we want to know if any packet * is transmitted by setting r_skip_req. */ LLE_REQ_LOCK(lle); lle->r_skip_req = 1; LLE_REQ_UNLOCK(lle); nd_delay = V_nd6_delay; nd_gctimer = V_nd6_gctimer; delay = (long)(MIN(nd_gctimer, nd_delay)) * hz; remtime = (long)nd_gctimer * hz - delay; break; case ND6_LLINFO_DELAY: lle->la_asked = 0; delay = (long)V_nd6_delay * hz; break; } if (delay > 0) nd6_llinfo_settimer_locked(lle, delay); lle->lle_remtime = remtime; lle->ln_state = newstate; } /* * Timer-dependent part of nd state machine. * * Set noinline to be dtrace-friendly */ static __noinline void nd6_llinfo_timer(void *arg) { struct llentry *ln; struct in6_addr *dst, *pdst, *psrc, src; struct ifnet *ifp; struct nd_ifinfo *ndi = NULL; int do_switch, send_ns; long delay; KASSERT(arg != NULL, ("%s: arg NULL", __func__)); ln = (struct llentry *)arg; LLE_WLOCK(ln); if (callout_pending(&ln->lle_timer)) { /* * Here we are a bit odd here in the treatment of * active/pending. If the pending bit is set, it got * rescheduled before I ran. The active * bit we ignore, since if it was stopped * in ll_tablefree() and was currently running * it would have return 0 so the code would * not have deleted it since the callout could * not be stopped so we want to go through * with the delete here now. If the callout * was restarted, the pending bit will be back on and * we just want to bail since the callout_reset would * return 1 and our reference would have been removed * by nd6_llinfo_settimer_locked above since canceled * would have been 1. */ LLE_WUNLOCK(ln); return; } ifp = ln->lle_tbl->llt_ifp; CURVNET_SET(ifp->if_vnet); ndi = ND_IFINFO(ifp); send_ns = 0; dst = &ln->r_l3addr.addr6; pdst = dst; if (ln->ln_ntick > 0) { if (ln->ln_ntick > INT_MAX) { ln->ln_ntick -= INT_MAX; nd6_llinfo_settimer_locked(ln, INT_MAX); } else { ln->ln_ntick = 0; nd6_llinfo_settimer_locked(ln, ln->ln_ntick); } goto done; } if (ln->la_flags & LLE_STATIC) { goto done; } if (ln->la_flags & LLE_DELETED) { nd6_free(ln, 0); ln = NULL; goto done; } switch (ln->ln_state) { case ND6_LLINFO_INCOMPLETE: if (ln->la_asked < V_nd6_mmaxtries) { ln->la_asked++; send_ns = 1; /* Send NS to multicast address */ pdst = NULL; } else { struct mbuf *m = ln->la_hold; if (m) { struct mbuf *m0; /* * assuming every packet in la_hold has the * same IP header. Send error after unlock. */ m0 = m->m_nextpkt; m->m_nextpkt = NULL; ln->la_hold = m0; clear_llinfo_pqueue(ln); } EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_TIMEDOUT); nd6_free(ln, 0); ln = NULL; if (m != NULL) icmp6_error2(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR, 0, ifp); } break; case ND6_LLINFO_REACHABLE: if (!ND6_LLINFO_PERMANENT(ln)) nd6_llinfo_setstate(ln, ND6_LLINFO_STALE); break; case ND6_LLINFO_STALE: if (nd6_is_stale(ln, &delay, &do_switch) != 0) { /* * No packet has used this entry and GC timeout * has not been passed. Reshedule timer and * return. */ nd6_llinfo_settimer_locked(ln, delay); break; } if (do_switch == 0) { /* * GC timer has ended and entry hasn't been used. * Run Garbage collector (RFC 4861, 5.3) */ if (!ND6_LLINFO_PERMANENT(ln)) { EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_EXPIRED); nd6_free(ln, 1); ln = NULL; } break; } /* Entry has been used AND delay timer has ended. */ /* FALLTHROUGH */ case ND6_LLINFO_DELAY: if (ndi && (ndi->flags & ND6_IFF_PERFORMNUD) != 0) { /* We need NUD */ ln->la_asked = 1; nd6_llinfo_setstate(ln, ND6_LLINFO_PROBE); send_ns = 1; } else nd6_llinfo_setstate(ln, ND6_LLINFO_STALE); /* XXX */ break; case ND6_LLINFO_PROBE: if (ln->la_asked < V_nd6_umaxtries) { ln->la_asked++; send_ns = 1; } else { EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_EXPIRED); nd6_free(ln, 0); ln = NULL; } break; default: panic("%s: paths in a dark night can be confusing: %d", __func__, ln->ln_state); } done: if (send_ns != 0) { nd6_llinfo_settimer_locked(ln, (long)ndi->retrans * hz / 1000); psrc = nd6_llinfo_get_holdsrc(ln, &src); LLE_FREE_LOCKED(ln); ln = NULL; nd6_ns_output(ifp, psrc, pdst, dst, NULL); } if (ln != NULL) LLE_FREE_LOCKED(ln); CURVNET_RESTORE(); } /* * ND6 timer routine to expire default route list and prefix list */ void nd6_timer(void *arg) { CURVNET_SET((struct vnet *) arg); struct nd_defrouter *dr, *ndr; struct nd_prefix *pr, *npr; struct in6_ifaddr *ia6, *nia6; callout_reset(&V_nd6_timer_ch, V_nd6_prune * hz, nd6_timer, curvnet); /* expire default router list */ TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) { if (dr->expire && dr->expire < time_uptime) defrtrlist_del(dr); } /* * expire interface addresses. * in the past the loop was inside prefix expiry processing. * However, from a stricter speci-confrmance standpoint, we should * rather separate address lifetimes and prefix lifetimes. * * XXXRW: in6_ifaddrhead locking. */ addrloop: TAILQ_FOREACH_SAFE(ia6, &V_in6_ifaddrhead, ia_link, nia6) { /* check address lifetime */ if (IFA6_IS_INVALID(ia6)) { int regen = 0; /* * If the expiring address is temporary, try * regenerating a new one. This would be useful when * we suspended a laptop PC, then turned it on after a * period that could invalidate all temporary * addresses. Although we may have to restart the * loop (see below), it must be after purging the * address. Otherwise, we'd see an infinite loop of * regeneration. */ if (V_ip6_use_tempaddr && (ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0) { if (regen_tmpaddr(ia6) == 0) regen = 1; } in6_purgeaddr(&ia6->ia_ifa); if (regen) goto addrloop; /* XXX: see below */ } else if (IFA6_IS_DEPRECATED(ia6)) { int oldflags = ia6->ia6_flags; ia6->ia6_flags |= IN6_IFF_DEPRECATED; /* * If a temporary address has just become deprecated, * regenerate a new one if possible. */ if (V_ip6_use_tempaddr && (ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0 && (oldflags & IN6_IFF_DEPRECATED) == 0) { if (regen_tmpaddr(ia6) == 0) { /* * A new temporary address is * generated. * XXX: this means the address chain * has changed while we are still in * the loop. Although the change * would not cause disaster (because * it's not a deletion, but an * addition,) we'd rather restart the * loop just for safety. Or does this * significantly reduce performance?? */ goto addrloop; } } } else if ((ia6->ia6_flags & IN6_IFF_TENTATIVE) != 0) { /* * Schedule DAD for a tentative address. This happens * if the interface was down or not running * when the address was configured. */ int delay; delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz); nd6_dad_start((struct ifaddr *)ia6, delay); } else { /* * Check status of the interface. If it is down, * mark the address as tentative for future DAD. */ if ((ia6->ia_ifp->if_flags & IFF_UP) == 0 || (ia6->ia_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || (ND_IFINFO(ia6->ia_ifp)->flags & ND6_IFF_IFDISABLED) != 0) { ia6->ia6_flags &= ~IN6_IFF_DUPLICATED; ia6->ia6_flags |= IN6_IFF_TENTATIVE; } /* * A new RA might have made a deprecated address * preferred. */ ia6->ia6_flags &= ~IN6_IFF_DEPRECATED; } } /* expire prefix list */ LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, npr) { /* * check prefix lifetime. * since pltime is just for autoconf, pltime processing for * prefix is not necessary. */ if (pr->ndpr_vltime != ND6_INFINITE_LIFETIME && time_uptime - pr->ndpr_lastupdate > pr->ndpr_vltime) { /* * address expiration and prefix expiration are * separate. NEVER perform in6_purgeaddr here. */ prelist_remove(pr); } } CURVNET_RESTORE(); } /* * ia6 - deprecated/invalidated temporary address */ static int regen_tmpaddr(struct in6_ifaddr *ia6) { struct ifaddr *ifa; struct ifnet *ifp; struct in6_ifaddr *public_ifa6 = NULL; ifp = ia6->ia_ifa.ifa_ifp; IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { struct in6_ifaddr *it6; if (ifa->ifa_addr->sa_family != AF_INET6) continue; it6 = (struct in6_ifaddr *)ifa; /* ignore no autoconf addresses. */ if ((it6->ia6_flags & IN6_IFF_AUTOCONF) == 0) continue; /* ignore autoconf addresses with different prefixes. */ if (it6->ia6_ndpr == NULL || it6->ia6_ndpr != ia6->ia6_ndpr) continue; /* * Now we are looking at an autoconf address with the same * prefix as ours. If the address is temporary and is still * preferred, do not create another one. It would be rare, but * could happen, for example, when we resume a laptop PC after * a long period. */ if ((it6->ia6_flags & IN6_IFF_TEMPORARY) != 0 && !IFA6_IS_DEPRECATED(it6)) { public_ifa6 = NULL; break; } /* * This is a public autoconf address that has the same prefix * as ours. If it is preferred, keep it. We can't break the * loop here, because there may be a still-preferred temporary * address with the prefix. */ if (!IFA6_IS_DEPRECATED(it6)) public_ifa6 = it6; } if (public_ifa6 != NULL) ifa_ref(&public_ifa6->ia_ifa); IF_ADDR_RUNLOCK(ifp); if (public_ifa6 != NULL) { int e; if ((e = in6_tmpifadd(public_ifa6, 0, 0)) != 0) { ifa_free(&public_ifa6->ia_ifa); log(LOG_NOTICE, "regen_tmpaddr: failed to create a new" " tmp addr,errno=%d\n", e); return (-1); } ifa_free(&public_ifa6->ia_ifa); return (0); } return (-1); } /* * Nuke neighbor cache/prefix/default router management table, right before * ifp goes away. */ void nd6_purge(struct ifnet *ifp) { struct nd_defrouter *dr, *ndr; struct nd_prefix *pr, *npr; /* * Nuke default router list entries toward ifp. * We defer removal of default router list entries that is installed * in the routing table, in order to keep additional side effects as * small as possible. */ TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) { if (dr->installed) continue; if (dr->ifp == ifp) defrtrlist_del(dr); } TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) { if (!dr->installed) continue; if (dr->ifp == ifp) defrtrlist_del(dr); } /* Nuke prefix list entries toward ifp */ LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, npr) { if (pr->ndpr_ifp == ifp) { /* * Because if_detach() does *not* release prefixes * while purging addresses the reference count will * still be above zero. We therefore reset it to * make sure that the prefix really gets purged. */ pr->ndpr_refcnt = 0; /* * Previously, pr->ndpr_addr is removed as well, * but I strongly believe we don't have to do it. * nd6_purge() is only called from in6_ifdetach(), * which removes all the associated interface addresses * by itself. * (jinmei@kame.net 20010129) */ prelist_remove(pr); } } /* cancel default outgoing interface setting */ if (V_nd6_defifindex == ifp->if_index) nd6_setdefaultiface(0); if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) { /* Refresh default router list. */ defrouter_select(); } /* XXXXX * We do not nuke the neighbor cache entries here any more * because the neighbor cache is kept in if_afdata[AF_INET6]. * nd6_purge() is invoked by in6_ifdetach() which is called * from if_detach() where everything gets purged. So let * in6_domifdetach() do the actual L2 table purging work. */ } /* * the caller acquires and releases the lock on the lltbls * Returns the llentry locked */ struct llentry * nd6_lookup(const struct in6_addr *addr6, int flags, struct ifnet *ifp) { struct sockaddr_in6 sin6; struct llentry *ln; bzero(&sin6, sizeof(sin6)); sin6.sin6_len = sizeof(struct sockaddr_in6); sin6.sin6_family = AF_INET6; sin6.sin6_addr = *addr6; IF_AFDATA_LOCK_ASSERT(ifp); ln = lla_lookup(LLTABLE6(ifp), flags, (struct sockaddr *)&sin6); return (ln); } struct llentry * nd6_alloc(const struct in6_addr *addr6, int flags, struct ifnet *ifp) { struct sockaddr_in6 sin6; struct llentry *ln; bzero(&sin6, sizeof(sin6)); sin6.sin6_len = sizeof(struct sockaddr_in6); sin6.sin6_family = AF_INET6; sin6.sin6_addr = *addr6; ln = lltable_alloc_entry(LLTABLE6(ifp), 0, (struct sockaddr *)&sin6); if (ln != NULL) ln->ln_state = ND6_LLINFO_NOSTATE; return (ln); } /* * Test whether a given IPv6 address is a neighbor or not, ignoring * the actual neighbor cache. The neighbor cache is ignored in order * to not reenter the routing code from within itself. */ static int nd6_is_new_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp) { struct nd_prefix *pr; struct ifaddr *dstaddr; /* * A link-local address is always a neighbor. * XXX: a link does not necessarily specify a single interface. */ if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) { struct sockaddr_in6 sin6_copy; u_int32_t zone; /* * We need sin6_copy since sa6_recoverscope() may modify the * content (XXX). */ sin6_copy = *addr; if (sa6_recoverscope(&sin6_copy)) return (0); /* XXX: should be impossible */ if (in6_setscope(&sin6_copy.sin6_addr, ifp, &zone)) return (0); if (sin6_copy.sin6_scope_id == zone) return (1); else return (0); } /* * If the address matches one of our addresses, * it should be a neighbor. * If the address matches one of our on-link prefixes, it should be a * neighbor. */ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) { if (pr->ndpr_ifp != ifp) continue; if (!(pr->ndpr_stateflags & NDPRF_ONLINK)) { struct rtentry *rt; /* Always use the default FIB here. */ rt = in6_rtalloc1((struct sockaddr *)&pr->ndpr_prefix, 0, 0, RT_DEFAULT_FIB); if (rt == NULL) continue; /* * This is the case where multiple interfaces * have the same prefix, but only one is installed * into the routing table and that prefix entry * is not the one being examined here. In the case * where RADIX_MPATH is enabled, multiple route * entries (of the same rt_key value) will be * installed because the interface addresses all * differ. */ if (!IN6_ARE_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr, &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr)) { RTFREE_LOCKED(rt); continue; } RTFREE_LOCKED(rt); } if (IN6_ARE_MASKED_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr, &addr->sin6_addr, &pr->ndpr_mask)) return (1); } /* * If the address is assigned on the node of the other side of * a p2p interface, the address should be a neighbor. */ dstaddr = ifa_ifwithdstaddr((const struct sockaddr *)addr, RT_ALL_FIBS); if (dstaddr != NULL) { if (dstaddr->ifa_ifp == ifp) { ifa_free(dstaddr); return (1); } ifa_free(dstaddr); } /* * If the default router list is empty, all addresses are regarded * as on-link, and thus, as a neighbor. */ if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV && TAILQ_EMPTY(&V_nd_defrouter) && V_nd6_defifindex == ifp->if_index) { return (1); } return (0); } /* * Detect if a given IPv6 address identifies a neighbor on a given link. * XXX: should take care of the destination of a p2p link? */ int nd6_is_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp) { struct llentry *lle; int rc = 0; IF_AFDATA_UNLOCK_ASSERT(ifp); if (nd6_is_new_addr_neighbor(addr, ifp)) return (1); /* * Even if the address matches none of our addresses, it might be * in the neighbor cache. */ IF_AFDATA_RLOCK(ifp); if ((lle = nd6_lookup(&addr->sin6_addr, 0, ifp)) != NULL) { LLE_RUNLOCK(lle); rc = 1; } IF_AFDATA_RUNLOCK(ifp); return (rc); } /* * Free an nd6 llinfo entry. * Since the function would cause significant changes in the kernel, DO NOT * make it global, unless you have a strong reason for the change, and are sure * that the change is safe. * * Set noinline to be dtrace-friendly */ static __noinline void nd6_free(struct llentry *ln, int gc) { struct nd_defrouter *dr; struct ifnet *ifp; LLE_WLOCK_ASSERT(ln); /* * we used to have pfctlinput(PRC_HOSTDEAD) here. * even though it is not harmful, it was not really necessary. */ /* cancel timer */ nd6_llinfo_settimer_locked(ln, -1); ifp = ln->lle_tbl->llt_ifp; if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) { dr = defrouter_lookup(&ln->r_l3addr.addr6, ifp); if (dr != NULL && dr->expire && ln->ln_state == ND6_LLINFO_STALE && gc) { /* * If the reason for the deletion is just garbage * collection, and the neighbor is an active default * router, do not delete it. Instead, reset the GC * timer using the router's lifetime. * Simply deleting the entry would affect default * router selection, which is not necessarily a good * thing, especially when we're using router preference * values. * XXX: the check for ln_state would be redundant, * but we intentionally keep it just in case. */ if (dr->expire > time_uptime) nd6_llinfo_settimer_locked(ln, (dr->expire - time_uptime) * hz); else nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz); LLE_REMREF(ln); LLE_WUNLOCK(ln); return; } if (dr) { /* * Unreachablity of a router might affect the default * router selection and on-link detection of advertised * prefixes. */ /* * Temporarily fake the state to choose a new default * router and to perform on-link determination of * prefixes correctly. * Below the state will be set correctly, * or the entry itself will be deleted. */ ln->ln_state = ND6_LLINFO_INCOMPLETE; } if (ln->ln_router || dr) { /* * We need to unlock to avoid a LOR with rt6_flush() with the * rnh and for the calls to pfxlist_onlink_check() and * defrouter_select() in the block further down for calls * into nd6_lookup(). We still hold a ref. */ LLE_WUNLOCK(ln); /* * rt6_flush must be called whether or not the neighbor * is in the Default Router List. * See a corresponding comment in nd6_na_input(). */ rt6_flush(&ln->r_l3addr.addr6, ifp); } if (dr) { /* * Since defrouter_select() does not affect the * on-link determination and MIP6 needs the check * before the default router selection, we perform * the check now. */ pfxlist_onlink_check(); /* * Refresh default router list. */ defrouter_select(); } /* * If this entry was added by an on-link redirect, remove the * corresponding host route. */ if (ln->la_flags & LLE_REDIRECT) nd6_free_redirect(ln); if (ln->ln_router || dr) LLE_WLOCK(ln); } /* * Save to unlock. We still hold an extra reference and will not * free(9) in llentry_free() if someone else holds one as well. */ LLE_WUNLOCK(ln); IF_AFDATA_LOCK(ifp); LLE_WLOCK(ln); /* Guard against race with other llentry_free(). */ if (ln->la_flags & LLE_LINKED) { /* Remove callout reference */ LLE_REMREF(ln); lltable_unlink_entry(ln->lle_tbl, ln); } IF_AFDATA_UNLOCK(ifp); llentry_free(ln); } static int nd6_isdynrte(const struct rtentry *rt, void *xap) { if (rt->rt_flags == (RTF_UP | RTF_HOST | RTF_DYNAMIC)) return (1); return (0); } /* * Remove the rtentry for the given llentry, * both of which were installed by a redirect. */ static void nd6_free_redirect(const struct llentry *ln) { int fibnum; struct sockaddr_in6 sin6; struct rt_addrinfo info; lltable_fill_sa_entry(ln, (struct sockaddr *)&sin6); memset(&info, 0, sizeof(info)); info.rti_info[RTAX_DST] = (struct sockaddr *)&sin6; info.rti_filter = nd6_isdynrte; for (fibnum = 0; fibnum < rt_numfibs; fibnum++) rtrequest1_fib(RTM_DELETE, &info, NULL, fibnum); } /* * Rejuvenate this function for routing operations related * processing. */ void nd6_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info) { struct sockaddr_in6 *gateway; struct nd_defrouter *dr; struct ifnet *ifp; gateway = (struct sockaddr_in6 *)rt->rt_gateway; ifp = rt->rt_ifp; switch (req) { case RTM_ADD: break; case RTM_DELETE: if (!ifp) return; /* * Only indirect routes are interesting. */ if ((rt->rt_flags & RTF_GATEWAY) == 0) return; /* * check for default route */ if (IN6_ARE_ADDR_EQUAL(&in6addr_any, &SIN6(rt_key(rt))->sin6_addr)) { dr = defrouter_lookup(&gateway->sin6_addr, ifp); if (dr != NULL) dr->installed = 0; } break; } } int nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp) { struct in6_ndireq *ndi = (struct in6_ndireq *)data; struct in6_nbrinfo *nbi = (struct in6_nbrinfo *)data; struct in6_ndifreq *ndif = (struct in6_ndifreq *)data; int error = 0; if (ifp->if_afdata[AF_INET6] == NULL) return (EPFNOSUPPORT); switch (cmd) { case OSIOCGIFINFO_IN6: #define ND ndi->ndi /* XXX: old ndp(8) assumes a positive value for linkmtu. */ bzero(&ND, sizeof(ND)); ND.linkmtu = IN6_LINKMTU(ifp); ND.maxmtu = ND_IFINFO(ifp)->maxmtu; ND.basereachable = ND_IFINFO(ifp)->basereachable; ND.reachable = ND_IFINFO(ifp)->reachable; ND.retrans = ND_IFINFO(ifp)->retrans; ND.flags = ND_IFINFO(ifp)->flags; ND.recalctm = ND_IFINFO(ifp)->recalctm; ND.chlim = ND_IFINFO(ifp)->chlim; break; case SIOCGIFINFO_IN6: ND = *ND_IFINFO(ifp); break; case SIOCSIFINFO_IN6: /* * used to change host variables from userland. * intented for a use on router to reflect RA configurations. */ /* 0 means 'unspecified' */ if (ND.linkmtu != 0) { if (ND.linkmtu < IPV6_MMTU || ND.linkmtu > IN6_LINKMTU(ifp)) { error = EINVAL; break; } ND_IFINFO(ifp)->linkmtu = ND.linkmtu; } if (ND.basereachable != 0) { int obasereachable = ND_IFINFO(ifp)->basereachable; ND_IFINFO(ifp)->basereachable = ND.basereachable; if (ND.basereachable != obasereachable) ND_IFINFO(ifp)->reachable = ND_COMPUTE_RTIME(ND.basereachable); } if (ND.retrans != 0) ND_IFINFO(ifp)->retrans = ND.retrans; if (ND.chlim != 0) ND_IFINFO(ifp)->chlim = ND.chlim; /* FALLTHROUGH */ case SIOCSIFINFO_FLAGS: { struct ifaddr *ifa; struct in6_ifaddr *ia; if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) && !(ND.flags & ND6_IFF_IFDISABLED)) { /* ifdisabled 1->0 transision */ /* * If the interface is marked as ND6_IFF_IFDISABLED and * has an link-local address with IN6_IFF_DUPLICATED, * do not clear ND6_IFF_IFDISABLED. * See RFC 4862, Section 5.4.5. */ IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; ia = (struct in6_ifaddr *)ifa; if ((ia->ia6_flags & IN6_IFF_DUPLICATED) && IN6_IS_ADDR_LINKLOCAL(IA6_IN6(ia))) break; } IF_ADDR_RUNLOCK(ifp); if (ifa != NULL) { /* LLA is duplicated. */ ND.flags |= ND6_IFF_IFDISABLED; log(LOG_ERR, "Cannot enable an interface" " with a link-local address marked" " duplicate.\n"); } else { ND_IFINFO(ifp)->flags &= ~ND6_IFF_IFDISABLED; if (ifp->if_flags & IFF_UP) in6_if_up(ifp); } } else if (!(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) && (ND.flags & ND6_IFF_IFDISABLED)) { /* ifdisabled 0->1 transision */ /* Mark all IPv6 address as tentative. */ ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED; if (V_ip6_dad_count > 0 && (ND_IFINFO(ifp)->flags & ND6_IFF_NO_DAD) == 0) { IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; ia = (struct in6_ifaddr *)ifa; ia->ia6_flags |= IN6_IFF_TENTATIVE; } IF_ADDR_RUNLOCK(ifp); } } if (ND.flags & ND6_IFF_AUTO_LINKLOCAL) { if (!(ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL)) { /* auto_linklocal 0->1 transision */ /* If no link-local address on ifp, configure */ ND_IFINFO(ifp)->flags |= ND6_IFF_AUTO_LINKLOCAL; in6_ifattach(ifp, NULL); } else if (!(ND.flags & ND6_IFF_IFDISABLED) && ifp->if_flags & IFF_UP) { /* * When the IF already has * ND6_IFF_AUTO_LINKLOCAL, no link-local * address is assigned, and IFF_UP, try to * assign one. */ IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; ia = (struct in6_ifaddr *)ifa; if (IN6_IS_ADDR_LINKLOCAL(IA6_IN6(ia))) break; } IF_ADDR_RUNLOCK(ifp); if (ifa != NULL) /* No LLA is configured. */ in6_ifattach(ifp, NULL); } } } ND_IFINFO(ifp)->flags = ND.flags; break; #undef ND case SIOCSNDFLUSH_IN6: /* XXX: the ioctl name is confusing... */ /* sync kernel routing table with the default router list */ defrouter_reset(); defrouter_select(); break; case SIOCSPFXFLUSH_IN6: { /* flush all the prefix advertised by routers */ struct nd_prefix *pr, *next; LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, next) { struct in6_ifaddr *ia, *ia_next; if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr)) continue; /* XXX */ /* do we really have to remove addresses as well? */ /* XXXRW: in6_ifaddrhead locking. */ TAILQ_FOREACH_SAFE(ia, &V_in6_ifaddrhead, ia_link, ia_next) { if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0) continue; if (ia->ia6_ndpr == pr) in6_purgeaddr(&ia->ia_ifa); } prelist_remove(pr); } break; } case SIOCSRTRFLUSH_IN6: { /* flush all the default routers */ struct nd_defrouter *dr, *next; defrouter_reset(); TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, next) { defrtrlist_del(dr); } defrouter_select(); break; } case SIOCGNBRINFO_IN6: { struct llentry *ln; struct in6_addr nb_addr = nbi->addr; /* make local for safety */ if ((error = in6_setscope(&nb_addr, ifp, NULL)) != 0) return (error); IF_AFDATA_RLOCK(ifp); ln = nd6_lookup(&nb_addr, 0, ifp); IF_AFDATA_RUNLOCK(ifp); if (ln == NULL) { error = EINVAL; break; } nbi->state = ln->ln_state; nbi->asked = ln->la_asked; nbi->isrouter = ln->ln_router; if (ln->la_expire == 0) nbi->expire = 0; else nbi->expire = ln->la_expire + ln->lle_remtime / hz + (time_second - time_uptime); LLE_RUNLOCK(ln); break; } case SIOCGDEFIFACE_IN6: /* XXX: should be implemented as a sysctl? */ ndif->ifindex = V_nd6_defifindex; break; case SIOCSDEFIFACE_IN6: /* XXX: should be implemented as a sysctl? */ return (nd6_setdefaultiface(ndif->ifindex)); } return (error); } /* * Calculates new isRouter value based on provided parameters and * returns it. */ static int nd6_is_router(int type, int code, int is_new, int old_addr, int new_addr, int ln_router) { /* * ICMP6 type dependent behavior. * * NS: clear IsRouter if new entry * RS: clear IsRouter * RA: set IsRouter if there's lladdr * redir: clear IsRouter if new entry * * RA case, (1): * The spec says that we must set IsRouter in the following cases: * - If lladdr exist, set IsRouter. This means (1-5). * - If it is old entry (!newentry), set IsRouter. This means (7). * So, based on the spec, in (1-5) and (7) cases we must set IsRouter. * A quetion arises for (1) case. (1) case has no lladdr in the * neighbor cache, this is similar to (6). * This case is rare but we figured that we MUST NOT set IsRouter. * * is_new old_addr new_addr NS RS RA redir * D R * 0 n n (1) c ? s * 0 y n (2) c s s * 0 n y (3) c s s * 0 y y (4) c s s * 0 y y (5) c s s * 1 -- n (6) c c c s * 1 -- y (7) c c s c s * * (c=clear s=set) */ switch (type & 0xff) { case ND_NEIGHBOR_SOLICIT: /* * New entry must have is_router flag cleared. */ if (is_new) /* (6-7) */ ln_router = 0; break; case ND_REDIRECT: /* * If the icmp is a redirect to a better router, always set the * is_router flag. Otherwise, if the entry is newly created, * clear the flag. [RFC 2461, sec 8.3] */ if (code == ND_REDIRECT_ROUTER) ln_router = 1; else { if (is_new) /* (6-7) */ ln_router = 0; } break; case ND_ROUTER_SOLICIT: /* * is_router flag must always be cleared. */ ln_router = 0; break; case ND_ROUTER_ADVERT: /* * Mark an entry with lladdr as a router. */ if ((!is_new && (old_addr || new_addr)) || /* (2-5) */ (is_new && new_addr)) { /* (7) */ ln_router = 1; } break; } return (ln_router); } /* * Create neighbor cache entry and cache link-layer address, * on reception of inbound ND6 packets. (RS/RA/NS/redirect) * * type - ICMP6 type * code - type dependent information * */ void nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr, int lladdrlen, int type, int code) { struct llentry *ln = NULL, *ln_tmp; int is_newentry; int do_update; int olladdr; int llchange; int flags; uint16_t router = 0; struct sockaddr_in6 sin6; struct mbuf *chain = NULL; IF_AFDATA_UNLOCK_ASSERT(ifp); KASSERT(ifp != NULL, ("%s: ifp == NULL", __func__)); KASSERT(from != NULL, ("%s: from == NULL", __func__)); /* nothing must be updated for unspecified address */ if (IN6_IS_ADDR_UNSPECIFIED(from)) return; /* * Validation about ifp->if_addrlen and lladdrlen must be done in * the caller. * * XXX If the link does not have link-layer adderss, what should * we do? (ifp->if_addrlen == 0) * Spec says nothing in sections for RA, RS and NA. There's small * description on it in NS section (RFC 2461 7.2.3). */ flags = lladdr ? LLE_EXCLUSIVE : 0; IF_AFDATA_RLOCK(ifp); ln = nd6_lookup(from, flags, ifp); IF_AFDATA_RUNLOCK(ifp); is_newentry = 0; if (ln == NULL) { flags |= LLE_EXCLUSIVE; ln = nd6_alloc(from, 0, ifp); if (ln == NULL) return; /* * Since we already know all the data for the new entry, * fill it before insertion. */ if (lladdr != NULL) lltable_set_entry_addr(ifp, ln, lladdr); IF_AFDATA_WLOCK(ifp); LLE_WLOCK(ln); /* Prefer any existing lle over newly-created one */ ln_tmp = nd6_lookup(from, LLE_EXCLUSIVE, ifp); if (ln_tmp == NULL) lltable_link_entry(LLTABLE6(ifp), ln); IF_AFDATA_WUNLOCK(ifp); if (ln_tmp == NULL) { /* No existing lle, mark as new entry (6,7) */ is_newentry = 1; nd6_llinfo_setstate(ln, ND6_LLINFO_STALE); if (lladdr != NULL) /* (7) */ EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED); } else { lltable_free_entry(LLTABLE6(ifp), ln); ln = ln_tmp; ln_tmp = NULL; } } /* do nothing if static ndp is set */ if ((ln->la_flags & LLE_STATIC)) { if (flags & LLE_EXCLUSIVE) LLE_WUNLOCK(ln); else LLE_RUNLOCK(ln); return; } olladdr = (ln->la_flags & LLE_VALID) ? 1 : 0; if (olladdr && lladdr) { llchange = bcmp(lladdr, &ln->ll_addr, ifp->if_addrlen); } else if (!olladdr && lladdr) llchange = 1; else llchange = 0; /* * newentry olladdr lladdr llchange (*=record) * 0 n n -- (1) * 0 y n -- (2) * 0 n y y (3) * STALE * 0 y y n (4) * * 0 y y y (5) * STALE * 1 -- n -- (6) NOSTATE(= PASSIVE) * 1 -- y -- (7) * STALE */ do_update = 0; if (is_newentry == 0 && llchange != 0) { do_update = 1; /* (3,5) */ /* * Record source link-layer address * XXX is it dependent to ifp->if_type? */ if (lltable_try_set_entry_addr(ifp, ln, lladdr) == 0) { /* Entry was deleted */ return; } nd6_llinfo_setstate(ln, ND6_LLINFO_STALE); EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED); if (ln->la_hold != NULL) nd6_grab_holdchain(ln, &chain, &sin6); } /* Calculates new router status */ router = nd6_is_router(type, code, is_newentry, olladdr, lladdr != NULL ? 1 : 0, ln->ln_router); ln->ln_router = router; /* Mark non-router redirects with special flag */ if ((type & 0xFF) == ND_REDIRECT && code != ND_REDIRECT_ROUTER) ln->la_flags |= LLE_REDIRECT; if (flags & LLE_EXCLUSIVE) LLE_WUNLOCK(ln); else LLE_RUNLOCK(ln); if (chain != NULL) nd6_flush_holdchain(ifp, ifp, chain, &sin6); /* * When the link-layer address of a router changes, select the * best router again. In particular, when the neighbor entry is newly * created, it might affect the selection policy. * Question: can we restrict the first condition to the "is_newentry" * case? * XXX: when we hear an RA from a new router with the link-layer * address option, defrouter_select() is called twice, since * defrtrlist_update called the function as well. However, I believe * we can compromise the overhead, since it only happens the first * time. * XXX: although defrouter_select() should not have a bad effect * for those are not autoconfigured hosts, we explicitly avoid such * cases for safety. */ if ((do_update || is_newentry) && router && ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) { /* * guaranteed recursion */ defrouter_select(); } } static void nd6_slowtimo(void *arg) { CURVNET_SET((struct vnet *) arg); struct nd_ifinfo *nd6if; struct ifnet *ifp; callout_reset(&V_nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz, nd6_slowtimo, curvnet); IFNET_RLOCK_NOSLEEP(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { if (ifp->if_afdata[AF_INET6] == NULL) continue; nd6if = ND_IFINFO(ifp); if (nd6if->basereachable && /* already initialized */ (nd6if->recalctm -= ND6_SLOWTIMER_INTERVAL) <= 0) { /* * Since reachable time rarely changes by router * advertisements, we SHOULD insure that a new random * value gets recomputed at least once every few hours. * (RFC 2461, 6.3.4) */ nd6if->recalctm = V_nd6_recalc_reachtm_interval; nd6if->reachable = ND_COMPUTE_RTIME(nd6if->basereachable); } } IFNET_RUNLOCK_NOSLEEP(); CURVNET_RESTORE(); } void nd6_grab_holdchain(struct llentry *ln, struct mbuf **chain, struct sockaddr_in6 *sin6) { LLE_WLOCK_ASSERT(ln); *chain = ln->la_hold; ln->la_hold = NULL; lltable_fill_sa_entry(ln, (struct sockaddr *)sin6); if (ln->ln_state == ND6_LLINFO_STALE) { /* * The first time we send a packet to a * neighbor whose entry is STALE, we have * to change the state to DELAY and a sets * a timer to expire in DELAY_FIRST_PROBE_TIME * seconds to ensure do neighbor unreachability * detection on expiration. * (RFC 2461 7.3.3) */ nd6_llinfo_setstate(ln, ND6_LLINFO_DELAY); } } int nd6_output_ifp(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m, struct sockaddr_in6 *dst, struct route *ro) { int error; int ip6len; struct ip6_hdr *ip6; struct m_tag *mtag; #ifdef MAC mac_netinet6_nd6_send(ifp, m); #endif /* * If called from nd6_ns_output() (NS), nd6_na_output() (NA), * icmp6_redirect_output() (REDIRECT) or from rip6_output() (RS, RA * as handled by rtsol and rtadvd), mbufs will be tagged for SeND * to be diverted to user space. When re-injected into the kernel, * send_output() will directly dispatch them to the outgoing interface. */ if (send_sendso_input_hook != NULL) { mtag = m_tag_find(m, PACKET_TAG_ND_OUTGOING, NULL); if (mtag != NULL) { ip6 = mtod(m, struct ip6_hdr *); ip6len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen); /* Use the SEND socket */ error = send_sendso_input_hook(m, ifp, SND_OUT, ip6len); /* -1 == no app on SEND socket */ if (error == 0 || error != -1) return (error); } } m_clrprotoflags(m); /* Avoid confusing lower layers. */ IP_PROBE(send, NULL, NULL, mtod(m, struct ip6_hdr *), ifp, NULL, mtod(m, struct ip6_hdr *)); if ((ifp->if_flags & IFF_LOOPBACK) == 0) origifp = ifp; error = (*ifp->if_output)(origifp, m, (struct sockaddr *)dst, ro); return (error); } /* * Do L2 address resolution for @sa_dst address. Stores found * address in @desten buffer. Copy of lle ln_flags can be also * saved in @pflags if @pflags is non-NULL. * * If destination LLE does not exists or lle state modification * is required, call "slow" version. * * Return values: * - 0 on success (address copied to buffer). * - EWOULDBLOCK (no local error, but address is still unresolved) * - other errors (alloc failure, etc) */ int nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m, const struct sockaddr *sa_dst, u_char *desten, uint32_t *pflags) { struct llentry *ln = NULL; const struct sockaddr_in6 *dst6; if (pflags != NULL) *pflags = 0; dst6 = (const struct sockaddr_in6 *)sa_dst; /* discard the packet if IPv6 operation is disabled on the interface */ if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) { m_freem(m); return (ENETDOWN); /* better error? */ } if (m != NULL && m->m_flags & M_MCAST) { switch (ifp->if_type) { case IFT_ETHER: case IFT_FDDI: case IFT_L2VLAN: case IFT_IEEE80211: case IFT_BRIDGE: case IFT_ISO88025: ETHER_MAP_IPV6_MULTICAST(&dst6->sin6_addr, desten); return (0); default: m_freem(m); return (EAFNOSUPPORT); } } IF_AFDATA_RLOCK(ifp); ln = nd6_lookup(&dst6->sin6_addr, LLE_UNLOCKED, ifp); if (ln != NULL && (ln->r_flags & RLLE_VALID) != 0) { /* Entry found, let's copy lle info */ bcopy(&ln->ll_addr, desten, ifp->if_addrlen); if (pflags != NULL) *pflags = LLE_VALID | (ln->r_flags & RLLE_IFADDR); /* Check if we have feedback request from nd6 timer */ if (ln->r_skip_req != 0) { LLE_REQ_LOCK(ln); ln->r_skip_req = 0; /* Notify that entry was used */ ln->lle_hittime = time_uptime; LLE_REQ_UNLOCK(ln); } IF_AFDATA_RUNLOCK(ifp); return (0); } IF_AFDATA_RUNLOCK(ifp); return (nd6_resolve_slow(ifp, m, dst6, desten, pflags)); } /* * Do L2 address resolution for @sa_dst address. Stores found * address in @desten buffer. Copy of lle ln_flags can be also * saved in @pflags if @pflags is non-NULL. * * Heavy version. * Function assume that destination LLE does not exist, * is invalid or stale, so LLE_EXCLUSIVE lock needs to be acquired. * * Set noinline to be dtrace-friendly */ static __noinline int nd6_resolve_slow(struct ifnet *ifp, struct mbuf *m, const struct sockaddr_in6 *dst, u_char *desten, uint32_t *pflags) { struct llentry *lle = NULL, *lle_tmp; struct in6_addr *psrc, src; int send_ns; /* * Address resolution or Neighbor Unreachability Detection * for the next hop. * At this point, the destination of the packet must be a unicast * or an anycast address(i.e. not a multicast). */ if (lle == NULL) { IF_AFDATA_RLOCK(ifp); lle = nd6_lookup(&dst->sin6_addr, LLE_EXCLUSIVE, ifp); IF_AFDATA_RUNLOCK(ifp); if ((lle == NULL) && nd6_is_addr_neighbor(dst, ifp)) { /* * Since nd6_is_addr_neighbor() internally calls nd6_lookup(), * the condition below is not very efficient. But we believe * it is tolerable, because this should be a rare case. */ lle = nd6_alloc(&dst->sin6_addr, 0, ifp); if (lle == NULL) { char ip6buf[INET6_ADDRSTRLEN]; log(LOG_DEBUG, "nd6_output: can't allocate llinfo for %s " "(ln=%p)\n", ip6_sprintf(ip6buf, &dst->sin6_addr), lle); m_freem(m); return (ENOBUFS); } IF_AFDATA_WLOCK(ifp); LLE_WLOCK(lle); /* Prefer any existing entry over newly-created one */ lle_tmp = nd6_lookup(&dst->sin6_addr, LLE_EXCLUSIVE, ifp); if (lle_tmp == NULL) lltable_link_entry(LLTABLE6(ifp), lle); IF_AFDATA_WUNLOCK(ifp); if (lle_tmp != NULL) { lltable_free_entry(LLTABLE6(ifp), lle); lle = lle_tmp; lle_tmp = NULL; } } } if (lle == NULL) { if (!(ND_IFINFO(ifp)->flags & ND6_IFF_PERFORMNUD)) { m_freem(m); return (ENOBUFS); } if (m != NULL) m_freem(m); return (ENOBUFS); } LLE_WLOCK_ASSERT(lle); /* * The first time we send a packet to a neighbor whose entry is * STALE, we have to change the state to DELAY and a sets a timer to * expire in DELAY_FIRST_PROBE_TIME seconds to ensure do * neighbor unreachability detection on expiration. * (RFC 2461 7.3.3) */ if (lle->ln_state == ND6_LLINFO_STALE) nd6_llinfo_setstate(lle, ND6_LLINFO_DELAY); /* * If the neighbor cache entry has a state other than INCOMPLETE * (i.e. its link-layer address is already resolved), just * send the packet. */ if (lle->ln_state > ND6_LLINFO_INCOMPLETE) { bcopy(&lle->ll_addr, desten, ifp->if_addrlen); if (pflags != NULL) *pflags = lle->la_flags; LLE_WUNLOCK(lle); return (0); } /* * There is a neighbor cache entry, but no ethernet address * response yet. Append this latest packet to the end of the * packet queue in the mbuf, unless the number of the packet * does not exceed nd6_maxqueuelen. When it exceeds nd6_maxqueuelen, * the oldest packet in the queue will be removed. */ if (lle->la_hold != NULL) { struct mbuf *m_hold; int i; i = 0; for (m_hold = lle->la_hold; m_hold; m_hold = m_hold->m_nextpkt){ i++; if (m_hold->m_nextpkt == NULL) { m_hold->m_nextpkt = m; break; } } while (i >= V_nd6_maxqueuelen) { m_hold = lle->la_hold; lle->la_hold = lle->la_hold->m_nextpkt; m_freem(m_hold); i--; } } else { lle->la_hold = m; } /* * If there has been no NS for the neighbor after entering the * INCOMPLETE state, send the first solicitation. * Note that for newly-created lle la_asked will be 0, * so we will transition from ND6_LLINFO_NOSTATE to * ND6_LLINFO_INCOMPLETE state here. */ psrc = NULL; send_ns = 0; if (lle->la_asked == 0) { lle->la_asked++; send_ns = 1; psrc = nd6_llinfo_get_holdsrc(lle, &src); nd6_llinfo_setstate(lle, ND6_LLINFO_INCOMPLETE); } LLE_WUNLOCK(lle); if (send_ns != 0) nd6_ns_output(ifp, psrc, NULL, &dst->sin6_addr, NULL); return (EWOULDBLOCK); } int nd6_flush_holdchain(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *chain, struct sockaddr_in6 *dst) { struct mbuf *m, *m_head; struct ifnet *outifp; int error = 0; m_head = chain; if ((ifp->if_flags & IFF_LOOPBACK) != 0) outifp = origifp; else outifp = ifp; while (m_head) { m = m_head; m_head = m_head->m_nextpkt; error = nd6_output_ifp(ifp, origifp, m, dst, NULL); } /* * XXX * note that intermediate errors are blindly ignored */ return (error); } static int nd6_need_cache(struct ifnet *ifp) { /* * XXX: we currently do not make neighbor cache on any interface * other than ARCnet, Ethernet, FDDI and GIF. * * RFC2893 says: * - unidirectional tunnels needs no ND */ switch (ifp->if_type) { case IFT_ARCNET: case IFT_ETHER: case IFT_FDDI: case IFT_IEEE1394: case IFT_L2VLAN: case IFT_IEEE80211: case IFT_INFINIBAND: case IFT_BRIDGE: case IFT_PROPVIRTUAL: return (1); default: return (0); } } /* * Add pernament ND6 link-layer record for given * interface address. * * Very similar to IPv4 arp_ifinit(), but: * 1) IPv6 DAD is performed in different place * 2) It is called by IPv6 protocol stack in contrast to * arp_ifinit() which is typically called in SIOCSIFADDR * driver ioctl handler. * */ int nd6_add_ifa_lle(struct in6_ifaddr *ia) { struct ifnet *ifp; struct llentry *ln, *ln_tmp; struct sockaddr *dst; ifp = ia->ia_ifa.ifa_ifp; if (nd6_need_cache(ifp) == 0) return (0); ia->ia_ifa.ifa_rtrequest = nd6_rtrequest; dst = (struct sockaddr *)&ia->ia_addr; ln = lltable_alloc_entry(LLTABLE6(ifp), LLE_IFADDR, dst); if (ln == NULL) return (ENOBUFS); IF_AFDATA_WLOCK(ifp); LLE_WLOCK(ln); /* Unlink any entry if exists */ ln_tmp = lla_lookup(LLTABLE6(ifp), LLE_EXCLUSIVE, dst); if (ln_tmp != NULL) lltable_unlink_entry(LLTABLE6(ifp), ln_tmp); lltable_link_entry(LLTABLE6(ifp), ln); IF_AFDATA_WUNLOCK(ifp); if (ln_tmp != NULL) EVENTHANDLER_INVOKE(lle_event, ln_tmp, LLENTRY_EXPIRED); EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED); LLE_WUNLOCK(ln); if (ln_tmp != NULL) llentry_free(ln_tmp); return (0); } /* * Removes either all lle entries for given @ia, or lle * corresponding to @ia address. */ void nd6_rem_ifa_lle(struct in6_ifaddr *ia, int all) { struct sockaddr_in6 mask, addr; struct sockaddr *saddr, *smask; struct ifnet *ifp; ifp = ia->ia_ifa.ifa_ifp; memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr)); memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask)); saddr = (struct sockaddr *)&addr; smask = (struct sockaddr *)&mask; if (all != 0) lltable_prefix_free(AF_INET6, saddr, smask, LLE_STATIC); else lltable_delete_addr(LLTABLE6(ifp), LLE_IFADDR, saddr); } static void clear_llinfo_pqueue(struct llentry *ln) { struct mbuf *m_hold, *m_hold_next; for (m_hold = ln->la_hold; m_hold; m_hold = m_hold_next) { m_hold_next = m_hold->m_nextpkt; m_freem(m_hold); } ln->la_hold = NULL; return; } static int nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS); static int nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS); #ifdef SYSCTL_DECL SYSCTL_DECL(_net_inet6_icmp6); #endif SYSCTL_NODE(_net_inet6_icmp6, ICMPV6CTL_ND6_DRLIST, nd6_drlist, - CTLFLAG_RD, nd6_sysctl_drlist, "List default routers"); + CTLFLAG_RD, nd6_sysctl_drlist, ""); SYSCTL_NODE(_net_inet6_icmp6, ICMPV6CTL_ND6_PRLIST, nd6_prlist, - CTLFLAG_RD, nd6_sysctl_prlist, "List prefixes"); + CTLFLAG_RD, nd6_sysctl_prlist, ""); SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MAXQLEN, nd6_maxqueuelen, - CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nd6_maxqueuelen), 1, - "Max packets cached in unresolved ND entries"); + CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nd6_maxqueuelen), 1, ""); SYSCTL_INT(_net_inet6_icmp6, OID_AUTO, nd6_gctimer, - CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nd6_gctimer), (60 * 60 * 24), - "Interface in seconds between garbage collection passes"); -SYSCTL_INT(_net_inet6_icmp6, OID_AUTO, nd6_on_link, CTLFLAG_VNET | CTLFLAG_RW, - &VNET_NAME(nd6_on_link), 0, - "Send unsolicited neighbor discovery on interface link up events"); + CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nd6_gctimer), (60 * 60 * 24), ""); static int nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS) { struct in6_defrouter d; struct nd_defrouter *dr; int error; if (req->newptr) return (EPERM); bzero(&d, sizeof(d)); d.rtaddr.sin6_family = AF_INET6; d.rtaddr.sin6_len = sizeof(d.rtaddr); /* * XXX locking */ TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) { d.rtaddr.sin6_addr = dr->rtaddr; error = sa6_recoverscope(&d.rtaddr); if (error != 0) return (error); d.flags = dr->flags; d.rtlifetime = dr->rtlifetime; d.expire = dr->expire + (time_second - time_uptime); d.if_index = dr->ifp->if_index; error = SYSCTL_OUT(req, &d, sizeof(d)); if (error != 0) return (error); } return (0); } static int nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS) { struct in6_prefix p; struct sockaddr_in6 s6; struct nd_prefix *pr; struct nd_pfxrouter *pfr; time_t maxexpire; int error; char ip6buf[INET6_ADDRSTRLEN]; if (req->newptr) return (EPERM); bzero(&p, sizeof(p)); p.origin = PR_ORIG_RA; bzero(&s6, sizeof(s6)); s6.sin6_family = AF_INET6; s6.sin6_len = sizeof(s6); /* * XXX locking */ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) { p.prefix = pr->ndpr_prefix; if (sa6_recoverscope(&p.prefix)) { log(LOG_ERR, "scope error in prefix list (%s)\n", ip6_sprintf(ip6buf, &p.prefix.sin6_addr)); /* XXX: press on... */ } p.raflags = pr->ndpr_raf; p.prefixlen = pr->ndpr_plen; p.vltime = pr->ndpr_vltime; p.pltime = pr->ndpr_pltime; p.if_index = pr->ndpr_ifp->if_index; if (pr->ndpr_vltime == ND6_INFINITE_LIFETIME) p.expire = 0; else { /* XXX: we assume time_t is signed. */ maxexpire = (-1) & ~((time_t)1 << ((sizeof(maxexpire) * 8) - 1)); if (pr->ndpr_vltime < maxexpire - pr->ndpr_lastupdate) p.expire = pr->ndpr_lastupdate + pr->ndpr_vltime + (time_second - time_uptime); else p.expire = maxexpire; } p.refcnt = pr->ndpr_refcnt; p.flags = pr->ndpr_stateflags; p.advrtrs = 0; LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) p.advrtrs++; error = SYSCTL_OUT(req, &p, sizeof(p)); if (error != 0) return (error); LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) { s6.sin6_addr = pfr->router->rtaddr; if (sa6_recoverscope(&s6)) log(LOG_ERR, "scope error in prefix list (%s)\n", ip6_sprintf(ip6buf, &pfr->router->rtaddr)); error = SYSCTL_OUT(req, &s6, sizeof(s6)); if (error != 0) return (error); } } return (0); } Index: user/alc/PQ_LAUNDRY/sys/netinet6/nd6.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/netinet6/nd6.h (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/netinet6/nd6.h (revision 292449) @@ -1,462 +1,458 @@ /*- * 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. * * $KAME: nd6.h,v 1.76 2001/12/18 02:10:31 itojun Exp $ * $FreeBSD$ */ #ifndef _NETINET6_ND6_H_ #define _NETINET6_ND6_H_ /* see net/route.h, or net/if_inarp.h */ #ifndef RTF_ANNOUNCE #define RTF_ANNOUNCE RTF_PROTO2 #endif #include #include struct llentry; #define ND6_LLINFO_NOSTATE -2 /* * We don't need the WAITDELETE state any more, but we keep the definition * in a comment line instead of removing it. This is necessary to avoid * unintentionally reusing the value for another purpose, which might * affect backward compatibility with old applications. * (20000711 jinmei@kame.net) */ /* #define ND6_LLINFO_WAITDELETE -1 */ #define ND6_LLINFO_INCOMPLETE 0 #define ND6_LLINFO_REACHABLE 1 #define ND6_LLINFO_STALE 2 #define ND6_LLINFO_DELAY 3 #define ND6_LLINFO_PROBE 4 #define ND6_IS_LLINFO_PROBREACH(n) ((n)->ln_state > ND6_LLINFO_INCOMPLETE) #define ND6_LLINFO_PERMANENT(n) (((n)->la_expire == 0) && ((n)->ln_state > ND6_LLINFO_INCOMPLETE)) struct nd_ifinfo { u_int32_t linkmtu; /* LinkMTU */ u_int32_t maxmtu; /* Upper bound of LinkMTU */ u_int32_t basereachable; /* BaseReachableTime */ u_int32_t reachable; /* Reachable Time */ u_int32_t retrans; /* Retrans Timer */ u_int32_t flags; /* Flags */ int recalctm; /* BaseReacable re-calculation timer */ u_int8_t chlim; /* CurHopLimit */ u_int8_t initialized; /* Flag to see the entry is initialized */ /* the following 3 members are for privacy extension for addrconf */ u_int8_t randomseed0[8]; /* upper 64 bits of MD5 digest */ u_int8_t randomseed1[8]; /* lower 64 bits (usually the EUI64 IFID) */ u_int8_t randomid[8]; /* current random ID */ }; #define ND6_IFF_PERFORMNUD 0x1 #define ND6_IFF_ACCEPT_RTADV 0x2 #define ND6_IFF_PREFER_SOURCE 0x4 /* Not used in FreeBSD. */ #define ND6_IFF_IFDISABLED 0x8 /* IPv6 operation is disabled due to * DAD failure. (XXX: not ND-specific) */ #define ND6_IFF_DONT_SET_IFROUTE 0x10 #define ND6_IFF_AUTO_LINKLOCAL 0x20 #define ND6_IFF_NO_RADR 0x40 #define ND6_IFF_NO_PREFER_IFACE 0x80 /* XXX: not related to ND. */ #define ND6_IFF_NO_DAD 0x100 #ifdef _KERNEL #define ND_IFINFO(ifp) \ (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->nd_ifinfo) #define IN6_LINKMTU(ifp) \ ((ND_IFINFO(ifp)->linkmtu && ND_IFINFO(ifp)->linkmtu < (ifp)->if_mtu) \ ? ND_IFINFO(ifp)->linkmtu \ : ((ND_IFINFO(ifp)->maxmtu && ND_IFINFO(ifp)->maxmtu < (ifp)->if_mtu) \ ? ND_IFINFO(ifp)->maxmtu : (ifp)->if_mtu)) #endif struct in6_nbrinfo { char ifname[IFNAMSIZ]; /* if name, e.g. "en0" */ struct in6_addr addr; /* IPv6 address of the neighbor */ long asked; /* number of queries already sent for this addr */ int isrouter; /* if it acts as a router */ int state; /* reachability state */ int expire; /* lifetime for NDP state transition */ }; #define DRLSTSIZ 10 #define PRLSTSIZ 10 struct in6_drlist { char ifname[IFNAMSIZ]; struct { struct in6_addr rtaddr; u_char flags; u_short rtlifetime; u_long expire; u_short if_index; } defrouter[DRLSTSIZ]; }; struct in6_defrouter { struct sockaddr_in6 rtaddr; u_char flags; u_short rtlifetime; u_long expire; u_short if_index; }; #ifdef _KERNEL struct in6_oprlist { char ifname[IFNAMSIZ]; struct { struct in6_addr prefix; struct prf_ra raflags; u_char prefixlen; u_char origin; u_long vltime; u_long pltime; u_long expire; u_short if_index; u_short advrtrs; /* number of advertisement routers */ struct in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */ } prefix[PRLSTSIZ]; }; #endif struct in6_prlist { char ifname[IFNAMSIZ]; struct { struct in6_addr prefix; struct prf_ra raflags; u_char prefixlen; u_char origin; u_int32_t vltime; u_int32_t pltime; time_t expire; u_short if_index; u_short advrtrs; /* number of advertisement routers */ struct in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */ } prefix[PRLSTSIZ]; }; struct in6_prefix { struct sockaddr_in6 prefix; struct prf_ra raflags; u_char prefixlen; u_char origin; u_int32_t vltime; u_int32_t pltime; time_t expire; u_int32_t flags; int refcnt; u_short if_index; u_short advrtrs; /* number of advertisement routers */ /* struct sockaddr_in6 advrtr[] */ }; #ifdef _KERNEL struct in6_ondireq { char ifname[IFNAMSIZ]; struct { u_int32_t linkmtu; /* LinkMTU */ u_int32_t maxmtu; /* Upper bound of LinkMTU */ u_int32_t basereachable; /* BaseReachableTime */ u_int32_t reachable; /* Reachable Time */ u_int32_t retrans; /* Retrans Timer */ u_int32_t flags; /* Flags */ int recalctm; /* BaseReacable re-calculation timer */ u_int8_t chlim; /* CurHopLimit */ u_int8_t receivedra; } ndi; }; #endif struct in6_ndireq { char ifname[IFNAMSIZ]; struct nd_ifinfo ndi; }; struct in6_ndifreq { char ifname[IFNAMSIZ]; u_long ifindex; }; /* Prefix status */ #define NDPRF_ONLINK 0x1 #define NDPRF_DETACHED 0x2 /* protocol constants */ #define MAX_RTR_SOLICITATION_DELAY 1 /* 1sec */ #define RTR_SOLICITATION_INTERVAL 4 /* 4sec */ #define MAX_RTR_SOLICITATIONS 3 #define ND6_INFINITE_LIFETIME 0xffffffff #ifdef _KERNEL /* node constants */ #define MAX_REACHABLE_TIME 3600000 /* msec */ #define REACHABLE_TIME 30000 /* msec */ #define RETRANS_TIMER 1000 /* msec */ #define MIN_RANDOM_FACTOR 512 /* 1024 * 0.5 */ #define MAX_RANDOM_FACTOR 1536 /* 1024 * 1.5 */ #define DEF_TEMP_VALID_LIFETIME 604800 /* 1 week */ #define DEF_TEMP_PREFERRED_LIFETIME 86400 /* 1 day */ #define TEMPADDR_REGEN_ADVANCE 5 /* sec */ #define MAX_TEMP_DESYNC_FACTOR 600 /* 10 min */ #define ND_COMPUTE_RTIME(x) \ (((MIN_RANDOM_FACTOR * (x >> 10)) + (arc4random() & \ ((MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR) * (x >> 10)))) /1000) TAILQ_HEAD(nd_drhead, nd_defrouter); struct nd_defrouter { TAILQ_ENTRY(nd_defrouter) dr_entry; struct in6_addr rtaddr; u_char flags; /* flags on RA message */ u_short rtlifetime; u_long expire; struct ifnet *ifp; int installed; /* is installed into kernel routing table */ }; struct nd_prefixctl { struct ifnet *ndpr_ifp; /* prefix */ struct sockaddr_in6 ndpr_prefix; u_char ndpr_plen; u_int32_t ndpr_vltime; /* advertised valid lifetime */ u_int32_t ndpr_pltime; /* advertised preferred lifetime */ struct prf_ra ndpr_flags; }; struct nd_prefix { struct ifnet *ndpr_ifp; LIST_ENTRY(nd_prefix) ndpr_entry; struct sockaddr_in6 ndpr_prefix; /* prefix */ struct in6_addr ndpr_mask; /* netmask derived from the prefix */ u_int32_t ndpr_vltime; /* advertised valid lifetime */ u_int32_t ndpr_pltime; /* advertised preferred lifetime */ time_t ndpr_expire; /* expiration time of the prefix */ time_t ndpr_preferred; /* preferred time of the prefix */ time_t ndpr_lastupdate; /* reception time of last advertisement */ struct prf_ra ndpr_flags; u_int32_t ndpr_stateflags; /* actual state flags */ /* list of routers that advertise the prefix: */ LIST_HEAD(pr_rtrhead, nd_pfxrouter) ndpr_advrtrs; u_char ndpr_plen; int ndpr_refcnt; /* reference couter from addresses */ }; #define ndpr_raf ndpr_flags #define ndpr_raf_onlink ndpr_flags.onlink #define ndpr_raf_auto ndpr_flags.autonomous #define ndpr_raf_router ndpr_flags.router /* * Message format for use in obtaining information about prefixes * from inet6 sysctl function */ struct inet6_ndpr_msghdr { u_short inpm_msglen; /* to skip over non-understood messages */ u_char inpm_version; /* future binary compatibility */ u_char inpm_type; /* message type */ struct in6_addr inpm_prefix; u_long prm_vltim; u_long prm_pltime; u_long prm_expire; u_long prm_preferred; struct in6_prflags prm_flags; u_short prm_index; /* index for associated ifp */ u_char prm_plen; /* length of prefix in bits */ }; #define prm_raf_onlink prm_flags.prf_ra.onlink #define prm_raf_auto prm_flags.prf_ra.autonomous #define prm_statef_onlink prm_flags.prf_state.onlink #define prm_rrf_decrvalid prm_flags.prf_rr.decrvalid #define prm_rrf_decrprefd prm_flags.prf_rr.decrprefd struct nd_pfxrouter { LIST_ENTRY(nd_pfxrouter) pfr_entry; struct nd_defrouter *router; }; LIST_HEAD(nd_prhead, nd_prefix); /* nd6.c */ VNET_DECLARE(int, nd6_prune); VNET_DECLARE(int, nd6_delay); VNET_DECLARE(int, nd6_umaxtries); VNET_DECLARE(int, nd6_mmaxtries); VNET_DECLARE(int, nd6_useloopback); VNET_DECLARE(int, nd6_maxnudhint); VNET_DECLARE(int, nd6_gctimer); VNET_DECLARE(struct nd_drhead, nd_defrouter); VNET_DECLARE(struct nd_prhead, nd_prefix); VNET_DECLARE(int, nd6_debug); VNET_DECLARE(int, nd6_onlink_ns_rfc4861); #define V_nd6_prune VNET(nd6_prune) #define V_nd6_delay VNET(nd6_delay) #define V_nd6_umaxtries VNET(nd6_umaxtries) #define V_nd6_mmaxtries VNET(nd6_mmaxtries) #define V_nd6_useloopback VNET(nd6_useloopback) #define V_nd6_maxnudhint VNET(nd6_maxnudhint) #define V_nd6_gctimer VNET(nd6_gctimer) #define V_nd_defrouter VNET(nd_defrouter) #define V_nd_prefix VNET(nd_prefix) #define V_nd6_debug VNET(nd6_debug) #define V_nd6_onlink_ns_rfc4861 VNET(nd6_onlink_ns_rfc4861) #define nd6log(x) do { if (V_nd6_debug) log x; } while (/*CONSTCOND*/ 0) VNET_DECLARE(struct callout, nd6_timer_ch); #define V_nd6_timer_ch VNET(nd6_timer_ch) /* nd6_rtr.c */ VNET_DECLARE(int, nd6_defifindex); VNET_DECLARE(int, ip6_desync_factor); /* seconds */ VNET_DECLARE(u_int32_t, ip6_temp_preferred_lifetime); /* seconds */ VNET_DECLARE(u_int32_t, ip6_temp_valid_lifetime); /* seconds */ VNET_DECLARE(int, ip6_temp_regen_advance); /* seconds */ #define V_nd6_defifindex VNET(nd6_defifindex) #define V_ip6_desync_factor VNET(ip6_desync_factor) #define V_ip6_temp_preferred_lifetime VNET(ip6_temp_preferred_lifetime) #define V_ip6_temp_valid_lifetime VNET(ip6_temp_valid_lifetime) #define V_ip6_temp_regen_advance VNET(ip6_temp_regen_advance) union nd_opts { struct nd_opt_hdr *nd_opt_array[16]; /* max = ND_OPT_NONCE */ struct { struct nd_opt_hdr *zero; struct nd_opt_hdr *src_lladdr; struct nd_opt_hdr *tgt_lladdr; struct nd_opt_prefix_info *pi_beg; /* multiple opts, start */ struct nd_opt_rd_hdr *rh; struct nd_opt_mtu *mtu; struct nd_opt_hdr *__res6; struct nd_opt_hdr *__res7; struct nd_opt_hdr *__res8; struct nd_opt_hdr *__res9; struct nd_opt_hdr *__res10; struct nd_opt_hdr *__res11; struct nd_opt_hdr *__res12; struct nd_opt_hdr *__res13; struct nd_opt_nonce *nonce; struct nd_opt_hdr *__res15; struct nd_opt_hdr *search; /* multiple opts */ struct nd_opt_hdr *last; /* multiple opts */ int done; struct nd_opt_prefix_info *pi_end;/* multiple opts, end */ } nd_opt_each; }; #define nd_opts_src_lladdr nd_opt_each.src_lladdr #define nd_opts_tgt_lladdr nd_opt_each.tgt_lladdr #define nd_opts_pi nd_opt_each.pi_beg #define nd_opts_pi_end nd_opt_each.pi_end #define nd_opts_rh nd_opt_each.rh #define nd_opts_mtu nd_opt_each.mtu #define nd_opts_nonce nd_opt_each.nonce #define nd_opts_search nd_opt_each.search #define nd_opts_last nd_opt_each.last #define nd_opts_done nd_opt_each.done /* XXX: need nd6_var.h?? */ /* nd6.c */ void nd6_init(void); #ifdef VIMAGE void nd6_destroy(void); #endif -void nd6_na_output_unsolicited(struct ifnet *); -void nd6_na_output_unsolicited_addr(struct ifnet *, const struct in6_addr *, - u_long); -int nd6_na_unsolicited_addr_delay(struct ifaddr *); struct nd_ifinfo *nd6_ifattach(struct ifnet *); void nd6_ifdetach(struct nd_ifinfo *); int nd6_is_addr_neighbor(const struct sockaddr_in6 *, struct ifnet *); void nd6_option_init(void *, int, union nd_opts *); struct nd_opt_hdr *nd6_option(union nd_opts *); int nd6_options(union nd_opts *); struct llentry *nd6_lookup(const struct in6_addr *, int, struct ifnet *); struct llentry *nd6_alloc(const struct in6_addr *, int, struct ifnet *); void nd6_setmtu(struct ifnet *); void nd6_llinfo_setstate(struct llentry *lle, int newstate); void nd6_timer(void *); void nd6_purge(struct ifnet *); int nd6_resolve(struct ifnet *, int, struct mbuf *, const struct sockaddr *, u_char *, uint32_t *); int nd6_ioctl(u_long, caddr_t, struct ifnet *); void nd6_cache_lladdr(struct ifnet *, struct in6_addr *, char *, int, int, int); void nd6_grab_holdchain(struct llentry *, struct mbuf **, struct sockaddr_in6 *); int nd6_flush_holdchain(struct ifnet *, struct ifnet *, struct mbuf *, struct sockaddr_in6 *); int nd6_add_ifa_lle(struct in6_ifaddr *); void nd6_rem_ifa_lle(struct in6_ifaddr *, int); int nd6_output_ifp(struct ifnet *, struct ifnet *, struct mbuf *, struct sockaddr_in6 *, struct route *); /* nd6_nbr.c */ void nd6_na_input(struct mbuf *, int, int); void nd6_na_output(struct ifnet *, const struct in6_addr *, const struct in6_addr *, u_long, int, struct sockaddr *); void nd6_ns_input(struct mbuf *, int, int); void nd6_ns_output(struct ifnet *, const struct in6_addr *, const struct in6_addr *, const struct in6_addr *, uint8_t *); caddr_t nd6_ifptomac(struct ifnet *); void nd6_dad_init(void); void nd6_dad_start(struct ifaddr *, int); void nd6_dad_stop(struct ifaddr *); /* nd6_rtr.c */ void nd6_rs_input(struct mbuf *, int, int); void nd6_ra_input(struct mbuf *, int, int); void prelist_del(struct nd_prefix *); void defrouter_reset(void); void defrouter_select(void); void defrtrlist_del(struct nd_defrouter *); void prelist_remove(struct nd_prefix *); int nd6_prelist_add(struct nd_prefixctl *, struct nd_defrouter *, struct nd_prefix **); void pfxlist_onlink_check(void); struct nd_defrouter *defrouter_lookup(struct in6_addr *, struct ifnet *); struct nd_prefix *nd6_prefix_lookup(struct nd_prefixctl *); void rt6_flush(struct in6_addr *, struct ifnet *); int nd6_setdefaultiface(int); int in6_tmpifadd(const struct in6_ifaddr *, int, int); #endif /* _KERNEL */ #endif /* _NETINET6_ND6_H_ */ Index: user/alc/PQ_LAUNDRY/sys/netinet6/nd6_nbr.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/netinet6/nd6_nbr.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/netinet6/nd6_nbr.c (revision 292449) @@ -1,1697 +1,1599 @@ /*- * 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. * * $KAME: nd6_nbr.c,v 1.86 2002/01/21 02:33:04 jinmei Exp $ */ #include __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" #include "opt_ipsec.h" #include "opt_mpath.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef RADIX_MPATH #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #define SDL(s) ((struct sockaddr_dl *)s) struct dadq; static struct dadq *nd6_dad_find(struct ifaddr *, struct nd_opt_nonce *); static void nd6_dad_add(struct dadq *dp); static void nd6_dad_del(struct dadq *dp); static void nd6_dad_rele(struct dadq *); static void nd6_dad_starttimer(struct dadq *, int, int); static void nd6_dad_stoptimer(struct dadq *); static void nd6_dad_timer(struct dadq *); static void nd6_dad_duplicated(struct ifaddr *, struct dadq *); static void nd6_dad_ns_output(struct dadq *); static void nd6_dad_ns_input(struct ifaddr *, struct nd_opt_nonce *); static void nd6_dad_na_input(struct ifaddr *); static void nd6_na_output_fib(struct ifnet *, const struct in6_addr *, const struct in6_addr *, u_long, int, struct sockaddr *, u_int); static void nd6_ns_output_fib(struct ifnet *, const struct in6_addr *, const struct in6_addr *, const struct in6_addr *, uint8_t *, u_int); static VNET_DEFINE(int, dad_enhanced) = 1; #define V_dad_enhanced VNET(dad_enhanced) SYSCTL_DECL(_net_inet6_ip6); SYSCTL_INT(_net_inet6_ip6, OID_AUTO, dad_enhanced, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(dad_enhanced), 0, "Enable Enhanced DAD, which adds a random nonce to NS messages for DAD."); static VNET_DEFINE(int, dad_maxtry) = 15; /* max # of *tries* to transmit DAD packet */ #define V_dad_maxtry VNET(dad_maxtry) /* * Input a Neighbor Solicitation Message. * * Based on RFC 2461 * Based on RFC 2462 (duplicate address detection) */ void nd6_ns_input(struct mbuf *m, int off, int icmp6len) { struct ifnet *ifp = m->m_pkthdr.rcvif; struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); struct nd_neighbor_solicit *nd_ns; struct in6_addr saddr6 = ip6->ip6_src; struct in6_addr daddr6 = ip6->ip6_dst; struct in6_addr taddr6; + struct in6_addr myaddr6; char *lladdr = NULL; struct ifaddr *ifa = NULL; - u_long flags; int lladdrlen = 0; - int proxy = 0; + int anycast = 0, proxy = 0, tentative = 0; int tlladdr; + int rflag; union nd_opts ndopts; struct sockaddr_dl proxydl; char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; + rflag = (V_ip6_forwarding) ? ND_NA_FLAG_ROUTER : 0; + if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV && V_ip6_norbit_raif) + rflag = 0; #ifndef PULLDOWN_TEST IP6_EXTHDR_CHECK(m, off, icmp6len,); nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off); #else IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m, off, icmp6len); if (nd_ns == NULL) { ICMP6STAT_INC(icp6s_tooshort); return; } #endif ip6 = mtod(m, struct ip6_hdr *); /* adjust pointer for safety */ taddr6 = nd_ns->nd_ns_target; if (in6_setscope(&taddr6, ifp, NULL) != 0) goto bad; if (ip6->ip6_hlim != 255) { nd6log((LOG_ERR, "nd6_ns_input: invalid hlim (%d) from %s to %s on %s\n", ip6->ip6_hlim, ip6_sprintf(ip6bufs, &ip6->ip6_src), ip6_sprintf(ip6bufd, &ip6->ip6_dst), if_name(ifp))); goto bad; } if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) { /* dst has to be a solicited node multicast address. */ if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL && /* don't check ifindex portion */ daddr6.s6_addr32[1] == 0 && daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE && daddr6.s6_addr8[12] == 0xff) { ; /* good */ } else { nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet " "(wrong ip6 dst)\n")); goto bad; } } else if (!V_nd6_onlink_ns_rfc4861) { struct sockaddr_in6 src_sa6; /* * According to recent IETF discussions, it is not a good idea * to accept a NS from an address which would not be deemed * to be a neighbor otherwise. This point is expected to be * clarified in future revisions of the specification. */ bzero(&src_sa6, sizeof(src_sa6)); src_sa6.sin6_family = AF_INET6; src_sa6.sin6_len = sizeof(src_sa6); src_sa6.sin6_addr = saddr6; if (nd6_is_addr_neighbor(&src_sa6, ifp) == 0) { nd6log((LOG_INFO, "nd6_ns_input: " "NS packet from non-neighbor\n")); goto bad; } } if (IN6_IS_ADDR_MULTICAST(&taddr6)) { nd6log((LOG_INFO, "nd6_ns_input: bad NS target (multicast)\n")); goto bad; } icmp6len -= sizeof(*nd_ns); nd6_option_init(nd_ns + 1, icmp6len, &ndopts); if (nd6_options(&ndopts) < 0) { nd6log((LOG_INFO, "nd6_ns_input: invalid ND option, ignored\n")); /* nd6_options have incremented stats */ goto freeit; } if (ndopts.nd_opts_src_lladdr) { lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1); lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3; } if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) && lladdr) { nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet " "(link-layer address option)\n")); goto bad; } /* * Attaching target link-layer address to the NA? * (RFC 2461 7.2.4) * * NS IP dst is unicast/anycast MUST NOT add * NS IP dst is solicited-node multicast MUST add * * In implementation, we add target link-layer address by default. * We do not add one in MUST NOT cases. */ - tlladdr = !IN6_IS_ADDR_MULTICAST(&daddr6); + if (!IN6_IS_ADDR_MULTICAST(&daddr6)) + tlladdr = 0; + else + tlladdr = 1; /* * Target address (taddr6) must be either: * (1) Valid unicast/anycast address for my receiving interface, * (2) Unicast address for which I'm offering proxy service, or * (3) "tentative" address on which DAD is being performed. */ /* (1) and (3) check. */ if (ifp->if_carp) ifa = (*carp_iamatch6_p)(ifp, &taddr6); else ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6); /* (2) check. */ if (ifa == NULL) { struct route_in6 ro; int need_proxy; bzero(&ro, sizeof(ro)); ro.ro_dst.sin6_len = sizeof(struct sockaddr_in6); ro.ro_dst.sin6_family = AF_INET6; ro.ro_dst.sin6_addr = taddr6; /* Always use the default FIB. */ #ifdef RADIX_MPATH rtalloc_mpath_fib((struct route *)&ro, ntohl(taddr6.s6_addr32[3]), RT_DEFAULT_FIB); #else in6_rtalloc(&ro, RT_DEFAULT_FIB); #endif need_proxy = (ro.ro_rt && (ro.ro_rt->rt_flags & RTF_ANNOUNCE) != 0 && ro.ro_rt->rt_gateway->sa_family == AF_LINK); if (ro.ro_rt != NULL) { if (need_proxy) proxydl = *SDL(ro.ro_rt->rt_gateway); RTFREE(ro.ro_rt); } if (need_proxy) { /* * proxy NDP for single entry */ ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, IN6_IFF_NOTREADY|IN6_IFF_ANYCAST); if (ifa) proxy = 1; } } if (ifa == NULL) { /* * We've got an NS packet, and we don't have that adddress * assigned for us. We MUST silently ignore it. * See RFC2461 7.2.3. */ goto freeit; } + myaddr6 = *IFA_IN6(ifa); + anycast = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST; + tentative = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE; if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DUPLICATED) goto freeit; if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { nd6log((LOG_INFO, "nd6_ns_input: lladdrlen mismatch for %s " "(if %d, NS packet %d)\n", ip6_sprintf(ip6bufs, &taddr6), ifp->if_addrlen, lladdrlen - 2)); goto bad; } - if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &saddr6)) { + if (IN6_ARE_ADDR_EQUAL(&myaddr6, &saddr6)) { nd6log((LOG_INFO, "nd6_ns_input: duplicate IP6 address %s\n", ip6_sprintf(ip6bufs, &saddr6))); goto freeit; } /* * We have neighbor solicitation packet, with target address equals to * one of my tentative address. * * src addr how to process? * --- --- * multicast of course, invalid (rejected in ip6_input) * unicast somebody is doing address resolution -> ignore * unspec dup address detection * * The processing is defined in RFC 2462. */ - if (IFA_IN6_FLAGS(ifa) & IN6_IFF_TENTATIVE) { + if (tentative) { /* * If source address is unspecified address, it is for * duplicate address detection. * * If not, the packet is for addess resolution; * silently ignore it. */ if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) nd6_dad_ns_input(ifa, ndopts.nd_opts_nonce); goto freeit; } - flags = IFA_ND6_NA_BASE_FLAGS(ifp, ifa); - if (proxy || !tlladdr) - flags &= ~ND_NA_FLAG_OVERRIDE; - /* * If the source address is unspecified address, entries must not * be created or updated. * It looks that sender is performing DAD. Output NA toward * all-node multicast address, to tell the sender that I'm using * the address. * S bit ("solicited") must be zero. */ if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) { struct in6_addr in6_all; in6_all = in6addr_linklocal_allnodes; if (in6_setscope(&in6_all, ifp, NULL) != 0) goto bad; - nd6_na_output_fib(ifp, &in6_all, &taddr6, flags, tlladdr, - proxy ? (struct sockaddr *)&proxydl : NULL, M_GETFIB(m)); + nd6_na_output_fib(ifp, &in6_all, &taddr6, + ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) | + rflag, tlladdr, proxy ? (struct sockaddr *)&proxydl : NULL, + M_GETFIB(m)); goto freeit; } nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_NEIGHBOR_SOLICIT, 0); - nd6_na_output_fib(ifp, &saddr6, &taddr6, flags | ND_NA_FLAG_SOLICITED, - tlladdr, proxy ? (struct sockaddr *)&proxydl : NULL, M_GETFIB(m)); + nd6_na_output_fib(ifp, &saddr6, &taddr6, + ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) | + rflag | ND_NA_FLAG_SOLICITED, tlladdr, + proxy ? (struct sockaddr *)&proxydl : NULL, M_GETFIB(m)); freeit: if (ifa != NULL) ifa_free(ifa); m_freem(m); return; bad: nd6log((LOG_ERR, "nd6_ns_input: src=%s\n", ip6_sprintf(ip6bufs, &saddr6))); nd6log((LOG_ERR, "nd6_ns_input: dst=%s\n", ip6_sprintf(ip6bufs, &daddr6))); nd6log((LOG_ERR, "nd6_ns_input: tgt=%s\n", ip6_sprintf(ip6bufs, &taddr6))); ICMP6STAT_INC(icp6s_badns); if (ifa != NULL) ifa_free(ifa); m_freem(m); } /* * Output a Neighbor Solicitation Message. Caller specifies: * - ICMP6 header source IP6 address * - ND6 header target IP6 address * - ND6 header source datalink address * * Based on RFC 2461 * Based on RFC 2462 (duplicate address detection) * * ln - for source address determination * nonce - If non-NULL, NS is used for duplicate address detection and * the value (length is ND_OPT_NONCE_LEN) is used as a random nonce. */ static void nd6_ns_output_fib(struct ifnet *ifp, const struct in6_addr *saddr6, const struct in6_addr *daddr6, const struct in6_addr *taddr6, uint8_t *nonce, u_int fibnum) { struct mbuf *m; struct m_tag *mtag; struct ip6_hdr *ip6; struct nd_neighbor_solicit *nd_ns; struct ip6_moptions im6o; int icmp6len; int maxlen; caddr_t mac; struct route_in6 ro; if (IN6_IS_ADDR_MULTICAST(taddr6)) return; /* estimate the size of message */ maxlen = sizeof(*ip6) + sizeof(*nd_ns); maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7; KASSERT(max_linkhdr + maxlen <= MCLBYTES, ( "%s: max_linkhdr + maxlen > MCLBYTES (%d + %d > %d)", __func__, max_linkhdr, maxlen, MCLBYTES)); if (max_linkhdr + maxlen > MHLEN) m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); else m = m_gethdr(M_NOWAIT, MT_DATA); if (m == NULL) return; M_SETFIB(m, fibnum); bzero(&ro, sizeof(ro)); if (daddr6 == NULL || IN6_IS_ADDR_MULTICAST(daddr6)) { m->m_flags |= M_MCAST; im6o.im6o_multicast_ifp = ifp; im6o.im6o_multicast_hlim = 255; im6o.im6o_multicast_loop = 0; } icmp6len = sizeof(*nd_ns); m->m_pkthdr.len = m->m_len = sizeof(*ip6) + icmp6len; m->m_data += max_linkhdr; /* or M_ALIGN() equivalent? */ /* fill neighbor solicitation packet */ ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_flow = 0; ip6->ip6_vfc &= ~IPV6_VERSION_MASK; ip6->ip6_vfc |= IPV6_VERSION; /* ip6->ip6_plen will be set later */ ip6->ip6_nxt = IPPROTO_ICMPV6; ip6->ip6_hlim = 255; if (daddr6) ip6->ip6_dst = *daddr6; else { ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL; ip6->ip6_dst.s6_addr16[1] = 0; ip6->ip6_dst.s6_addr32[1] = 0; ip6->ip6_dst.s6_addr32[2] = IPV6_ADDR_INT32_ONE; ip6->ip6_dst.s6_addr32[3] = taddr6->s6_addr32[3]; ip6->ip6_dst.s6_addr8[12] = 0xff; if (in6_setscope(&ip6->ip6_dst, ifp, NULL) != 0) goto bad; } if (nonce == NULL) { struct ifaddr *ifa = NULL; /* * RFC2461 7.2.2: * "If the source address of the packet prompting the * solicitation is the same as one of the addresses assigned * to the outgoing interface, that address SHOULD be placed * in the IP Source Address of the outgoing solicitation. * Otherwise, any one of the addresses assigned to the * interface should be used." * * We use the source address for the prompting packet * (saddr6), if saddr6 belongs to the outgoing interface. * Otherwise, we perform the source address selection as usual. */ if (saddr6 != NULL) ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, saddr6); if (ifa != NULL) { /* ip6_src set already. */ ip6->ip6_src = *saddr6; ifa_free(ifa); } else { int error; struct sockaddr_in6 dst_sa; struct in6_addr src_in; struct ifnet *oifp; bzero(&dst_sa, sizeof(dst_sa)); dst_sa.sin6_family = AF_INET6; dst_sa.sin6_len = sizeof(dst_sa); dst_sa.sin6_addr = ip6->ip6_dst; oifp = ifp; error = in6_selectsrc(&dst_sa, NULL, NULL, &ro, NULL, &oifp, &src_in); if (error) { char ip6buf[INET6_ADDRSTRLEN]; nd6log((LOG_DEBUG, "%s: source can't be " "determined: dst=%s, error=%d\n", __func__, ip6_sprintf(ip6buf, &dst_sa.sin6_addr), error)); goto bad; } ip6->ip6_src = src_in; } } else { /* * Source address for DAD packet must always be IPv6 * unspecified address. (0::0) * We actually don't have to 0-clear the address (we did it * above), but we do so here explicitly to make the intention * clearer. */ bzero(&ip6->ip6_src, sizeof(ip6->ip6_src)); } nd_ns = (struct nd_neighbor_solicit *)(ip6 + 1); nd_ns->nd_ns_type = ND_NEIGHBOR_SOLICIT; nd_ns->nd_ns_code = 0; nd_ns->nd_ns_reserved = 0; nd_ns->nd_ns_target = *taddr6; in6_clearscope(&nd_ns->nd_ns_target); /* XXX */ /* * Add source link-layer address option. * * spec implementation * --- --- * DAD packet MUST NOT do not add the option * there's no link layer address: * impossible do not add the option * there's link layer address: * Multicast NS MUST add one add the option * Unicast NS SHOULD add one add the option */ if (nonce == NULL && (mac = nd6_ifptomac(ifp))) { int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen; struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_ns + 1); /* 8 byte alignments... */ optlen = (optlen + 7) & ~7; m->m_pkthdr.len += optlen; m->m_len += optlen; icmp6len += optlen; bzero((caddr_t)nd_opt, optlen); nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; nd_opt->nd_opt_len = optlen >> 3; bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen); } /* * Add a Nonce option (RFC 3971) to detect looped back NS messages. * This behavior is documented as Enhanced Duplicate Address * Detection in RFC 7527. * net.inet6.ip6.dad_enhanced=0 disables this. */ if (V_dad_enhanced != 0 && nonce != NULL) { int optlen = sizeof(struct nd_opt_hdr) + ND_OPT_NONCE_LEN; struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_ns + 1); /* 8-byte alignment is required. */ optlen = (optlen + 7) & ~7; m->m_pkthdr.len += optlen; m->m_len += optlen; icmp6len += optlen; bzero((caddr_t)nd_opt, optlen); nd_opt->nd_opt_type = ND_OPT_NONCE; nd_opt->nd_opt_len = optlen >> 3; bcopy(nonce, (caddr_t)(nd_opt + 1), ND_OPT_NONCE_LEN); } ip6->ip6_plen = htons((u_short)icmp6len); nd_ns->nd_ns_cksum = 0; nd_ns->nd_ns_cksum = in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), icmp6len); if (send_sendso_input_hook != NULL) { mtag = m_tag_get(PACKET_TAG_ND_OUTGOING, sizeof(unsigned short), M_NOWAIT); if (mtag == NULL) goto bad; *(unsigned short *)(mtag + 1) = nd_ns->nd_ns_type; m_tag_prepend(m, mtag); } ip6_output(m, NULL, &ro, (nonce != NULL) ? IPV6_UNSPECSRC : 0, &im6o, NULL, NULL); icmp6_ifstat_inc(ifp, ifs6_out_msg); icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit); ICMP6STAT_INC(icp6s_outhist[ND_NEIGHBOR_SOLICIT]); /* We don't cache this route. */ RO_RTFREE(&ro); return; bad: if (ro.ro_rt) { RTFREE(ro.ro_rt); } m_freem(m); return; } #ifndef BURN_BRIDGES void nd6_ns_output(struct ifnet *ifp, const struct in6_addr *saddr6, const struct in6_addr *daddr6, const struct in6_addr *taddr6,uint8_t *nonce) { nd6_ns_output_fib(ifp, saddr6, daddr6, taddr6, nonce, RT_DEFAULT_FIB); } #endif /* * Neighbor advertisement input handling. * * Based on RFC 2461 * Based on RFC 2462 (duplicate address detection) * * the following items are not implemented yet: * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD) * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD) */ void nd6_na_input(struct mbuf *m, int off, int icmp6len) { struct ifnet *ifp = m->m_pkthdr.rcvif; struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); struct nd_neighbor_advert *nd_na; struct in6_addr daddr6 = ip6->ip6_dst; struct in6_addr taddr6; int flags; int is_router; int is_solicited; int is_override; char *lladdr = NULL; int lladdrlen = 0; int checklink = 0; struct ifaddr *ifa; struct llentry *ln = NULL; union nd_opts ndopts; struct mbuf *chain = NULL; struct sockaddr_in6 sin6; char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; if (ip6->ip6_hlim != 255) { nd6log((LOG_ERR, "nd6_na_input: invalid hlim (%d) from %s to %s on %s\n", ip6->ip6_hlim, ip6_sprintf(ip6bufs, &ip6->ip6_src), ip6_sprintf(ip6bufd, &ip6->ip6_dst), if_name(ifp))); goto bad; } #ifndef PULLDOWN_TEST IP6_EXTHDR_CHECK(m, off, icmp6len,); nd_na = (struct nd_neighbor_advert *)((caddr_t)ip6 + off); #else IP6_EXTHDR_GET(nd_na, struct nd_neighbor_advert *, m, off, icmp6len); if (nd_na == NULL) { ICMP6STAT_INC(icp6s_tooshort); return; } #endif flags = nd_na->nd_na_flags_reserved; is_router = ((flags & ND_NA_FLAG_ROUTER) != 0); is_solicited = ((flags & ND_NA_FLAG_SOLICITED) != 0); is_override = ((flags & ND_NA_FLAG_OVERRIDE) != 0); memset(&sin6, 0, sizeof(sin6)); taddr6 = nd_na->nd_na_target; if (in6_setscope(&taddr6, ifp, NULL)) goto bad; /* XXX: impossible */ if (IN6_IS_ADDR_MULTICAST(&taddr6)) { nd6log((LOG_ERR, "nd6_na_input: invalid target address %s\n", ip6_sprintf(ip6bufs, &taddr6))); goto bad; } if (IN6_IS_ADDR_MULTICAST(&daddr6)) if (is_solicited) { nd6log((LOG_ERR, "nd6_na_input: a solicited adv is multicasted\n")); goto bad; } icmp6len -= sizeof(*nd_na); nd6_option_init(nd_na + 1, icmp6len, &ndopts); if (nd6_options(&ndopts) < 0) { nd6log((LOG_INFO, "nd6_na_input: invalid ND option, ignored\n")); /* nd6_options have incremented stats */ goto freeit; } if (ndopts.nd_opts_tgt_lladdr) { lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1); lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3; } /* * This effectively disables the DAD check on a non-master CARP * address. */ if (ifp->if_carp) ifa = (*carp_iamatch6_p)(ifp, &taddr6); else ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6); /* * Target address matches one of my interface address. * * If my address is tentative, this means that there's somebody * already using the same address as mine. This indicates DAD failure. * This is defined in RFC 2462. * * Otherwise, process as defined in RFC 2461. */ if (ifa && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE)) { nd6_dad_na_input(ifa); ifa_free(ifa); goto freeit; } /* Just for safety, maybe unnecessary. */ if (ifa) { ifa_free(ifa); log(LOG_ERR, "nd6_na_input: duplicate IP6 address %s\n", ip6_sprintf(ip6bufs, &taddr6)); goto freeit; } if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { nd6log((LOG_INFO, "nd6_na_input: lladdrlen mismatch for %s " "(if %d, NA packet %d)\n", ip6_sprintf(ip6bufs, &taddr6), ifp->if_addrlen, lladdrlen - 2)); goto bad; } /* * If no neighbor cache entry is found, NA SHOULD silently be * discarded. */ IF_AFDATA_RLOCK(ifp); ln = nd6_lookup(&taddr6, LLE_EXCLUSIVE, ifp); IF_AFDATA_RUNLOCK(ifp); if (ln == NULL) { goto freeit; } if (ln->ln_state == ND6_LLINFO_INCOMPLETE) { /* * If the link-layer has address, and no lladdr option came, * discard the packet. */ if (ifp->if_addrlen && lladdr == NULL) { goto freeit; } /* * Record link-layer address, and update the state. */ if (lltable_try_set_entry_addr(ifp, ln, lladdr) == 0) { ln = NULL; goto freeit; } EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED); if (is_solicited) nd6_llinfo_setstate(ln, ND6_LLINFO_REACHABLE); else nd6_llinfo_setstate(ln, ND6_LLINFO_STALE); if ((ln->ln_router = is_router) != 0) { /* * This means a router's state has changed from * non-reachable to probably reachable, and might * affect the status of associated prefixes.. */ checklink = 1; } } else { int llchange; /* * Check if the link-layer address has changed or not. */ if (lladdr == NULL) llchange = 0; else { if (ln->la_flags & LLE_VALID) { if (bcmp(lladdr, &ln->ll_addr, ifp->if_addrlen)) llchange = 1; else llchange = 0; } else llchange = 1; } /* * This is VERY complex. Look at it with care. * * override solicit lladdr llchange action * (L: record lladdr) * * 0 0 n -- (2c) * 0 0 y n (2b) L * 0 0 y y (1) REACHABLE->STALE * 0 1 n -- (2c) *->REACHABLE * 0 1 y n (2b) L *->REACHABLE * 0 1 y y (1) REACHABLE->STALE * 1 0 n -- (2a) * 1 0 y n (2a) L * 1 0 y y (2a) L *->STALE * 1 1 n -- (2a) *->REACHABLE * 1 1 y n (2a) L *->REACHABLE * 1 1 y y (2a) L *->REACHABLE */ if (!is_override && (lladdr != NULL && llchange)) { /* (1) */ /* * If state is REACHABLE, make it STALE. * no other updates should be done. */ if (ln->ln_state == ND6_LLINFO_REACHABLE) nd6_llinfo_setstate(ln, ND6_LLINFO_STALE); goto freeit; } else if (is_override /* (2a) */ || (!is_override && (lladdr != NULL && !llchange)) /* (2b) */ || lladdr == NULL) { /* (2c) */ /* * Update link-local address, if any. */ if (lladdr != NULL) { int ret; ret = lltable_try_set_entry_addr(ifp, ln,lladdr); if (ret == 0) { ln = NULL; goto freeit; } EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED); } /* * If solicited, make the state REACHABLE. * If not solicited and the link-layer address was * changed, make it STALE. */ if (is_solicited) nd6_llinfo_setstate(ln, ND6_LLINFO_REACHABLE); else { if (lladdr != NULL && llchange) nd6_llinfo_setstate(ln, ND6_LLINFO_STALE); } } if (ln->ln_router && !is_router) { /* * The peer dropped the router flag. * Remove the sender from the Default Router List and * update the Destination Cache entries. */ struct nd_defrouter *dr; struct in6_addr *in6; in6 = &ln->r_l3addr.addr6; /* * Lock to protect the default router list. * XXX: this might be unnecessary, since this function * is only called under the network software interrupt * context. However, we keep it just for safety. */ dr = defrouter_lookup(in6, ln->lle_tbl->llt_ifp); if (dr) defrtrlist_del(dr); else if (ND_IFINFO(ln->lle_tbl->llt_ifp)->flags & ND6_IFF_ACCEPT_RTADV) { /* * Even if the neighbor is not in the default * router list, the neighbor may be used * as a next hop for some destinations * (e.g. redirect case). So we must * call rt6_flush explicitly. */ rt6_flush(&ip6->ip6_src, ifp); } } ln->ln_router = is_router; } /* XXX - QL * Does this matter? * rt->rt_flags &= ~RTF_REJECT; */ ln->la_asked = 0; if (ln->la_hold != NULL) nd6_grab_holdchain(ln, &chain, &sin6); freeit: if (ln != NULL) LLE_WUNLOCK(ln); if (chain != NULL) nd6_flush_holdchain(ifp, ifp, chain, &sin6); if (checklink) pfxlist_onlink_check(); m_freem(m); return; bad: if (ln != NULL) LLE_WUNLOCK(ln); ICMP6STAT_INC(icp6s_badna); m_freem(m); } /* * Neighbor advertisement output handling. * * Based on RFC 2461 * * the following items are not implemented yet: * - proxy advertisement delay rule (RFC2461 7.2.8, last paragraph, SHOULD) * - anycast advertisement delay rule (RFC2461 7.2.7, SHOULD) * * tlladdr - 1 if include target link-layer address * sdl0 - sockaddr_dl (= proxy NA) or NULL */ static void nd6_na_output_fib(struct ifnet *ifp, const struct in6_addr *daddr6_0, const struct in6_addr *taddr6, u_long flags, int tlladdr, struct sockaddr *sdl0, u_int fibnum) { struct mbuf *m; struct m_tag *mtag; struct ifnet *oifp; struct ip6_hdr *ip6; struct nd_neighbor_advert *nd_na; struct ip6_moptions im6o; struct in6_addr src, daddr6; struct sockaddr_in6 dst_sa; int icmp6len, maxlen, error; caddr_t mac = NULL; struct route_in6 ro; bzero(&ro, sizeof(ro)); daddr6 = *daddr6_0; /* make a local copy for modification */ /* estimate the size of message */ maxlen = sizeof(*ip6) + sizeof(*nd_na); maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7; KASSERT(max_linkhdr + maxlen <= MCLBYTES, ( "%s: max_linkhdr + maxlen > MCLBYTES (%d + %d > %d)", __func__, max_linkhdr, maxlen, MCLBYTES)); if (max_linkhdr + maxlen > MHLEN) m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); else m = m_gethdr(M_NOWAIT, MT_DATA); if (m == NULL) return; M_SETFIB(m, fibnum); if (IN6_IS_ADDR_MULTICAST(&daddr6)) { m->m_flags |= M_MCAST; im6o.im6o_multicast_ifp = ifp; im6o.im6o_multicast_hlim = 255; im6o.im6o_multicast_loop = 0; } icmp6len = sizeof(*nd_na); m->m_pkthdr.len = m->m_len = sizeof(struct ip6_hdr) + icmp6len; m->m_data += max_linkhdr; /* or M_ALIGN() equivalent? */ /* fill neighbor advertisement packet */ ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_flow = 0; ip6->ip6_vfc &= ~IPV6_VERSION_MASK; ip6->ip6_vfc |= IPV6_VERSION; ip6->ip6_nxt = IPPROTO_ICMPV6; ip6->ip6_hlim = 255; if (IN6_IS_ADDR_UNSPECIFIED(&daddr6)) { /* reply to DAD */ daddr6.s6_addr16[0] = IPV6_ADDR_INT16_MLL; daddr6.s6_addr16[1] = 0; daddr6.s6_addr32[1] = 0; daddr6.s6_addr32[2] = 0; daddr6.s6_addr32[3] = IPV6_ADDR_INT32_ONE; if (in6_setscope(&daddr6, ifp, NULL)) goto bad; flags &= ~ND_NA_FLAG_SOLICITED; } ip6->ip6_dst = daddr6; bzero(&dst_sa, sizeof(struct sockaddr_in6)); dst_sa.sin6_family = AF_INET6; dst_sa.sin6_len = sizeof(struct sockaddr_in6); dst_sa.sin6_addr = daddr6; /* * Select a source whose scope is the same as that of the dest. */ bcopy(&dst_sa, &ro.ro_dst, sizeof(dst_sa)); oifp = ifp; error = in6_selectsrc(&dst_sa, NULL, NULL, &ro, NULL, &oifp, &src); if (error) { char ip6buf[INET6_ADDRSTRLEN]; nd6log((LOG_DEBUG, "nd6_na_output: source can't be " "determined: dst=%s, error=%d\n", ip6_sprintf(ip6buf, &dst_sa.sin6_addr), error)); goto bad; } ip6->ip6_src = src; nd_na = (struct nd_neighbor_advert *)(ip6 + 1); nd_na->nd_na_type = ND_NEIGHBOR_ADVERT; nd_na->nd_na_code = 0; nd_na->nd_na_target = *taddr6; in6_clearscope(&nd_na->nd_na_target); /* XXX */ /* * "tlladdr" indicates NS's condition for adding tlladdr or not. * see nd6_ns_input() for details. * Basically, if NS packet is sent to unicast/anycast addr, * target lladdr option SHOULD NOT be included. */ if (tlladdr) { /* * sdl0 != NULL indicates proxy NA. If we do proxy, use * lladdr in sdl0. If we are not proxying (sending NA for * my address) use lladdr configured for the interface. */ if (sdl0 == NULL) { if (ifp->if_carp) mac = (*carp_macmatch6_p)(ifp, m, taddr6); if (mac == NULL) mac = nd6_ifptomac(ifp); } else if (sdl0->sa_family == AF_LINK) { struct sockaddr_dl *sdl; sdl = (struct sockaddr_dl *)sdl0; if (sdl->sdl_alen == ifp->if_addrlen) mac = LLADDR(sdl); } } if (tlladdr && mac) { int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen; struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_na + 1); /* roundup to 8 bytes alignment! */ optlen = (optlen + 7) & ~7; m->m_pkthdr.len += optlen; m->m_len += optlen; icmp6len += optlen; bzero((caddr_t)nd_opt, optlen); nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; nd_opt->nd_opt_len = optlen >> 3; bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen); } else flags &= ~ND_NA_FLAG_OVERRIDE; ip6->ip6_plen = htons((u_short)icmp6len); nd_na->nd_na_flags_reserved = flags; nd_na->nd_na_cksum = 0; nd_na->nd_na_cksum = in6_cksum(m, IPPROTO_ICMPV6, sizeof(struct ip6_hdr), icmp6len); if (send_sendso_input_hook != NULL) { mtag = m_tag_get(PACKET_TAG_ND_OUTGOING, sizeof(unsigned short), M_NOWAIT); if (mtag == NULL) goto bad; *(unsigned short *)(mtag + 1) = nd_na->nd_na_type; m_tag_prepend(m, mtag); } ip6_output(m, NULL, &ro, 0, &im6o, NULL, NULL); icmp6_ifstat_inc(ifp, ifs6_out_msg); icmp6_ifstat_inc(ifp, ifs6_out_neighboradvert); ICMP6STAT_INC(icp6s_outhist[ND_NEIGHBOR_ADVERT]); /* We don't cache this route. */ RO_RTFREE(&ro); return; bad: if (ro.ro_rt) { RTFREE(ro.ro_rt); } m_freem(m); return; } #ifndef BURN_BRIDGES void nd6_na_output(struct ifnet *ifp, const struct in6_addr *daddr6_0, const struct in6_addr *taddr6, u_long flags, int tlladdr, struct sockaddr *sdl0) { nd6_na_output_fib(ifp, daddr6_0, taddr6, flags, tlladdr, sdl0, RT_DEFAULT_FIB); } #endif caddr_t nd6_ifptomac(struct ifnet *ifp) { switch (ifp->if_type) { case IFT_ARCNET: case IFT_ETHER: case IFT_FDDI: case IFT_IEEE1394: case IFT_L2VLAN: case IFT_IEEE80211: case IFT_INFINIBAND: case IFT_BRIDGE: case IFT_ISO88025: return IF_LLADDR(ifp); default: return NULL; } } struct dadq { TAILQ_ENTRY(dadq) dad_list; struct ifaddr *dad_ifa; int dad_count; /* max NS to send */ int dad_ns_tcount; /* # of trials to send NS */ int dad_ns_ocount; /* NS sent so far */ int dad_ns_icount; int dad_na_icount; int dad_ns_lcount; /* looped back NS */ int dad_loopbackprobe; /* probing state for loopback detection */ struct callout dad_timer_ch; struct vnet *dad_vnet; u_int dad_refcnt; #define ND_OPT_NONCE_LEN32 \ ((ND_OPT_NONCE_LEN + sizeof(uint32_t) - 1)/sizeof(uint32_t)) uint32_t dad_nonce[ND_OPT_NONCE_LEN32]; }; static VNET_DEFINE(TAILQ_HEAD(, dadq), dadq); static VNET_DEFINE(struct rwlock, dad_rwlock); #define V_dadq VNET(dadq) #define V_dad_rwlock VNET(dad_rwlock) #define DADQ_RLOCK() rw_rlock(&V_dad_rwlock) #define DADQ_RUNLOCK() rw_runlock(&V_dad_rwlock) #define DADQ_WLOCK() rw_wlock(&V_dad_rwlock) #define DADQ_WUNLOCK() rw_wunlock(&V_dad_rwlock) static void nd6_dad_add(struct dadq *dp) { DADQ_WLOCK(); TAILQ_INSERT_TAIL(&V_dadq, dp, dad_list); DADQ_WUNLOCK(); } static void nd6_dad_del(struct dadq *dp) { DADQ_WLOCK(); TAILQ_REMOVE(&V_dadq, dp, dad_list); DADQ_WUNLOCK(); nd6_dad_rele(dp); } static struct dadq * nd6_dad_find(struct ifaddr *ifa, struct nd_opt_nonce *n) { struct dadq *dp; DADQ_RLOCK(); TAILQ_FOREACH(dp, &V_dadq, dad_list) { if (dp->dad_ifa != ifa) continue; /* * Skip if the nonce matches the received one. * +2 in the length is required because of type and * length fields are included in a header. */ if (n != NULL && n->nd_opt_nonce_len == (ND_OPT_NONCE_LEN + 2) / 8 && memcmp(&n->nd_opt_nonce[0], &dp->dad_nonce[0], ND_OPT_NONCE_LEN) == 0) { dp->dad_ns_lcount++; continue; } refcount_acquire(&dp->dad_refcnt); break; } DADQ_RUNLOCK(); return (dp); } static void nd6_dad_starttimer(struct dadq *dp, int ticks, int send_ns) { if (send_ns != 0) nd6_dad_ns_output(dp); callout_reset(&dp->dad_timer_ch, ticks, (void (*)(void *))nd6_dad_timer, (void *)dp); } static void nd6_dad_stoptimer(struct dadq *dp) { callout_drain(&dp->dad_timer_ch); } static void nd6_dad_rele(struct dadq *dp) { if (refcount_release(&dp->dad_refcnt)) { ifa_free(dp->dad_ifa); free(dp, M_IP6NDP); } } void nd6_dad_init(void) { rw_init(&V_dad_rwlock, "nd6 DAD queue"); TAILQ_INIT(&V_dadq); } /* * Start Duplicate Address Detection (DAD) for specified interface address. */ void nd6_dad_start(struct ifaddr *ifa, int delay) { struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa; struct dadq *dp; char ip6buf[INET6_ADDRSTRLEN]; int send_ns; /* * If we don't need DAD, don't do it. * There are several cases: * - DAD is disabled (ip6_dad_count == 0) * - the interface address is anycast */ if (!(ia->ia6_flags & IN6_IFF_TENTATIVE)) { log(LOG_DEBUG, "nd6_dad_start: called with non-tentative address " "%s(%s)\n", ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr), ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); return; } if (ia->ia6_flags & IN6_IFF_ANYCAST) { ia->ia6_flags &= ~IN6_IFF_TENTATIVE; return; } if (!V_ip6_dad_count) { ia->ia6_flags &= ~IN6_IFF_TENTATIVE; return; } if (ifa->ifa_ifp == NULL) panic("nd6_dad_start: ifa->ifa_ifp == NULL"); if (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_NO_DAD) { ia->ia6_flags &= ~IN6_IFF_TENTATIVE; return; } if (!(ifa->ifa_ifp->if_flags & IFF_UP) || !(ifa->ifa_ifp->if_drv_flags & IFF_DRV_RUNNING) || (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_IFDISABLED)) { ia->ia6_flags |= IN6_IFF_TENTATIVE; return; } if ((dp = nd6_dad_find(ifa, NULL)) != NULL) { /* * DAD already in progress. Let the existing entry * to finish it. */ return; } dp = malloc(sizeof(*dp), M_IP6NDP, M_NOWAIT | M_ZERO); if (dp == NULL) { log(LOG_ERR, "nd6_dad_start: memory allocation failed for " "%s(%s)\n", ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr), ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); return; } callout_init(&dp->dad_timer_ch, 0); #ifdef VIMAGE dp->dad_vnet = curvnet; #endif nd6log((LOG_DEBUG, "%s: starting DAD for %s\n", if_name(ifa->ifa_ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr))); /* * Send NS packet for DAD, ip6_dad_count times. * Note that we must delay the first transmission, if this is the * first packet to be sent from the interface after interface * (re)initialization. */ dp->dad_ifa = ifa; ifa_ref(dp->dad_ifa); dp->dad_count = V_ip6_dad_count; dp->dad_ns_icount = dp->dad_na_icount = 0; dp->dad_ns_ocount = dp->dad_ns_tcount = 0; dp->dad_ns_lcount = dp->dad_loopbackprobe = 0; refcount_init(&dp->dad_refcnt, 1); nd6_dad_add(dp); send_ns = 0; if (delay == 0) { send_ns = 1; delay = (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000; } nd6_dad_starttimer(dp, delay, send_ns); } /* * terminate DAD unconditionally. used for address removals. */ void nd6_dad_stop(struct ifaddr *ifa) { struct dadq *dp; dp = nd6_dad_find(ifa, NULL); if (!dp) { /* DAD wasn't started yet */ return; } nd6_dad_stoptimer(dp); /* * The DAD queue entry may have been removed by nd6_dad_timer() while * we were waiting for it to stop, so re-do the lookup. */ nd6_dad_rele(dp); if (nd6_dad_find(ifa, NULL) == NULL) return; nd6_dad_del(dp); nd6_dad_rele(dp); } static void nd6_dad_timer(struct dadq *dp) { CURVNET_SET(dp->dad_vnet); struct ifaddr *ifa = dp->dad_ifa; struct ifnet *ifp = dp->dad_ifa->ifa_ifp; struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa; char ip6buf[INET6_ADDRSTRLEN]; /* Sanity check */ if (ia == NULL) { log(LOG_ERR, "nd6_dad_timer: called with null parameter\n"); goto err; } if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) { /* Do not need DAD for ifdisabled interface. */ log(LOG_ERR, "nd6_dad_timer: cancel DAD on %s because of " "ND6_IFF_IFDISABLED.\n", ifp->if_xname); goto err; } if (ia->ia6_flags & IN6_IFF_DUPLICATED) { log(LOG_ERR, "nd6_dad_timer: called with duplicated address " "%s(%s)\n", ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr), ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); goto err; } if ((ia->ia6_flags & IN6_IFF_TENTATIVE) == 0) { log(LOG_ERR, "nd6_dad_timer: called with non-tentative address " "%s(%s)\n", ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr), ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); goto err; } /* Stop DAD if the interface is down even after dad_maxtry attempts. */ if ((dp->dad_ns_tcount > V_dad_maxtry) && (((ifp->if_flags & IFF_UP) == 0) || ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0))) { nd6log((LOG_INFO, "%s: could not run DAD " "because the interface was down or not running.\n", if_name(ifa->ifa_ifp))); goto err; } /* Need more checks? */ if (dp->dad_ns_ocount < dp->dad_count) { /* * We have more NS to go. Send NS packet for DAD. */ nd6_dad_starttimer(dp, (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000, 1); goto done; } else { /* * We have transmitted sufficient number of DAD packets. * See what we've got. */ if (dp->dad_ns_icount > 0 || dp->dad_na_icount > 0) /* We've seen NS or NA, means DAD has failed. */ nd6_dad_duplicated(ifa, dp); else if (V_dad_enhanced != 0 && dp->dad_ns_lcount > 0 && dp->dad_ns_lcount > dp->dad_loopbackprobe) { /* * Sec. 4.1 in RFC 7527 requires transmission of * additional probes until the loopback condition * becomes clear when a looped back probe is detected. */ log(LOG_ERR, "%s: a looped back NS message is " "detected during DAD for %s. " "Another DAD probes are being sent.\n", if_name(ifa->ifa_ifp), ip6_sprintf(ip6buf, IFA_IN6(ifa))); dp->dad_loopbackprobe = dp->dad_ns_lcount; /* * Send an NS immediately and increase dad_count by * V_nd6_mmaxtries - 1. */ dp->dad_count = dp->dad_ns_ocount + V_nd6_mmaxtries - 1; nd6_dad_starttimer(dp, (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000, 1); goto done; } else { /* * We are done with DAD. No NA came, no NS came. * No duplicate address found. Check IFDISABLED flag * again in case that it is changed between the * beginning of this function and here. */ if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) == 0) ia->ia6_flags &= ~IN6_IFF_TENTATIVE; nd6log((LOG_DEBUG, "%s: DAD complete for %s - no duplicates found\n", if_name(ifa->ifa_ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr))); if (dp->dad_ns_lcount > 0) log(LOG_ERR, "%s: DAD completed while " "a looped back NS message is detected " "during DAD for %s.\n", if_name(ifa->ifa_ifp), ip6_sprintf(ip6buf, IFA_IN6(ifa))); } } err: nd6_dad_del(dp); done: CURVNET_RESTORE(); } static void nd6_dad_duplicated(struct ifaddr *ifa, struct dadq *dp) { struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa; struct ifnet *ifp; char ip6buf[INET6_ADDRSTRLEN]; log(LOG_ERR, "%s: DAD detected duplicate IPv6 address %s: " "NS in/out/loopback=%d/%d/%d, NA in=%d\n", if_name(ifa->ifa_ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr), dp->dad_ns_icount, dp->dad_ns_ocount, dp->dad_ns_lcount, dp->dad_na_icount); ia->ia6_flags &= ~IN6_IFF_TENTATIVE; ia->ia6_flags |= IN6_IFF_DUPLICATED; ifp = ifa->ifa_ifp; log(LOG_ERR, "%s: DAD complete for %s - duplicate found\n", if_name(ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr)); log(LOG_ERR, "%s: manual intervention required\n", if_name(ifp)); /* * If the address is a link-local address formed from an interface * identifier based on the hardware address which is supposed to be * uniquely assigned (e.g., EUI-64 for an Ethernet interface), IP * operation on the interface SHOULD be disabled. * [RFC 4862, Section 5.4.5] */ if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr)) { struct in6_addr in6; /* * To avoid over-reaction, we only apply this logic when we are * very sure that hardware addresses are supposed to be unique. */ switch (ifp->if_type) { case IFT_ETHER: case IFT_FDDI: case IFT_ATM: case IFT_IEEE1394: case IFT_IEEE80211: case IFT_INFINIBAND: in6 = ia->ia_addr.sin6_addr; if (in6_get_hw_ifid(ifp, &in6) == 0 && IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, &in6)) { ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED; log(LOG_ERR, "%s: possible hardware address " "duplication detected, disable IPv6\n", if_name(ifp)); } break; } } } static void nd6_dad_ns_output(struct dadq *dp) { struct in6_ifaddr *ia = (struct in6_ifaddr *)dp->dad_ifa; struct ifnet *ifp = dp->dad_ifa->ifa_ifp; int i; dp->dad_ns_tcount++; if ((ifp->if_flags & IFF_UP) == 0) { return; } if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { return; } dp->dad_ns_ocount++; if (V_dad_enhanced != 0) { for (i = 0; i < ND_OPT_NONCE_LEN32; i++) dp->dad_nonce[i] = arc4random(); /* * XXXHRS: Note that in the case that * DupAddrDetectTransmits > 1, multiple NS messages with * different nonces can be looped back in an unexpected * order. The current implementation recognizes only * the latest nonce on the sender side. Practically it * should work well in almost all cases. */ } nd6_ns_output(ifp, NULL, NULL, &ia->ia_addr.sin6_addr, (uint8_t *)&dp->dad_nonce[0]); } static void nd6_dad_ns_input(struct ifaddr *ifa, struct nd_opt_nonce *ndopt_nonce) { struct in6_ifaddr *ia; struct ifnet *ifp; const struct in6_addr *taddr6; struct dadq *dp; if (ifa == NULL) panic("ifa == NULL in nd6_dad_ns_input"); ia = (struct in6_ifaddr *)ifa; ifp = ifa->ifa_ifp; taddr6 = &ia->ia_addr.sin6_addr; /* Ignore Nonce option when Enhanced DAD is disabled. */ if (V_dad_enhanced == 0) ndopt_nonce = NULL; dp = nd6_dad_find(ifa, ndopt_nonce); if (dp == NULL) return; dp->dad_ns_icount++; nd6_dad_rele(dp); } static void nd6_dad_na_input(struct ifaddr *ifa) { struct dadq *dp; if (ifa == NULL) panic("ifa == NULL in nd6_dad_na_input"); dp = nd6_dad_find(ifa, NULL); if (dp != NULL) { dp->dad_na_icount++; nd6_dad_rele(dp); } } - -/* - * Send unsolicited neighbor advertisements for all interface addresses to - * notify other nodes of changes. - * - * This is a noop if the interface isn't up. - */ -void __noinline -nd6_na_output_unsolicited(struct ifnet *ifp) -{ - int i, cnt, entries; - struct ifaddr *ifa; - struct ann { - struct in6_addr addr; - u_long flags; - int delay; - } *ann1, *head; - - if (!(ifp->if_flags & IFF_UP)) - return; - - entries = 8; - cnt = 0; - head = malloc(sizeof(struct ann) * entries, M_TEMP, M_WAITOK); - - /* Take a copy then process to avoid locking issues. */ - IF_ADDR_RLOCK(ifp); - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { - if (ifa->ifa_addr->sa_family != AF_INET6 || - IFA_ND6_NA_UNSOLICITED_SKIP(ifa)) - continue; - - if (cnt == entries) { - ann1 = (struct ann*)realloc(head, sizeof(struct ann) * - (entries + 8), M_TEMP, M_NOWAIT); - if (ann1 == NULL) { - log(LOG_INFO, "nd6_announce: realloc to %d " - "entries failed\n", entries + 8); - /* Process what we have. */ - break; - } - entries += 8; - head = ann1; - } - - ann1 = head + cnt; - bcopy(IFA_IN6(ifa), &ann1->addr, sizeof(ann1->addr)); - ann1->flags = IFA_ND6_NA_BASE_FLAGS(ifp, ifa); - ann1->delay = nd6_na_unsolicited_addr_delay(ifa); - cnt++; - } - IF_ADDR_RUNLOCK(ifp); - - for (i = 0; i < cnt;) { - ann1 = head + i; - nd6_na_output_unsolicited_addr(ifp, &ann1->addr, ann1->flags); - i++; - if (i == cnt) - break; - /* XXX DELAY needs to be done in taskqueue to avoid stalling. */ - //DELAY(ann1->delay); - } - free(head, M_TEMP); -} - -/* - * Return the delay required for announcements of the address as per RFC 4861. - */ -int -nd6_na_unsolicited_addr_delay(struct ifaddr *ifa) -{ - - if (IFA_IN6_FLAGS(ifa) & IN6_IFF_ANYCAST) { - /* - * Random value between 0 and MAX_ANYCAST_DELAY_TIME - * as per section 7.2.7. - */ - return (random() % IN6_MAX_ANYCAST_DELAY_TIME_MS); - } - - /* Small delay as per section 7.2.6. */ - return (IN6_BROADCAST_DELAY_TIME_MS); -} - -/* - * Send an unsolicited neighbor advertisement for an address to notify other - * nodes of changes. - */ -void __noinline -nd6_na_output_unsolicited_addr(struct ifnet *ifp, const struct in6_addr *addr, - u_long flags) -{ - int error; - struct in6_addr mcast; - - mcast = in6addr_linklocal_allnodes; - if ((error = in6_setscope(&mcast, ifp, NULL)) != 0) { - /* - * This shouldn't by possible as the only error is for loopback - * address which we're not using. - */ - log(LOG_INFO, "in6_setscope: on mcast failed: %d\n", error); - return; - } - nd6_na_output(ifp, &mcast, addr, flags, 1, NULL); -} - - Index: user/alc/PQ_LAUNDRY/sys/powerpc/conf/GENERIC64 =================================================================== --- user/alc/PQ_LAUNDRY/sys/powerpc/conf/GENERIC64 (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/powerpc/conf/GENERIC64 (revision 292449) @@ -1,219 +1,220 @@ # # GENERIC -- Generic kernel configuration file for FreeBSD/powerpc # # For more information on this file, please read the handbook section on # Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ cpu AIM ident GENERIC machine powerpc powerpc64 makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols makeoptions WITH_CTF=1 # Platform support options POWERMAC #NewWorld Apple PowerMacs options PS3 #Sony Playstation 3 options MAMBO #IBM Mambo Full System Simulator options PSERIES #PAPR-compliant systems (e.g. IBM p) options FDT #Flattened Device Tree options SCHED_ULE #ULE scheduler options PREEMPTION #Enable kernel thread preemption options INET #InterNETworking options INET6 #IPv6 communications protocols options SCTP #Stream Control Transmission Protocol options FFS #Berkeley Fast Filesystem options SOFTUPDATES #Enable FFS soft updates support options UFS_ACL #Support for access control lists options UFS_DIRHASH #Improve performance on big directories options UFS_GJOURNAL #Enable gjournal-based UFS journaling options QUOTA #Enable disk quotas for UFS options MD_ROOT #MD is a potential root device options NFSCL #Network Filesystem Client options NFSD #Network Filesystem Server options NFSLOCKD #Network Lock Manager options NFS_ROOT #NFS usable as root device options MSDOSFS #MSDOS Filesystem options CD9660 #ISO 9660 Filesystem options PROCFS #Process filesystem (requires PSEUDOFS) options PSEUDOFS #Pseudo-filesystem framework options GEOM_PART_APM #Apple Partition Maps. options GEOM_PART_GPT #GUID Partition Tables. options GEOM_LABEL #Provides labelization options COMPAT_FREEBSD32 #Compatible with FreeBSD/powerpc binaries options COMPAT_FREEBSD5 #Compatible with FreeBSD5 options COMPAT_FREEBSD6 #Compatible with FreeBSD6 options COMPAT_FREEBSD7 #Compatible with FreeBSD7 options COMPAT_FREEBSD9 # Compatible with FreeBSD9 options COMPAT_FREEBSD10 # Compatible with FreeBSD10 options SCSI_DELAY=5000 #Delay (in ms) before probing SCSI options KTRACE #ktrace(1) syscall trace support options STACK #stack(9) support options SYSVSHM #SYSV-style shared memory options SYSVMSG #SYSV-style message queues options SYSVSEM #SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions +options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed. options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4) options AUDIT # Security event auditing options CAPABILITY_MODE # Capsicum capability mode options CAPABILITIES # Capsicum capabilities options MAC # TrustedBSD MAC Framework options KDTRACE_HOOKS # Kernel DTrace hooks options DDB_CTF # Kernel ELF linker loads CTF data options INCLUDE_CONFIG_FILE # Include this file in kernel # Debugging support. Always need this: options KDB # Enable kernel debugger support. options KDB_TRACE # Print a stack trace for a panic. # For full debugger support use (turn off in stable branch): options DDB #Support DDB #options DEADLKRES #Enable the deadlock resolver options INVARIANTS #Enable calls of extra sanity checking options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS options WITNESS #Enable checks to detect deadlocks and cycles options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones # Make an SMP-capable kernel by default options SMP # Symmetric MultiProcessor Kernel # CPU frequency control device cpufreq # Standard busses device pci device agp # ATA controllers device ahci # AHCI-compatible SATA controllers device ata # Legacy ATA/SATA controllers device mvs # Marvell 88SX50XX/88SX60XX/88SX70XX/SoC SATA device siis # SiliconImage SiI3124/SiI3132/SiI3531 SATA # SCSI Controllers device ahc # AHA2940 and onboard AIC7xxx devices options AHC_ALLOW_MEMIO # Attempt to use memory mapped I/O options AHC_REG_PRETTY_PRINT # Print register bitfields in debug # output. Adds ~128k to driver. device isp # Qlogic family device ispfw # Firmware module for Qlogic host adapters device mpt # LSI-Logic MPT-Fusion device mps # LSI-Logic MPT-Fusion 2 device sym # NCR/Symbios/LSI Logic 53C8XX/53C1010/53C1510D # ATA/SCSI peripherals device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device sa # Sequential Access (tape etc) device cd # CD device pass # Passthrough device (direct ATA/SCSI access) # vt is the default console driver, resembling an SCO console device vt # Core console driver device kbdmux # Serial (COM) ports device scc device uart device uart_z8530 # Ethernet hardware device em # Intel PRO/1000 Gigabit Ethernet Family device igb # Intel PRO/1000 PCIE Server Gigabit Family device ix # Intel PRO/10GbE PCIE PF Ethernet Family device ixv # Intel PRO/10GbE PCIE VF Ethernet Family device glc # Sony Playstation 3 Ethernet device llan # IBM pSeries Virtual Ethernet # PCI Ethernet NICs that use the common MII bus controller code. device miibus # MII bus support device bge # Broadcom BCM570xx Gigabit Ethernet device gem # Sun GEM/Sun ERI/Apple GMAC device dc # DEC/Intel 21143 and various workalikes device fxp # Intel EtherExpress PRO/100B (82557, 82558) device re # RealTek 8139C+/8169/8169S/8110S device rl # RealTek 8129/8139 # Pseudo devices. device loop # Network loopback device random # Entropy device device ether # Ethernet support device vlan # 802.1Q VLAN support device tun # Packet tunnel. device md # Memory "disks" device ofwd # Open Firmware disks device gif # IPv6 and IPv4 tunneling device firmware # firmware assist module # The `bpf' device enables the Berkeley Packet Filter. # Be aware of the administrative consequences of enabling this! # Note that 'bpf' is required for DHCP. device bpf #Berkeley packet filter # USB support options USB_DEBUG # enable debug msgs device uhci # UHCI PCI->USB interface device ohci # OHCI PCI->USB interface device ehci # EHCI PCI->USB interface device usb # USB Bus (required) device uhid # "Human Interface Devices" device ukbd # Keyboard options KBD_INSTALL_CDEV # install a CDEV entry in /dev device ulpt # Printer device umass # Disks/Mass storage - Requires scbus and da0 device ums # Mouse device urio # Diamond Rio 500 MP3 player # USB Ethernet device aue # ADMtek USB Ethernet device axe # ASIX Electronics USB Ethernet device cdce # Generic USB over Ethernet device cue # CATC USB Ethernet device kue # Kawasaki LSI USB Ethernet # Wireless NIC cards options IEEE80211_SUPPORT_MESH options AH_SUPPORT_AR5416 # FireWire support device firewire # FireWire bus code device sbp # SCSI over FireWire (Requires scbus and da) device fwe # Ethernet over FireWire (non-standard!) # Misc device iicbus # I2C bus code device kiic # Keywest I2C device ad7417 # PowerMac7,2 temperature sensor device ds1631 # PowerMac11,2 temperature sensor device ds1775 # PowerMac7,2 temperature sensor device fcu # Apple Fan Control Unit device max6690 # PowerMac7,2 temperature sensor device powermac_nvram # Open Firmware configuration NVRAM device smu # Apple System Management Unit device atibl # ATI-based backlight driver for PowerBooks/iBooks device nvbl # nVidia-based backlight driver for PowerBooks/iBooks # ADB support device adb device pmu # Sound support device sound # Generic sound driver (required) device snd_ai2s # Apple I2S audio device snd_uaudio # USB Audio Index: user/alc/PQ_LAUNDRY/sys/riscv/include/_align.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/_align.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/_align.h (revision 292449) @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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 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. + * + * from: @(#)param.h 5.8 (Berkeley) 6/28/91 + * $FreeBSD$ + */ + +#ifndef _MACHINE__ALIGN_H_ +#define _MACHINE__ALIGN_H_ + +/* + * Round p (pointer or byte index) up to a correctly-aligned value + * for all data types (int, long, ...). The result is unsigned int + * and must be cast to any desired pointer type. + */ +#define _ALIGNBYTES (sizeof(long long) - 1) +#define _ALIGN(p) (((u_long)(p) + _ALIGNBYTES) & ~_ALIGNBYTES) + +#endif /* !_MACHINE__ALIGN_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/_align.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/_bus.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/_bus.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/_bus.h (revision 292449) @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2005 M. Warner Losh. + * 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, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE__BUS_H_ +#define _MACHINE__BUS_H_ + +/* + * Addresses (in bus space). + */ +typedef u_long bus_addr_t; +typedef u_long bus_size_t; + +/* + * Access methods for bus space. + */ +typedef u_long bus_space_handle_t; +typedef struct bus_space *bus_space_tag_t; + +#endif /* !_MACHINE__BUS_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/_bus.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/_inttypes.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/_inttypes.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/_inttypes.h (revision 292449) @@ -0,0 +1,213 @@ +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Klaus Klein. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + * + * From: $NetBSD: int_fmtio.h,v 1.4 2008/04/28 20:23:36 martin Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE__INTTYPES_H_ +#define _MACHINE__INTTYPES_H_ + +/* + * Macros for format specifiers. + */ + +/* fprintf(3) macros for signed integers. */ + +#define PRId8 "d" /* int8_t */ +#define PRId16 "d" /* int16_t */ +#define PRId32 "d" /* int32_t */ +#define PRId64 "ld" /* int64_t */ +#define PRIdLEAST8 "d" /* int_least8_t */ +#define PRIdLEAST16 "d" /* int_least16_t */ +#define PRIdLEAST32 "d" /* int_least32_t */ +#define PRIdLEAST64 "ld" /* int_least64_t */ +#define PRIdFAST8 "d" /* int_fast8_t */ +#define PRIdFAST16 "d" /* int_fast16_t */ +#define PRIdFAST32 "d" /* int_fast32_t */ +#define PRIdFAST64 "ld" /* int_fast64_t */ +#define PRIdMAX "jd" /* intmax_t */ +#define PRIdPTR "ld" /* intptr_t */ + +#define PRIi8 "i" /* int8_t */ +#define PRIi16 "i" /* int16_t */ +#define PRIi32 "i" /* int32_t */ +#define PRIi64 "li" /* int64_t */ +#define PRIiLEAST8 "i" /* int_least8_t */ +#define PRIiLEAST16 "i" /* int_least16_t */ +#define PRIiLEAST32 "i" /* int_least32_t */ +#define PRIiLEAST64 "li" /* int_least64_t */ +#define PRIiFAST8 "i" /* int_fast8_t */ +#define PRIiFAST16 "i" /* int_fast16_t */ +#define PRIiFAST32 "i" /* int_fast32_t */ +#define PRIiFAST64 "li" /* int_fast64_t */ +#define PRIiMAX "ji" /* intmax_t */ +#define PRIiPTR "li" /* intptr_t */ + +/* fprintf(3) macros for unsigned integers. */ + +#define PRIo8 "o" /* uint8_t */ +#define PRIo16 "o" /* uint16_t */ +#define PRIo32 "o" /* uint32_t */ +#define PRIo64 "lo" /* uint64_t */ +#define PRIoLEAST8 "o" /* uint_least8_t */ +#define PRIoLEAST16 "o" /* uint_least16_t */ +#define PRIoLEAST32 "o" /* uint_least32_t */ +#define PRIoLEAST64 "lo" /* uint_least64_t */ +#define PRIoFAST8 "o" /* uint_fast8_t */ +#define PRIoFAST16 "o" /* uint_fast16_t */ +#define PRIoFAST32 "o" /* uint_fast32_t */ +#define PRIoFAST64 "lo" /* uint_fast64_t */ +#define PRIoMAX "jo" /* uintmax_t */ +#define PRIoPTR "lo" /* uintptr_t */ + +#define PRIu8 "u" /* uint8_t */ +#define PRIu16 "u" /* uint16_t */ +#define PRIu32 "u" /* uint32_t */ +#define PRIu64 "lu" /* uint64_t */ +#define PRIuLEAST8 "u" /* uint_least8_t */ +#define PRIuLEAST16 "u" /* uint_least16_t */ +#define PRIuLEAST32 "u" /* uint_least32_t */ +#define PRIuLEAST64 "lu" /* uint_least64_t */ +#define PRIuFAST8 "u" /* uint_fast8_t */ +#define PRIuFAST16 "u" /* uint_fast16_t */ +#define PRIuFAST32 "u" /* uint_fast32_t */ +#define PRIuFAST64 "lu" /* uint_fast64_t */ +#define PRIuMAX "ju" /* uintmax_t */ +#define PRIuPTR "lu" /* uintptr_t */ + +#define PRIx8 "x" /* uint8_t */ +#define PRIx16 "x" /* uint16_t */ +#define PRIx32 "x" /* uint32_t */ +#define PRIx64 "lx" /* uint64_t */ +#define PRIxLEAST8 "x" /* uint_least8_t */ +#define PRIxLEAST16 "x" /* uint_least16_t */ +#define PRIxLEAST32 "x" /* uint_least32_t */ +#define PRIxLEAST64 "lx" /* uint_least64_t */ +#define PRIxFAST8 "x" /* uint_fast8_t */ +#define PRIxFAST16 "x" /* uint_fast16_t */ +#define PRIxFAST32 "x" /* uint_fast32_t */ +#define PRIxFAST64 "lx" /* uint_fast64_t */ +#define PRIxMAX "jx" /* uintmax_t */ +#define PRIxPTR "lx" /* uintptr_t */ + +#define PRIX8 "X" /* uint8_t */ +#define PRIX16 "X" /* uint16_t */ +#define PRIX32 "X" /* uint32_t */ +#define PRIX64 "lX" /* uint64_t */ +#define PRIXLEAST8 "X" /* uint_least8_t */ +#define PRIXLEAST16 "X" /* uint_least16_t */ +#define PRIXLEAST32 "X" /* uint_least32_t */ +#define PRIXLEAST64 "lX" /* uint_least64_t */ +#define PRIXFAST8 "X" /* uint_fast8_t */ +#define PRIXFAST16 "X" /* uint_fast16_t */ +#define PRIXFAST32 "X" /* uint_fast32_t */ +#define PRIXFAST64 "lX" /* uint_fast64_t */ +#define PRIXMAX "jX" /* uintmax_t */ +#define PRIXPTR "lX" /* uintptr_t */ + +/* fscanf(3) macros for signed integers. */ + +#define SCNd8 "hhd" /* int8_t */ +#define SCNd16 "hd" /* int16_t */ +#define SCNd32 "d" /* int32_t */ +#define SCNd64 "ld" /* int64_t */ +#define SCNdLEAST8 "hhd" /* int_least8_t */ +#define SCNdLEAST16 "hd" /* int_least16_t */ +#define SCNdLEAST32 "d" /* int_least32_t */ +#define SCNdLEAST64 "ld" /* int_least64_t */ +#define SCNdFAST8 "d" /* int_fast8_t */ +#define SCNdFAST16 "d" /* int_fast16_t */ +#define SCNdFAST32 "d" /* int_fast32_t */ +#define SCNdFAST64 "ld" /* int_fast64_t */ +#define SCNdMAX "jd" /* intmax_t */ +#define SCNdPTR "ld" /* intptr_t */ + +#define SCNi8 "hhi" /* int8_t */ +#define SCNi16 "hi" /* int16_t */ +#define SCNi32 "i" /* int32_t */ +#define SCNi64 "li" /* int64_t */ +#define SCNiLEAST8 "hhi" /* int_least8_t */ +#define SCNiLEAST16 "hi" /* int_least16_t */ +#define SCNiLEAST32 "i" /* int_least32_t */ +#define SCNiLEAST64 "li" /* int_least64_t */ +#define SCNiFAST8 "i" /* int_fast8_t */ +#define SCNiFAST16 "i" /* int_fast16_t */ +#define SCNiFAST32 "i" /* int_fast32_t */ +#define SCNiFAST64 "li" /* int_fast64_t */ +#define SCNiMAX "ji" /* intmax_t */ +#define SCNiPTR "li" /* intptr_t */ + +/* fscanf(3) macros for unsigned integers. */ + +#define SCNo8 "hho" /* uint8_t */ +#define SCNo16 "ho" /* uint16_t */ +#define SCNo32 "o" /* uint32_t */ +#define SCNo64 "lo" /* uint64_t */ +#define SCNoLEAST8 "hho" /* uint_least8_t */ +#define SCNoLEAST16 "ho" /* uint_least16_t */ +#define SCNoLEAST32 "o" /* uint_least32_t */ +#define SCNoLEAST64 "lo" /* uint_least64_t */ +#define SCNoFAST8 "o" /* uint_fast8_t */ +#define SCNoFAST16 "o" /* uint_fast16_t */ +#define SCNoFAST32 "o" /* uint_fast32_t */ +#define SCNoFAST64 "lo" /* uint_fast64_t */ +#define SCNoMAX "jo" /* uintmax_t */ +#define SCNoPTR "lo" /* uintptr_t */ + +#define SCNu8 "hhu" /* uint8_t */ +#define SCNu16 "hu" /* uint16_t */ +#define SCNu32 "u" /* uint32_t */ +#define SCNu64 "lu" /* uint64_t */ +#define SCNuLEAST8 "hhu" /* uint_least8_t */ +#define SCNuLEAST16 "hu" /* uint_least16_t */ +#define SCNuLEAST32 "u" /* uint_least32_t */ +#define SCNuLEAST64 "lu" /* uint_least64_t */ +#define SCNuFAST8 "u" /* uint_fast8_t */ +#define SCNuFAST16 "u" /* uint_fast16_t */ +#define SCNuFAST32 "u" /* uint_fast32_t */ +#define SCNuFAST64 "lu" /* uint_fast64_t */ +#define SCNuMAX "ju" /* uintmax_t */ +#define SCNuPTR "lu" /* uintptr_t */ + +#define SCNx8 "hhx" /* uint8_t */ +#define SCNx16 "hx" /* uint16_t */ +#define SCNx32 "x" /* uint32_t */ +#define SCNx64 "lx" /* uint64_t */ +#define SCNxLEAST8 "hhx" /* uint_least8_t */ +#define SCNxLEAST16 "hx" /* uint_least16_t */ +#define SCNxLEAST32 "x" /* uint_least32_t */ +#define SCNxLEAST64 "lx" /* uint_least64_t */ +#define SCNxFAST8 "x" /* uint_fast8_t */ +#define SCNxFAST16 "x" /* uint_fast16_t */ +#define SCNxFAST32 "x" /* uint_fast32_t */ +#define SCNxFAST64 "lx" /* uint_fast64_t */ +#define SCNxMAX "jx" /* uintmax_t */ +#define SCNxPTR "lx" /* uintptr_t */ + +#endif /* !_MACHINE__INTTYPES_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/_inttypes.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/_limits.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/_limits.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/_limits.h (revision 292449) @@ -0,0 +1,85 @@ +/*- + * Copyright (c) 1988, 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. + * + * 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. + * + * @(#)limits.h 8.3 (Berkeley) 1/4/94 + * $FreeBSD$ + */ + +#ifndef _MACHINE__LIMITS_H_ +#define _MACHINE__LIMITS_H_ + +/* + * According to ANSI (section 2.2.4.2), the values below must be usable by + * #if preprocessing directives. Additionally, the expression must have the + * same type as would an expression that is an object of the corresponding + * type converted according to the integral promotions. The subtraction for + * INT_MIN, etc., is so the value is not unsigned; e.g., 0x80000000 is an + * unsigned int for 32-bit two's complement ANSI compilers (section 3.1.3.2). + */ + +#define __CHAR_BIT 8 /* number of bits in a char */ + +#define __SCHAR_MAX 0x7f /* max value for a signed char */ +#define __SCHAR_MIN (-0x7f - 1) /* min value for a signed char */ + +#define __UCHAR_MAX 0xff /* max value for an unsigned char */ + +#define __USHRT_MAX 0xffff /* max value for an unsigned short */ +#define __SHRT_MAX 0x7fff /* max value for a short */ +#define __SHRT_MIN (-0x7fff - 1) /* min value for a short */ + +#define __UINT_MAX 0xffffffff /* max value for an unsigned int */ +#define __INT_MAX 0x7fffffff /* max value for an int */ +#define __INT_MIN (-0x7fffffff - 1) /* min value for an int */ + +#define __ULONG_MAX 0xffffffffffffffffUL /* max for an unsigned long */ +#define __LONG_MAX 0x7fffffffffffffffL /* max for a long */ +#define __LONG_MIN (-0x7fffffffffffffffL - 1) /* min for a long */ + +/* Long longs have the same size but not the same type as longs. */ + /* max for an unsigned long long */ +#define __ULLONG_MAX 0xffffffffffffffffULL +#define __LLONG_MAX 0x7fffffffffffffffLL /* max for a long long */ +#define __LLONG_MIN (-0x7fffffffffffffffLL - 1) /* min for a long long */ + +#define __SSIZE_MAX __LONG_MAX /* max value for a ssize_t */ + +#define __SIZE_T_MAX __ULONG_MAX /* max value for a size_t */ + +#define __OFF_MAX __LONG_MAX /* max value for an off_t */ +#define __OFF_MIN __LONG_MIN /* min value for an off_t */ + +/* Quads and longs are the same size. Ensure they stay in sync. */ +#define __UQUAD_MAX (__ULONG_MAX) /* max value for a uquad_t */ +#define __QUAD_MAX (__LONG_MAX) /* max value for a quad_t */ +#define __QUAD_MIN (__LONG_MIN) /* min value for a quad_t */ + +#define __LONG_BIT 64 +#define __WORD_BIT 32 + +/* Minimum signal stack size. */ +#define __MINSIGSTKSZ (1024 * 4) + +#endif /* !_MACHINE__LIMITS_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/_limits.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/_stdint.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/_stdint.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/_stdint.h (revision 292449) @@ -0,0 +1,158 @@ +/*- + * Copyright (c) 2001, 2002 Mike Barcroft + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Klaus Klein. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE__STDINT_H_ +#define _MACHINE__STDINT_H_ + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) + +#define INT8_C(c) (c) +#define INT16_C(c) (c) +#define INT32_C(c) (c) +#define INT64_C(c) (c ## L) + +#define UINT8_C(c) (c) +#define UINT16_C(c) (c) +#define UINT32_C(c) (c ## U) +#define UINT64_C(c) (c ## UL) + +#define INTMAX_C(c) INT64_C(c) +#define UINTMAX_C(c) UINT64_C(c) + +#endif /* !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) */ + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) + +/* + * ISO/IEC 9899:1999 + * 7.18.2.1 Limits of exact-width integer types + */ +/* Minimum values of exact-width signed integer types. */ +#define INT8_MIN (-0x7f-1) +#define INT16_MIN (-0x7fff-1) +#define INT32_MIN (-0x7fffffff-1) +#define INT64_MIN (-0x7fffffffffffffffL-1) + +/* Maximum values of exact-width signed integer types. */ +#define INT8_MAX 0x7f +#define INT16_MAX 0x7fff +#define INT32_MAX 0x7fffffff +#define INT64_MAX 0x7fffffffffffffffL + +/* Maximum values of exact-width unsigned integer types. */ +#define UINT8_MAX 0xff +#define UINT16_MAX 0xffff +#define UINT32_MAX 0xffffffffU +#define UINT64_MAX 0xffffffffffffffffUL + +/* + * ISO/IEC 9899:1999 + * 7.18.2.2 Limits of minimum-width integer types + */ +/* Minimum values of minimum-width signed integer types. */ +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +/* Maximum values of minimum-width signed integer types. */ +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +/* Maximum values of minimum-width unsigned integer types. */ +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +/* + * ISO/IEC 9899:1999 + * 7.18.2.3 Limits of fastest minimum-width integer types + */ +/* Minimum values of fastest minimum-width signed integer types. */ +#define INT_FAST8_MIN INT32_MIN +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST64_MIN INT64_MIN + +/* Maximum values of fastest minimum-width signed integer types. */ +#define INT_FAST8_MAX INT32_MAX +#define INT_FAST16_MAX INT32_MAX +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MAX INT64_MAX + +/* Maximum values of fastest minimum-width unsigned integer types. */ +#define UINT_FAST8_MAX UINT32_MAX +#define UINT_FAST16_MAX UINT32_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +/* + * ISO/IEC 9899:1999 + * 7.18.2.4 Limits of integer types capable of holding object pointers + */ +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX + +/* + * ISO/IEC 9899:1999 + * 7.18.2.5 Limits of greatest-width integer types + */ +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +/* + * ISO/IEC 9899:1999 + * 7.18.3 Limits of other integer types + */ +/* Limits of ptrdiff_t. */ +#define PTRDIFF_MIN INT64_MIN +#define PTRDIFF_MAX INT64_MAX + +/* Limits of sig_atomic_t. */ +#define SIG_ATOMIC_MIN INT32_MIN +#define SIG_ATOMIC_MAX INT32_MAX + +/* Limit of size_t. */ +#define SIZE_MAX UINT64_MAX + +/* Limits of wint_t. */ +#define WINT_MIN INT32_MIN +#define WINT_MAX INT32_MAX + +#endif /* !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) */ + +#endif /* !_MACHINE__STDINT_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/_stdint.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/_types.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/_types.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/_types.h (revision 292449) @@ -0,0 +1,114 @@ +/*- + * Copyright (c) 2002 Mike Barcroft + * Copyright (c) 1990, 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. 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. + * + * From: @(#)ansi.h 8.2 (Berkeley) 1/4/94 + * From: @(#)types.h 8.3 (Berkeley) 1/5/94 + * $FreeBSD$ + */ + +#ifndef _MACHINE__TYPES_H_ +#define _MACHINE__TYPES_H_ + +#ifndef _SYS_CDEFS_H_ +#error this file needs sys/cdefs.h as a prerequisite +#endif + +/* + * Basic types upon which most other types are built. + */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +typedef long __int64_t; +typedef unsigned long __uint64_t; + +/* + * Standard type definitions. + */ +typedef __int32_t __clock_t; /* clock()... */ +typedef __int64_t __critical_t; +typedef double __double_t; +typedef float __float_t; +typedef __int64_t __intfptr_t; +typedef __int64_t __intmax_t; +typedef __int64_t __intptr_t; +typedef __int32_t __int_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __int8_t __int_least8_t; +typedef __int16_t __int_least16_t; +typedef __int32_t __int_least32_t; +typedef __int64_t __int_least64_t; +typedef __int64_t __ptrdiff_t; /* ptr1 - ptr2 */ +typedef __int64_t __register_t; +typedef __int64_t __segsz_t; /* segment size (in pages) */ +typedef __uint64_t __size_t; /* sizeof() */ +typedef __int64_t __ssize_t; /* byte count or error */ +typedef __int64_t __time_t; /* time()... */ +typedef __uint64_t __uintfptr_t; +typedef __uint64_t __uintmax_t; +typedef __uint64_t __uintptr_t; +typedef __uint32_t __uint_fast8_t; +typedef __uint32_t __uint_fast16_t; +typedef __uint32_t __uint_fast32_t; +typedef __uint64_t __uint_fast64_t; +typedef __uint8_t __uint_least8_t; +typedef __uint16_t __uint_least16_t; +typedef __uint32_t __uint_least32_t; +typedef __uint64_t __uint_least64_t; +typedef __uint64_t __u_register_t; +typedef __uint64_t __vm_offset_t; +typedef __int64_t __vm_ooffset_t; +typedef __uint64_t __vm_paddr_t; +typedef __uint64_t __vm_pindex_t; +typedef __uint64_t __vm_size_t; +typedef int ___wchar_t; + +#define __WCHAR_MIN __INT_MIN /* min value for a wchar_t */ +#define __WCHAR_MAX __INT_MAX /* max value for a wchar_t */ + +/* + * Unusual type definitions. + */ +#ifdef __GNUCLIKE_BUILTIN_VARARGS +typedef __builtin_va_list __va_list; /* internally known to gcc */ +#else +typedef char * __va_list; +#endif /* __GNUCLIKE_BUILTIN_VARARGS */ +#if defined(__GNUCLIKE_BUILTIN_VAALIST) && !defined(__GNUC_VA_LIST) \ + && !defined(__NO_GNUC_VA_LIST) +#define __GNUC_VA_LIST +typedef __va_list __gnuc_va_list; /* compatibility w/GNU headers*/ +#endif + +#endif /* !_MACHINE__TYPES_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/_types.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/asm.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/asm.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/asm.h (revision 292449) @@ -0,0 +1,68 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_ASM_H_ +#define _MACHINE_ASM_H_ + +#undef __FBSDID +#if !defined(lint) && !defined(STRIP_FBSDID) +#define __FBSDID(s) .ident s +#else +#define __FBSDID(s) /* nothing */ +#endif /* not lint and not STRIP_FBSDID */ + +#define _C_LABEL(x) x + +#define ENTRY(sym) \ + .text; .globl sym; .type sym,@function; .align 2; sym: +#define END(sym) .size sym, . - sym + +#define EENTRY(sym) \ + .globl sym; sym: +#define EEND(sym) + +#define WEAK_REFERENCE(sym, alias) \ + .weak alias; \ + .set alias,sym + +#define SET_FAULT_HANDLER(handler, tmp) \ + la tmp, pcpup; \ + ld tmp, 0(tmp); \ + ld tmp, PC_CURTHREAD(tmp); \ + ld tmp, TD_PCB(tmp); /* Load the pcb */ \ + sd handler, PCB_ONFAULT(tmp) /* Set the handler */ + +#endif /* _MACHINE_ASM_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/asm.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/atomic.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/atomic.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/atomic.h (revision 292449) @@ -0,0 +1,452 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +#define fence() __asm __volatile("fence" ::: "memory"); +#define mb() fence() +#define rmb() fence() +#define wmb() fence() + +#define ATOMIC_ACQ_REL(NAME, WIDTH) \ +static __inline void \ +atomic_##NAME##_acq_##WIDTH(__volatile uint##WIDTH##_t *p, uint##WIDTH##_t v)\ +{ \ + atomic_##NAME##_##WIDTH(p, v); \ + fence(); \ +} \ + \ +static __inline void \ +atomic_##NAME##_rel_##WIDTH(__volatile uint##WIDTH##_t *p, uint##WIDTH##_t v)\ +{ \ + fence(); \ + atomic_##NAME##_##WIDTH(p, v); \ +} + +static __inline void +atomic_add_32(volatile uint32_t *p, uint32_t val) +{ + + __asm __volatile("amoadd.w zero, %1, %0" + : "+A" (*p) + : "r" (val) + : "memory"); +} + +static __inline void +atomic_subtract_32(volatile uint32_t *p, uint32_t val) +{ + + __asm __volatile("amoadd.w zero, %1, %0" + : "+A" (*p) + : "r" (-val) + : "memory"); +} + +static __inline void +atomic_set_32(volatile uint32_t *p, uint32_t val) +{ + + __asm __volatile("amoor.w zero, %1, %0" + : "+A" (*p) + : "r" (val) + : "memory"); +} + +static __inline void +atomic_clear_32(volatile uint32_t *p, uint32_t val) +{ + + __asm __volatile("amoand.w zero, %1, %0" + : "+A" (*p) + : "r" (~val) + : "memory"); +} + +static __inline int +atomic_cmpset_32(volatile uint32_t *p, uint32_t cmpval, uint32_t newval) +{ + uint32_t tmp; + int res; + + res = 0; + + __asm __volatile( + "0:" + "li %1, 1\n" /* Preset to fail */ + "lr.w %0, %2\n" + "bne %0, %z3, 1f\n" + "sc.w %1, %z4, %2\n" + "bnez %1, 0b\n" + "1:" + : "=&r" (tmp), "=&r" (res), "+A" (*p) + : "rJ" (cmpval), "rJ" (newval) + : "memory"); + + return (!res); +} + +static __inline uint32_t +atomic_fetchadd_32(volatile uint32_t *p, uint32_t val) +{ + uint32_t ret; + + __asm __volatile("amoadd.w %0, %2, %1" + : "=&r" (ret), "+A" (*p) + : "r" (val) + : "memory"); + + return (ret); +} + +static __inline uint32_t +atomic_readandclear_32(volatile uint32_t *p) +{ + uint32_t ret; + uint32_t val; + + val = 0; + + __asm __volatile("amoswap.w %0, %2, %1" + : "=&r"(ret), "+A" (*p) + : "r" (val) + : "memory"); + + return (ret); +} + +#define atomic_add_int atomic_add_32 +#define atomic_clear_int atomic_clear_32 +#define atomic_cmpset_int atomic_cmpset_32 +#define atomic_fetchadd_int atomic_fetchadd_32 +#define atomic_readandclear_int atomic_readandclear_32 +#define atomic_set_int atomic_set_32 +#define atomic_subtract_int atomic_subtract_32 + +ATOMIC_ACQ_REL(set, 32) +ATOMIC_ACQ_REL(clear, 32) +ATOMIC_ACQ_REL(add, 32) +ATOMIC_ACQ_REL(subtract, 32) + +static __inline int +atomic_cmpset_acq_32(volatile uint32_t *p, uint32_t cmpval, uint32_t newval) +{ + int res; + + res = atomic_cmpset_32(p, cmpval, newval); + + fence(); + + return (res); +} + +static __inline int +atomic_cmpset_rel_32(volatile uint32_t *p, uint32_t cmpval, uint32_t newval) +{ + + fence(); + + return (atomic_cmpset_32(p, cmpval, newval)); +} + +static __inline uint32_t +atomic_load_acq_32(volatile uint32_t *p) +{ + uint32_t ret; + + ret = *p; + + fence(); + + return (ret); +} + +static __inline void +atomic_store_rel_32(volatile uint32_t *p, uint32_t val) +{ + + fence(); + + *p = val; +} + +#define atomic_add_acq_int atomic_add_acq_32 +#define atomic_clear_acq_int atomic_clear_acq_32 +#define atomic_cmpset_acq_int atomic_cmpset_acq_32 +#define atomic_load_acq_int atomic_load_acq_32 +#define atomic_set_acq_int atomic_set_acq_32 +#define atomic_subtract_acq_int atomic_subtract_acq_32 + +#define atomic_add_rel_int atomic_add_rel_32 +#define atomic_clear_rel_int atomic_add_rel_32 +#define atomic_cmpset_rel_int atomic_cmpset_rel_32 +#define atomic_set_rel_int atomic_set_rel_32 +#define atomic_subtract_rel_int atomic_subtract_rel_32 +#define atomic_store_rel_int atomic_store_rel_32 + +static __inline void +atomic_add_64(volatile uint64_t *p, uint64_t val) +{ + + __asm __volatile("amoadd.d zero, %1, %0" + : "+A" (*p) + : "r" (val) + : "memory"); +} + +static __inline void +atomic_subtract_64(volatile uint64_t *p, uint64_t val) +{ + + __asm __volatile("amoadd.d zero, %1, %0" + : "+A" (*p) + : "r" (-val) + : "memory"); +} + +static __inline void +atomic_set_64(volatile uint64_t *p, uint64_t val) +{ + + __asm __volatile("amoor.d zero, %1, %0" + : "+A" (*p) + : "r" (val) + : "memory"); +} + +static __inline void +atomic_clear_64(volatile uint64_t *p, uint64_t val) +{ + + __asm __volatile("amoand.d zero, %1, %0" + : "+A" (*p) + : "r" (~val) + : "memory"); +} + +static __inline int +atomic_cmpset_64(volatile uint64_t *p, uint64_t cmpval, uint64_t newval) +{ + uint64_t tmp; + int res; + + res = 0; + + __asm __volatile( + "0:" + "li %1, 1\n" /* Preset to fail */ + "lr.d %0, %2\n" + "bne %0, %z3, 1f\n" + "sc.d %1, %z4, %2\n" + "bnez %1, 0b\n" + "1:" + : "=&r" (tmp), "=&r" (res), "+A" (*p) + : "rJ" (cmpval), "rJ" (newval) + : "memory"); + + return (!res); +} + +static __inline uint64_t +atomic_fetchadd_64(volatile uint64_t *p, uint64_t val) +{ + uint64_t ret; + + __asm __volatile("amoadd.d %0, %2, %1" + : "=&r" (ret), "+A" (*p) + : "r" (val) + : "memory"); + + return (ret); +} + +static __inline uint64_t +atomic_readandclear_64(volatile uint64_t *p) +{ + uint64_t ret; + uint64_t val; + + val = 0; + + __asm __volatile("amoswap.d %0, %2, %1" + : "=&r"(ret), "+A" (*p) + : "r" (val) + : "memory"); + + return (ret); +} + +static __inline uint64_t +atomic_swap_64(volatile uint64_t *p, uint64_t val) +{ + uint64_t old; + + __asm __volatile("amoswap.d %0, %2, %1" + : "=&r"(old), "+A" (*p) + : "r" (val) + : "memory"); + + return (old); +} + +#define atomic_add_long atomic_add_64 +#define atomic_clear_long atomic_clear_64 +#define atomic_cmpset_long atomic_cmpset_64 +#define atomic_fetchadd_long atomic_fetchadd_64 +#define atomic_readandclear_long atomic_readandclear_64 +#define atomic_set_long atomic_set_64 +#define atomic_subtract_long atomic_subtract_64 + +#define atomic_add_ptr atomic_add_64 +#define atomic_clear_ptr atomic_clear_64 +#define atomic_cmpset_ptr atomic_cmpset_64 +#define atomic_fetchadd_ptr atomic_fetchadd_64 +#define atomic_readandclear_ptr atomic_readandclear_64 +#define atomic_set_ptr atomic_set_64 +#define atomic_subtract_ptr atomic_subtract_64 + +ATOMIC_ACQ_REL(set, 64) +ATOMIC_ACQ_REL(clear, 64) +ATOMIC_ACQ_REL(add, 64) +ATOMIC_ACQ_REL(subtract, 64) + +static __inline int +atomic_cmpset_acq_64(volatile uint64_t *p, uint64_t cmpval, uint64_t newval) +{ + int res; + + res = atomic_cmpset_64(p, cmpval, newval); + + fence(); + + return (res); +} + +static __inline int +atomic_cmpset_rel_64(volatile uint64_t *p, uint64_t cmpval, uint64_t newval) +{ + + fence(); + + return (atomic_cmpset_64(p, cmpval, newval)); +} + +static __inline uint64_t +atomic_load_acq_64(volatile uint64_t *p) +{ + uint64_t ret; + + ret = *p; + + fence(); + + return (ret); +} + +static __inline void +atomic_store_rel_64(volatile uint64_t *p, uint64_t val) +{ + + fence(); + + *p = val; +} + +#define atomic_add_acq_int atomic_add_acq_32 +#define atomic_clear_acq_int atomic_clear_acq_32 +#define atomic_cmpset_acq_int atomic_cmpset_acq_32 + +#define atomic_add_acq_long atomic_add_acq_64 +#define atomic_clear_acq_long atomic_add_acq_64 +#define atomic_cmpset_acq_long atomic_cmpset_acq_64 +#define atomic_load_acq_long atomic_load_acq_64 +#define atomic_set_acq_long atomic_set_acq_64 +#define atomic_subtract_acq_long atomic_subtract_acq_64 + +#define atomic_add_acq_ptr atomic_add_acq_64 +#define atomic_clear_acq_ptr atomic_add_acq_64 +#define atomic_cmpset_acq_ptr atomic_cmpset_acq_64 +#define atomic_load_acq_ptr atomic_load_acq_64 +#define atomic_set_acq_ptr atomic_set_acq_64 +#define atomic_subtract_acq_ptr atomic_subtract_acq_64 + +static __inline void +atomic_thread_fence_acq(void) +{ + + fence(); +} + +static __inline void +atomic_thread_fence_rel(void) +{ + + fence(); +} + +static __inline void +atomic_thread_fence_acq_rel(void) +{ + + fence(); +} + +static __inline void +atomic_thread_fence_seq_cst(void) +{ + + fence(); +} + +#define atomic_add_rel_long atomic_add_rel_64 +#define atomic_clear_rel_long atomic_clear_rel_64 + +#define atomic_add_rel_long atomic_add_rel_64 +#define atomic_clear_rel_long atomic_clear_rel_64 +#define atomic_cmpset_rel_long atomic_cmpset_rel_64 +#define atomic_set_rel_long atomic_set_rel_64 +#define atomic_subtract_rel_long atomic_subtract_rel_64 +#define atomic_store_rel_long atomic_store_rel_64 + +#define atomic_add_rel_ptr atomic_add_rel_64 +#define atomic_clear_rel_ptr atomic_clear_rel_64 +#define atomic_cmpset_rel_ptr atomic_cmpset_rel_64 +#define atomic_set_rel_ptr atomic_set_rel_64 +#define atomic_subtract_rel_ptr atomic_subtract_rel_64 +#define atomic_store_rel_ptr atomic_store_rel_64 + +#endif /* _MACHINE_ATOMIC_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/atomic.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/bus.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/bus.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/bus.h (revision 292449) @@ -0,0 +1,469 @@ +/* $NetBSD: bus.h,v 1.11 2003/07/28 17:35:54 thorpej Exp $ */ + +/*- + * Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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) 1996 Charles M. Hannum. All rights reserved. + * Copyright (c) 1996 Christopher G. Demetriou. 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 Christopher G. Demetriou + * for the NetBSD Project. + * 4. 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 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. + * + * From: sys/arm/include/bus.h + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#include + +#define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t) + +#define BUS_SPACE_MAXADDR_24BIT 0xFFFFFFUL +#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFFUL +#define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFFUL +#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFFUL + +#define BUS_SPACE_MAXADDR 0xFFFFFFFFFFFFFFFFUL +#define BUS_SPACE_MAXSIZE 0xFFFFFFFFFFFFFFFFUL + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_LINEAR 0x02 +#define BUS_SPACE_MAP_PREFETCHABLE 0x04 + +#define BUS_SPACE_UNRESTRICTED (~0) + +#define BUS_SPACE_BARRIER_READ 0x01 +#define BUS_SPACE_BARRIER_WRITE 0x02 + + +struct bus_space { + /* cookie */ + void *bs_cookie; + + /* mapping/unmapping */ + int (*bs_map) (void *, bus_addr_t, bus_size_t, + int, bus_space_handle_t *); + void (*bs_unmap) (void *, bus_space_handle_t, bus_size_t); + int (*bs_subregion) (void *, bus_space_handle_t, + bus_size_t, bus_size_t, bus_space_handle_t *); + + /* allocation/deallocation */ + int (*bs_alloc) (void *, bus_addr_t, bus_addr_t, + bus_size_t, bus_size_t, bus_size_t, int, + bus_addr_t *, bus_space_handle_t *); + void (*bs_free) (void *, bus_space_handle_t, + bus_size_t); + + /* get kernel virtual address */ + /* barrier */ + void (*bs_barrier) (void *, bus_space_handle_t, + bus_size_t, bus_size_t, int); + + /* read single */ + u_int8_t (*bs_r_1) (void *, bus_space_handle_t, bus_size_t); + u_int16_t (*bs_r_2) (void *, bus_space_handle_t, bus_size_t); + u_int32_t (*bs_r_4) (void *, bus_space_handle_t, bus_size_t); + u_int64_t (*bs_r_8) (void *, bus_space_handle_t, bus_size_t); + + /* read multiple */ + void (*bs_rm_1) (void *, bus_space_handle_t, bus_size_t, + u_int8_t *, bus_size_t); + void (*bs_rm_2) (void *, bus_space_handle_t, bus_size_t, + u_int16_t *, bus_size_t); + void (*bs_rm_4) (void *, bus_space_handle_t, + bus_size_t, u_int32_t *, bus_size_t); + void (*bs_rm_8) (void *, bus_space_handle_t, + bus_size_t, u_int64_t *, bus_size_t); + + /* read region */ + void (*bs_rr_1) (void *, bus_space_handle_t, + bus_size_t, u_int8_t *, bus_size_t); + void (*bs_rr_2) (void *, bus_space_handle_t, + bus_size_t, u_int16_t *, bus_size_t); + void (*bs_rr_4) (void *, bus_space_handle_t, + bus_size_t, u_int32_t *, bus_size_t); + void (*bs_rr_8) (void *, bus_space_handle_t, + bus_size_t, u_int64_t *, bus_size_t); + + /* write single */ + void (*bs_w_1) (void *, bus_space_handle_t, + bus_size_t, u_int8_t); + void (*bs_w_2) (void *, bus_space_handle_t, + bus_size_t, u_int16_t); + void (*bs_w_4) (void *, bus_space_handle_t, + bus_size_t, u_int32_t); + void (*bs_w_8) (void *, bus_space_handle_t, + bus_size_t, u_int64_t); + + /* write multiple */ + void (*bs_wm_1) (void *, bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t); + void (*bs_wm_2) (void *, bus_space_handle_t, + bus_size_t, const u_int16_t *, bus_size_t); + void (*bs_wm_4) (void *, bus_space_handle_t, + bus_size_t, const u_int32_t *, bus_size_t); + void (*bs_wm_8) (void *, bus_space_handle_t, + bus_size_t, const u_int64_t *, bus_size_t); + + /* write region */ + void (*bs_wr_1) (void *, bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t); + void (*bs_wr_2) (void *, bus_space_handle_t, + bus_size_t, const u_int16_t *, bus_size_t); + void (*bs_wr_4) (void *, bus_space_handle_t, + bus_size_t, const u_int32_t *, bus_size_t); + void (*bs_wr_8) (void *, bus_space_handle_t, + bus_size_t, const u_int64_t *, bus_size_t); + + /* set multiple */ + void (*bs_sm_1) (void *, bus_space_handle_t, + bus_size_t, u_int8_t, bus_size_t); + void (*bs_sm_2) (void *, bus_space_handle_t, + bus_size_t, u_int16_t, bus_size_t); + void (*bs_sm_4) (void *, bus_space_handle_t, + bus_size_t, u_int32_t, bus_size_t); + void (*bs_sm_8) (void *, bus_space_handle_t, + bus_size_t, u_int64_t, bus_size_t); + + /* set region */ + void (*bs_sr_1) (void *, bus_space_handle_t, + bus_size_t, u_int8_t, bus_size_t); + void (*bs_sr_2) (void *, bus_space_handle_t, + bus_size_t, u_int16_t, bus_size_t); + void (*bs_sr_4) (void *, bus_space_handle_t, + bus_size_t, u_int32_t, bus_size_t); + void (*bs_sr_8) (void *, bus_space_handle_t, + bus_size_t, u_int64_t, bus_size_t); + + /* copy */ + void (*bs_c_1) (void *, bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t); + void (*bs_c_2) (void *, bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t); + void (*bs_c_4) (void *, bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t); + void (*bs_c_8) (void *, bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t); + + /* read single stream */ + u_int8_t (*bs_r_1_s) (void *, bus_space_handle_t, bus_size_t); + u_int16_t (*bs_r_2_s) (void *, bus_space_handle_t, bus_size_t); + u_int32_t (*bs_r_4_s) (void *, bus_space_handle_t, bus_size_t); + u_int64_t (*bs_r_8_s) (void *, bus_space_handle_t, bus_size_t); + + /* read multiple stream */ + void (*bs_rm_1_s) (void *, bus_space_handle_t, bus_size_t, + u_int8_t *, bus_size_t); + void (*bs_rm_2_s) (void *, bus_space_handle_t, bus_size_t, + u_int16_t *, bus_size_t); + void (*bs_rm_4_s) (void *, bus_space_handle_t, + bus_size_t, u_int32_t *, bus_size_t); + void (*bs_rm_8_s) (void *, bus_space_handle_t, + bus_size_t, u_int64_t *, bus_size_t); + + /* read region stream */ + void (*bs_rr_1_s) (void *, bus_space_handle_t, + bus_size_t, u_int8_t *, bus_size_t); + void (*bs_rr_2_s) (void *, bus_space_handle_t, + bus_size_t, u_int16_t *, bus_size_t); + void (*bs_rr_4_s) (void *, bus_space_handle_t, + bus_size_t, u_int32_t *, bus_size_t); + void (*bs_rr_8_s) (void *, bus_space_handle_t, + bus_size_t, u_int64_t *, bus_size_t); + + /* write single stream */ + void (*bs_w_1_s) (void *, bus_space_handle_t, + bus_size_t, u_int8_t); + void (*bs_w_2_s) (void *, bus_space_handle_t, + bus_size_t, u_int16_t); + void (*bs_w_4_s) (void *, bus_space_handle_t, + bus_size_t, u_int32_t); + void (*bs_w_8_s) (void *, bus_space_handle_t, + bus_size_t, u_int64_t); + + /* write multiple stream */ + void (*bs_wm_1_s) (void *, bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t); + void (*bs_wm_2_s) (void *, bus_space_handle_t, + bus_size_t, const u_int16_t *, bus_size_t); + void (*bs_wm_4_s) (void *, bus_space_handle_t, + bus_size_t, const u_int32_t *, bus_size_t); + void (*bs_wm_8_s) (void *, bus_space_handle_t, + bus_size_t, const u_int64_t *, bus_size_t); + + /* write region stream */ + void (*bs_wr_1_s) (void *, bus_space_handle_t, + bus_size_t, const u_int8_t *, bus_size_t); + void (*bs_wr_2_s) (void *, bus_space_handle_t, + bus_size_t, const u_int16_t *, bus_size_t); + void (*bs_wr_4_s) (void *, bus_space_handle_t, + bus_size_t, const u_int32_t *, bus_size_t); + void (*bs_wr_8_s) (void *, bus_space_handle_t, + bus_size_t, const u_int64_t *, bus_size_t); +}; + + +/* + * Utility macros; INTERNAL USE ONLY. + */ +#define __bs_c(a,b) __CONCAT(a,b) +#define __bs_opname(op,size) __bs_c(__bs_c(__bs_c(bs_,op),_),size) + +#define __bs_rs(sz, t, h, o) \ + (*(t)->__bs_opname(r,sz))((t)->bs_cookie, h, o) +#define __bs_ws(sz, t, h, o, v) \ + (*(t)->__bs_opname(w,sz))((t)->bs_cookie, h, o, v) +#define __bs_nonsingle(type, sz, t, h, o, a, c) \ + (*(t)->__bs_opname(type,sz))((t)->bs_cookie, h, o, a, c) +#define __bs_set(type, sz, t, h, o, v, c) \ + (*(t)->__bs_opname(type,sz))((t)->bs_cookie, h, o, v, c) +#define __bs_copy(sz, t, h1, o1, h2, o2, cnt) \ + (*(t)->__bs_opname(c,sz))((t)->bs_cookie, h1, o1, h2, o2, cnt) + +#define __bs_opname_s(op,size) __bs_c(__bs_c(__bs_c(__bs_c(bs_,op),_),size),_s) +#define __bs_rs_s(sz, t, h, o) \ + (*(t)->__bs_opname_s(r,sz))((t)->bs_cookie, h, o) +#define __bs_ws_s(sz, t, h, o, v) \ + (*(t)->__bs_opname_s(w,sz))((t)->bs_cookie, h, o, v) +#define __bs_nonsingle_s(type, sz, t, h, o, a, c) \ + (*(t)->__bs_opname_s(type,sz))((t)->bs_cookie, h, o, a, c) + + +/* + * Mapping and unmapping operations. + */ +#define bus_space_map(t, a, s, c, hp) \ + (*(t)->bs_map)((t)->bs_cookie, (a), (s), (c), (hp)) +#define bus_space_unmap(t, h, s) \ + (*(t)->bs_unmap)((t)->bs_cookie, (h), (s)) +#define bus_space_subregion(t, h, o, s, hp) \ + (*(t)->bs_subregion)((t)->bs_cookie, (h), (o), (s), (hp)) + + +/* + * Allocation and deallocation operations. + */ +#define bus_space_alloc(t, rs, re, s, a, b, c, ap, hp) \ + (*(t)->bs_alloc)((t)->bs_cookie, (rs), (re), (s), (a), (b), \ + (c), (ap), (hp)) +#define bus_space_free(t, h, s) \ + (*(t)->bs_free)((t)->bs_cookie, (h), (s)) + +/* + * Bus barrier operations. + */ +#define bus_space_barrier(t, h, o, l, f) \ + (*(t)->bs_barrier)((t)->bs_cookie, (h), (o), (l), (f)) + + + +/* + * Bus read (single) operations. + */ +#define bus_space_read_1(t, h, o) __bs_rs(1,(t),(h),(o)) +#define bus_space_read_2(t, h, o) __bs_rs(2,(t),(h),(o)) +#define bus_space_read_4(t, h, o) __bs_rs(4,(t),(h),(o)) +#define bus_space_read_8(t, h, o) __bs_rs(8,(t),(h),(o)) + +#define bus_space_read_stream_1(t, h, o) __bs_rs_s(1,(t), (h), (o)) +#define bus_space_read_stream_2(t, h, o) __bs_rs_s(2,(t), (h), (o)) +#define bus_space_read_stream_4(t, h, o) __bs_rs_s(4,(t), (h), (o)) +#define bus_space_read_stream_8(t, h, o) __bs_rs_s(8,8,(t),(h),(o)) + +/* + * Bus read multiple operations. + */ +#define bus_space_read_multi_1(t, h, o, a, c) \ + __bs_nonsingle(rm,1,(t),(h),(o),(a),(c)) +#define bus_space_read_multi_2(t, h, o, a, c) \ + __bs_nonsingle(rm,2,(t),(h),(o),(a),(c)) +#define bus_space_read_multi_4(t, h, o, a, c) \ + __bs_nonsingle(rm,4,(t),(h),(o),(a),(c)) +#define bus_space_read_multi_8(t, h, o, a, c) \ + __bs_nonsingle(rm,8,(t),(h),(o),(a),(c)) + +#define bus_space_read_multi_stream_1(t, h, o, a, c) \ + __bs_nonsingle_s(rm,1,(t),(h),(o),(a),(c)) +#define bus_space_read_multi_stream_2(t, h, o, a, c) \ + __bs_nonsingle_s(rm,2,(t),(h),(o),(a),(c)) +#define bus_space_read_multi_stream_4(t, h, o, a, c) \ + __bs_nonsingle_s(rm,4,(t),(h),(o),(a),(c)) +#define bus_space_read_multi_stream_8(t, h, o, a, c) \ + __bs_nonsingle_s(rm,8,(t),(h),(o),(a),(c)) + + +/* + * Bus read region operations. + */ +#define bus_space_read_region_1(t, h, o, a, c) \ + __bs_nonsingle(rr,1,(t),(h),(o),(a),(c)) +#define bus_space_read_region_2(t, h, o, a, c) \ + __bs_nonsingle(rr,2,(t),(h),(o),(a),(c)) +#define bus_space_read_region_4(t, h, o, a, c) \ + __bs_nonsingle(rr,4,(t),(h),(o),(a),(c)) +#define bus_space_read_region_8(t, h, o, a, c) \ + __bs_nonsingle(rr,8,(t),(h),(o),(a),(c)) + +#define bus_space_read_region_stream_1(t, h, o, a, c) \ + __bs_nonsingle_s(rr,1,(t),(h),(o),(a),(c)) +#define bus_space_read_region_stream_2(t, h, o, a, c) \ + __bs_nonsingle_s(rr,2,(t),(h),(o),(a),(c)) +#define bus_space_read_region_stream_4(t, h, o, a, c) \ + __bs_nonsingle_s(rr,4,(t),(h),(o),(a),(c)) +#define bus_space_read_region_stream_8(t, h, o, a, c) \ + __bs_nonsingle_s(rr,8,(t),(h),(o),(a),(c)) + + +/* + * Bus write (single) operations. + */ +#define bus_space_write_1(t, h, o, v) __bs_ws(1,(t),(h),(o),(v)) +#define bus_space_write_2(t, h, o, v) __bs_ws(2,(t),(h),(o),(v)) +#define bus_space_write_4(t, h, o, v) __bs_ws(4,(t),(h),(o),(v)) +#define bus_space_write_8(t, h, o, v) __bs_ws(8,(t),(h),(o),(v)) + +#define bus_space_write_stream_1(t, h, o, v) __bs_ws_s(1,(t),(h),(o),(v)) +#define bus_space_write_stream_2(t, h, o, v) __bs_ws_s(2,(t),(h),(o),(v)) +#define bus_space_write_stream_4(t, h, o, v) __bs_ws_s(4,(t),(h),(o),(v)) +#define bus_space_write_stream_8(t, h, o, v) __bs_ws_s(8,(t),(h),(o),(v)) + + +/* + * Bus write multiple operations. + */ +#define bus_space_write_multi_1(t, h, o, a, c) \ + __bs_nonsingle(wm,1,(t),(h),(o),(a),(c)) +#define bus_space_write_multi_2(t, h, o, a, c) \ + __bs_nonsingle(wm,2,(t),(h),(o),(a),(c)) +#define bus_space_write_multi_4(t, h, o, a, c) \ + __bs_nonsingle(wm,4,(t),(h),(o),(a),(c)) +#define bus_space_write_multi_8(t, h, o, a, c) \ + __bs_nonsingle(wm,8,(t),(h),(o),(a),(c)) + +#define bus_space_write_multi_stream_1(t, h, o, a, c) \ + __bs_nonsingle_s(wm,1,(t),(h),(o),(a),(c)) +#define bus_space_write_multi_stream_2(t, h, o, a, c) \ + __bs_nonsingle_s(wm,2,(t),(h),(o),(a),(c)) +#define bus_space_write_multi_stream_4(t, h, o, a, c) \ + __bs_nonsingle_s(wm,4,(t),(h),(o),(a),(c)) +#define bus_space_write_multi_stream_8(t, h, o, a, c) \ + __bs_nonsingle_s(wm,8,(t),(h),(o),(a),(c)) + + +/* + * Bus write region operations. + */ +#define bus_space_write_region_1(t, h, o, a, c) \ + __bs_nonsingle(wr,1,(t),(h),(o),(a),(c)) +#define bus_space_write_region_2(t, h, o, a, c) \ + __bs_nonsingle(wr,2,(t),(h),(o),(a),(c)) +#define bus_space_write_region_4(t, h, o, a, c) \ + __bs_nonsingle(wr,4,(t),(h),(o),(a),(c)) +#define bus_space_write_region_8(t, h, o, a, c) \ + __bs_nonsingle(wr,8,(t),(h),(o),(a),(c)) + +#define bus_space_write_region_stream_1(t, h, o, a, c) \ + __bs_nonsingle_s(wr,1,(t),(h),(o),(a),(c)) +#define bus_space_write_region_stream_2(t, h, o, a, c) \ + __bs_nonsingle_s(wr,2,(t),(h),(o),(a),(c)) +#define bus_space_write_region_stream_4(t, h, o, a, c) \ + __bs_nonsingle_s(wr,4,(t),(h),(o),(a),(c)) +#define bus_space_write_region_stream_8(t, h, o, a, c) \ + __bs_nonsingle_s(wr,8,(t),(h),(o),(a),(c)) + + +/* + * Set multiple operations. + */ +#define bus_space_set_multi_1(t, h, o, v, c) \ + __bs_set(sm,1,(t),(h),(o),(v),(c)) +#define bus_space_set_multi_2(t, h, o, v, c) \ + __bs_set(sm,2,(t),(h),(o),(v),(c)) +#define bus_space_set_multi_4(t, h, o, v, c) \ + __bs_set(sm,4,(t),(h),(o),(v),(c)) +#define bus_space_set_multi_8(t, h, o, v, c) \ + __bs_set(sm,8,(t),(h),(o),(v),(c)) + + +/* + * Set region operations. + */ +#define bus_space_set_region_1(t, h, o, v, c) \ + __bs_set(sr,1,(t),(h),(o),(v),(c)) +#define bus_space_set_region_2(t, h, o, v, c) \ + __bs_set(sr,2,(t),(h),(o),(v),(c)) +#define bus_space_set_region_4(t, h, o, v, c) \ + __bs_set(sr,4,(t),(h),(o),(v),(c)) +#define bus_space_set_region_8(t, h, o, v, c) \ + __bs_set(sr,8,(t),(h),(o),(v),(c)) + + +/* + * Copy operations. + */ +#define bus_space_copy_region_1(t, h1, o1, h2, o2, c) \ + __bs_copy(1, t, h1, o1, h2, o2, c) +#define bus_space_copy_region_2(t, h1, o1, h2, o2, c) \ + __bs_copy(2, t, h1, o1, h2, o2, c) +#define bus_space_copy_region_4(t, h1, o1, h2, o2, c) \ + __bs_copy(4, t, h1, o1, h2, o2, c) +#define bus_space_copy_region_8(t, h1, o1, h2, o2, c) \ + __bs_copy(8, t, h1, o1, h2, o2, c) + +#include + +#endif /* _MACHINE_BUS_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/bus.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/bus_dma.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/bus_dma.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/bus_dma.h (revision 292449) @@ -0,0 +1,8 @@ +/* $FreeBSD$ */ + +#ifndef _MACHINE_BUS_DMA_H_ +#define _MACHINE_BUS_DMA_H_ + +#include + +#endif /* !_MACHINE_BUS_DMA_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/bus_dma.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/clock.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/clock.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/clock.h (revision 292449) @@ -0,0 +1 @@ +/* $FreeBSD$ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/clock.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/counter.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/counter.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/counter.h (revision 292449) @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 2012 Konstantin Belousov + * 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 AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_COUNTER_H_ +#define _MACHINE_COUNTER_H_ + +#include +#ifdef INVARIANTS +#include +#endif + +#define counter_enter() critical_enter() +#define counter_exit() critical_exit() + +#ifdef IN_SUBR_COUNTER_C +static inline uint64_t +counter_u64_read_one(uint64_t *p, int cpu) +{ + + return (*(uint64_t *)((char *)p + sizeof(struct pcpu) * cpu)); +} + +static inline uint64_t +counter_u64_fetch_inline(uint64_t *p) +{ + uint64_t r; + int i; + + r = 0; + for (i = 0; i < mp_ncpus; i++) + r += counter_u64_read_one((uint64_t *)p, i); + + return (r); +} + +/* XXXKIB might interrupt increment */ +static void +counter_u64_zero_one_cpu(void *arg) +{ + + *((uint64_t *)((char *)arg + sizeof(struct pcpu) * + PCPU_GET(cpuid))) = 0; +} + +static inline void +counter_u64_zero_inline(counter_u64_t c) +{ + + smp_rendezvous(smp_no_rendevous_barrier, counter_u64_zero_one_cpu, + smp_no_rendevous_barrier, c); +} +#endif + +#define counter_u64_add_protected(c, inc) do { \ + CRITICAL_ASSERT(curthread); \ + *(uint64_t *)zpcpu_get(c) += (inc); \ +} while (0) + +static inline void +counter_u64_add(counter_u64_t c, int64_t inc) +{ + + counter_enter(); + counter_u64_add_protected(c, inc); + counter_exit(); +} + +#endif /* ! _MACHINE_COUNTER_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/counter.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/cpu.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/cpu.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/cpu.h (revision 292449) @@ -0,0 +1,95 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +#include +#include + +#define TRAPF_PC(tfp) ((tfp)->tf_ra) +#define TRAPF_USERMODE(tfp) (((tfp)->tf_sepc & (1ul << 63)) == 0) + +#define cpu_getstack(td) ((td)->td_frame->tf_sp) +#define cpu_setstack(td, sp) ((td)->td_frame->tf_sp = (sp)) +#define cpu_spinwait() /* nothing */ + +#ifdef _KERNEL + +/* + * 0x0000 CPU ID unimplemented + * 0x0001 UC Berkeley Rocket repo + * 0x0002­0x7FFE Reserved for open-source repos + * 0x7FFF Reserved for extension + * 0x8000 Reserved for anonymous source + * 0x8001­0xFFFE Reserved for proprietary implementations + * 0xFFFF Reserved for extension + */ + +#define CPU_IMPL_SHIFT 0 +#define CPU_IMPL_MASK (0xffff << CPU_IMPL_SHIFT) +#define CPU_IMPL(mimpid) ((mimpid & CPU_IMPL_MASK) >> CPU_IMPL_SHIFT) +#define CPU_IMPL_UNIMPLEMEN 0x0 +#define CPU_IMPL_UCB_ROCKET 0x1 + +#define CPU_PART_SHIFT 62 +#define CPU_PART_MASK (0x3ul << CPU_PART_SHIFT) +#define CPU_PART(mcpuid) ((mcpuid & CPU_PART_MASK) >> CPU_PART_SHIFT) +#define CPU_PART_RV32I 0x0 +#define CPU_PART_RV32E 0x1 +#define CPU_PART_RV64I 0x2 +#define CPU_PART_RV128I 0x3 + +extern char btext[]; +extern char etext[]; + +void cpu_halt(void) __dead2; +void cpu_reset(void) __dead2; +void fork_trampoline(void); +void identify_cpu(void); +void swi_vm(void *v); + +static __inline uint64_t +get_cyclecount(void) +{ + + /* TODO: This is bogus */ + return (1); +} + +#endif + +#endif /* !_MACHINE_CPU_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/cpu.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/cpufunc.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/cpufunc.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/cpufunc.h (revision 292449) @@ -0,0 +1,123 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_CPUFUNC_H_ +#define _MACHINE_CPUFUNC_H_ + +#ifdef _KERNEL + +#include + +static __inline void +breakpoint(void) +{ + + __asm("ebreak"); +} + +static __inline register_t +intr_disable(void) +{ + uint64_t ret; + + __asm __volatile( + "csrrci %0, sstatus, 1" + : "=&r" (ret) + ); + + return (ret & SSTATUS_IE); +} + +static __inline void +intr_restore(register_t s) +{ + + __asm __volatile( + "csrs sstatus, %0" + :: "r" (s) + ); +} + +static __inline void +intr_enable(void) +{ + + __asm __volatile( + "csrsi sstatus, 1" + ); +} + +static __inline register_t +machine_command(uint64_t cmd, uint64_t arg) +{ + uint64_t res; + + __asm __volatile( + "mv t5, %2\n" + "mv t6, %1\n" + "ecall\n" + "mv %0, t6" : "=&r"(res) : "r"(arg), "r"(cmd) + ); + + return (res); +} + +#define cpu_nullop() riscv_nullop() +#define cpufunc_nullop() riscv_nullop() +#define cpu_setttb(a) riscv_setttb(a) + +#define cpu_tlb_flushID() riscv_tlb_flushID() +#define cpu_tlb_flushID_SE(e) riscv_tlb_flushID_SE(e) + +#define cpu_dcache_wbinv_range(a, s) riscv_dcache_wbinv_range((a), (s)) +#define cpu_dcache_inv_range(a, s) riscv_dcache_inv_range((a), (s)) +#define cpu_dcache_wb_range(a, s) riscv_dcache_wb_range((a), (s)) + +#define cpu_idcache_wbinv_range(a, s) riscv_idcache_wbinv_range((a), (s)) +#define cpu_icache_sync_range(a, s) riscv_icache_sync_range((a), (s)) + +void riscv_nullop(void); +void riscv_setttb(vm_offset_t); +void riscv_tlb_flushID(void); +void riscv_tlb_flushID_SE(vm_offset_t); +void riscv_icache_sync_range(vm_offset_t, vm_size_t); +void riscv_idcache_wbinv_range(vm_offset_t, vm_size_t); +void riscv_dcache_wbinv_range(vm_offset_t, vm_size_t); +void riscv_dcache_inv_range(vm_offset_t, vm_size_t); +void riscv_dcache_wb_range(vm_offset_t, vm_size_t); + +#endif /* _KERNEL */ +#endif /* _MACHINE_CPUFUNC_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/cpufunc.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/db_machdep.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/db_machdep.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/db_machdep.h (revision 292449) @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_DB_MACHDEP_H_ +#define _MACHINE_DB_MACHDEP_H_ + +#include +#include +#include + +typedef vm_offset_t db_addr_t; +typedef long db_expr_t; + +#endif /* !_MACHINE_DB_MACHDEP_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/db_machdep.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/dump.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/dump.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/dump.h (revision 292449) @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2014 EMC Corp. + * Author: Conrad Meyer + * 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 AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_DUMP_H_ +#define _MACHINE_DUMP_H_ + +#define KERNELDUMP_ARCH_VERSION KERNELDUMP_RISCV_VERSION +#define EM_VALUE EM_RISCV + +/* 20 phys_avail entry pairs correspond to 10 pa's */ +#define DUMPSYS_MD_PA_NPAIRS 10 +#define DUMPSYS_NUM_AUX_HDRS 0 + +static inline void +dumpsys_pa_init(void) +{ + + dumpsys_gen_pa_init(); +} + +static inline struct dump_pa * +dumpsys_pa_next(struct dump_pa *p) +{ + + return (dumpsys_gen_pa_next(p)); +} + +static inline void +dumpsys_wbinv_all(void) +{ + + dumpsys_gen_wbinv_all(); +} + +static inline void +dumpsys_unmap_chunk(vm_paddr_t pa, size_t s, void *va) +{ + + dumpsys_gen_unmap_chunk(pa, s, va); +} + +static inline int +dumpsys_write_aux_headers(struct dumperinfo *di) +{ + + return (dumpsys_gen_write_aux_headers(di)); +} + +static inline int +dumpsys(struct dumperinfo *di) +{ + + return (dumpsys_generic(di)); +} + +#endif /* !_MACHINE_DUMP_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/dump.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/elf.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/elf.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/elf.h (revision 292449) @@ -0,0 +1,105 @@ +/*- + * Copyright (c) 1996-1997 John D. Polstra. + * 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 AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_ELF_H_ +#define _MACHINE_ELF_H_ + +/* + * ELF definitions for the RISC-V architecture. + */ + +#include /* Definitions common to all 32 bit architectures. */ +#include /* Definitions common to all 64 bit architectures. */ + +#define __ELF_WORD_SIZE 64 /* Used by */ +#include + +/* + * Auxiliary vector entries for passing information to the interpreter. + */ + +typedef struct { /* Auxiliary vector entry on initial stack */ + int a_type; /* Entry type. */ + union { + int a_val; /* Integer value. */ + } a_un; +} Elf32_Auxinfo; + +typedef struct { /* Auxiliary vector entry on initial stack */ + long a_type; /* Entry type. */ + union { + long a_val; /* Integer value. */ + void *a_ptr; /* Address. */ + void (*a_fcn)(void); /* Function pointer (not used). */ + } a_un; +} Elf64_Auxinfo; + +__ElfType(Auxinfo); + +#define ELF_ARCH EM_RISCV + +#define ELF_MACHINE_OK(x) ((x) == (ELF_ARCH)) + +/* Values for a_type. */ +#define AT_NULL 0 /* Terminates the vector. */ +#define AT_IGNORE 1 /* Ignored entry. */ +#define AT_EXECFD 2 /* File descriptor of program to load. */ +#define AT_PHDR 3 /* Program header of program already loaded. */ +#define AT_PHENT 4 /* Size of each program header entry. */ +#define AT_PHNUM 5 /* Number of program header entries. */ +#define AT_PAGESZ 6 /* Page size in bytes. */ +#define AT_BASE 7 /* Interpreter's base address. */ +#define AT_FLAGS 8 /* Flags (unused). */ +#define AT_ENTRY 9 /* Where interpreter should transfer control. */ +#define AT_NOTELF 10 /* Program is not ELF ?? */ +#define AT_UID 11 /* Real uid. */ +#define AT_EUID 12 /* Effective uid. */ +#define AT_GID 13 /* Real gid. */ +#define AT_EGID 14 /* Effective gid. */ +#define AT_EXECPATH 15 /* Path to the executable. */ +#define AT_CANARY 16 /* Canary for SSP */ +#define AT_CANARYLEN 17 /* Length of the canary. */ +#define AT_OSRELDATE 18 /* OSRELDATE. */ +#define AT_NCPUS 19 /* Number of CPUs. */ +#define AT_PAGESIZES 20 /* Pagesizes. */ +#define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ +#define AT_TIMEKEEP 22 /* Pointer to timehands. */ +#define AT_STACKPROT 23 /* Initial stack protection. */ + +#define AT_COUNT 24 /* Count of defined aux entry types. */ + +/* Define "machine" characteristics */ +#define ELF_TARG_CLASS ELFCLASS64 +#define ELF_TARG_DATA ELFDATA2LSB +#define ELF_TARG_MACH EM_RISCV +#define ELF_TARG_VER 1 + +/* TODO: set correct value */ +#define ET_DYN_LOAD_ADDR 0x100000 + +#endif /* !_MACHINE_ELF_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/elf.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/endian.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/endian.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/endian.h (revision 292449) @@ -0,0 +1,124 @@ +/*- + * Copyright (c) 2001 David E. O'Brien + * + * 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 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. + * + * @(#)endian.h 8.1 (Berkeley) 6/10/93 + * $NetBSD: endian.h,v 1.7 1999/08/21 05:53:51 simonb Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_ENDIAN_H_ +#define _MACHINE_ENDIAN_H_ + +#include + +/* + * Definitions for byte order, according to byte significance from low + * address to high. + */ +#define _LITTLE_ENDIAN 1234 /* LSB first: i386, vax */ +#define _BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */ +#define _PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */ + +#define _BYTE_ORDER _LITTLE_ENDIAN + +#if __BSD_VISIBLE +#define LITTLE_ENDIAN _LITTLE_ENDIAN +#define BIG_ENDIAN _BIG_ENDIAN +#define PDP_ENDIAN _PDP_ENDIAN +#define BYTE_ORDER _BYTE_ORDER +#endif + +#define _QUAD_HIGHWORD 1 +#define _QUAD_LOWWORD 0 +#define __ntohl(x) (__bswap32(x)) +#define __ntohs(x) (__bswap16(x)) +#define __htonl(x) (__bswap32(x)) +#define __htons(x) (__bswap16(x)) + +static __inline __uint64_t +__bswap64(__uint64_t _x) +{ + __uint64_t ret; + + ret = (_x >> 56); + ret |= ((_x >> 40) & 0xff00); + ret |= ((_x >> 24) & 0xff0000); + ret |= ((_x >> 8) & 0xff000000); + ret |= ((_x << 8) & ((__uint64_t)0xff << 32)); + ret |= ((_x << 24) & ((__uint64_t)0xff << 40)); + ret |= ((_x << 40) & ((__uint64_t)0xff << 48)); + ret |= (_x << 56); + + return (ret); +} + +static __inline __uint32_t +__bswap32_var(__uint32_t _x) +{ + + return ((_x >> 24) | ((_x >> 8) & 0xff00) | ((_x << 8) & 0xff0000) | + ((_x << 24) & 0xff000000)); +} + +static __inline __uint16_t +__bswap16_var(__uint16_t _x) +{ + __uint32_t ret; + + ret = ((_x >> 8) | ((_x << 8) & 0xff00)); + + return ((__uint16_t)ret); +} + +#ifdef __OPTIMIZE__ + +#define __bswap32_constant(x) \ + ((((x) & 0xff000000U) >> 24) | \ + (((x) & 0x00ff0000U) >> 8) | \ + (((x) & 0x0000ff00U) << 8) | \ + (((x) & 0x000000ffU) << 24)) + +#define __bswap16_constant(x) \ + ((((x) & 0xff00) >> 8) | \ + (((x) & 0x00ff) << 8)) + +#define __bswap16(x) \ + ((__uint16_t)(__builtin_constant_p(x) ? \ + __bswap16_constant(x) : \ + __bswap16_var(x))) + +#define __bswap32(x) \ + ((__uint32_t)(__builtin_constant_p(x) ? \ + __bswap32_constant(x) : \ + __bswap32_var(x))) + +#else +#define __bswap16(x) __bswap16_var(x) +#define __bswap32(x) __bswap32_var(x) + +#endif /* __OPTIMIZE__ */ +#endif /* !_MACHINE_ENDIAN_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/endian.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/exec.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/exec.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/exec.h (revision 292449) @@ -0,0 +1 @@ +/* $FreeBSD$ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/exec.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/float.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/float.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/float.h (revision 292449) @@ -0,0 +1,111 @@ +/*- + * Copyright (c) 1989 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. 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. + * + * from: @(#)float.h 7.1 (Berkeley) 5/8/90 + * $FreeBSD$ + */ + +#ifndef _MACHINE_FLOAT_H_ +#define _MACHINE_FLOAT_H_ + +#include + +__BEGIN_DECLS +extern int __flt_rounds(void); +__END_DECLS + +#define FLT_RADIX 2 /* b */ +#define FLT_ROUNDS __flt_rounds() +#if __ISO_C_VISIBLE >= 1999 +#define FLT_EVAL_METHOD 0 +#define DECIMAL_DIG 17 /* max precision in decimal digits */ +#endif + +#define FLT_MANT_DIG 24 /* p */ +#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define FLT_MIN_EXP (-125) /* emin */ +#define FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define FLT_MAX_EXP 128 /* emax */ +#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ +#if __ISO_C_VISIBLE >= 2011 +#define FLT_TRUE_MIN 1.40129846E-45F /* b**(emin-p) */ +#define FLT_DECIMAL_DIG 9 /* ceil(1+p*log10(b)) */ +#define FLT_HAS_SUBNORM 1 +#endif /* __ISO_C_VISIBLE >= 2011 */ + +#define DBL_MANT_DIG 53 +#define DBL_EPSILON 2.2204460492503131E-16 +#define DBL_DIG 15 +#define DBL_MIN_EXP (-1021) +#define DBL_MIN 2.2250738585072014E-308 +#define DBL_MIN_10_EXP (-307) +#define DBL_MAX_EXP 1024 +#define DBL_MAX 1.7976931348623157E+308 +#define DBL_MAX_10_EXP 308 +#if __ISO_C_VISIBLE >= 2011 +#define DBL_TRUE_MIN 4.9406564584124654E-324 +#define DBL_DECIMAL_DIG 17 +#define DBL_HAS_SUBNORM 1 +#endif /* __ISO_C_VISIBLE >= 2011 */ + +#define LDBL_MANT_DIG DBL_MANT_DIG +#define LDBL_EPSILON ((long double)DBL_EPSILON) +#define LDBL_DIG DBL_DIG +#define LDBL_MIN_EXP DBL_MIN_EXP +#define LDBL_MIN ((long double)DBL_MIN) +#define LDBL_MIN_10_EXP DBL_MIN_10_EXP +#define LDBL_MAX_EXP DBL_MAX_EXP +#define LDBL_MAX ((long double)DBL_MAX) +#define LDBL_MAX_10_EXP DBL_MAX_10_EXP +#if __ISO_C_VISIBLE >= 2011 +#define LDBL_TRUE_MIN ((long double)DBL_TRUE_MIN) +#define LDBL_DECIMAL_DIG DBL_DECIMAL_DIG +#define LDBL_HAS_SUBNORM DBL_HAS_SUBNORM +#endif /* __ISO_C_VISIBLE >= 2011 */ + +#if 0 /* RISCVTODO */ +#define LDBL_MANT_DIG 113 +#define LDBL_EPSILON 1.925929944387235853055977942584927319E-34L +#define LDBL_DIG 33 +#define LDBL_MIN_EXP (-16381) +#define LDBL_MIN 3.362103143112093506262677817321752603E-4932L +#define LDBL_MIN_10_EXP (-4931) +#define LDBL_MAX_EXP (+16384) +#define LDBL_MAX 1.189731495357231765085759326628007016E+4932L +#define LDBL_MAX_10_EXP (+4932) +#if __ISO_C_VISIBLE >= 2011 +#define LDBL_TRUE_MIN 6.475175119438025110924438958227646552E-4966L +#define LDBL_DECIMAL_DIG 36 +#define LDBL_HAS_SUBNORM 1 +#endif /* __ISO_C_VISIBLE >= 2011 */ +#endif + +#endif /* _MACHINE_FLOAT_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/float.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/floatingpoint.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/floatingpoint.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/floatingpoint.h (revision 292449) @@ -0,0 +1,3 @@ +/* $FreeBSD$ */ + +#include Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/floatingpoint.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/frame.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/frame.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/frame.h (revision 292449) @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ + +#ifndef LOCORE + +#include +#include + +/* + * NOTE: keep this structure in sync with struct reg and struct mcontext. + */ +struct trapframe { + uint64_t tf_ra; + uint64_t tf_sp; + uint64_t tf_gp; + uint64_t tf_tp; + uint64_t tf_t[7]; + uint64_t tf_s[12]; + uint64_t tf_a[8]; + uint64_t tf_sepc; + uint64_t tf_sstatus; + uint64_t tf_sbadaddr; + uint64_t tf_scause; +}; + +/* + * Signal frame. Pushed onto user stack before calling sigcode. + */ +struct sigframe { + siginfo_t sf_si; /* actual saved siginfo */ + ucontext_t sf_uc; /* actual saved ucontext */ +}; + +#endif /* !LOCORE */ + +#endif /* !_MACHINE_FRAME_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/frame.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/ieeefp.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/ieeefp.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/ieeefp.h (revision 292449) @@ -0,0 +1,8 @@ +/* $FreeBSD$ */ + +#ifndef _MACHINE_IEEEFP_H_ +#define _MACHINE_IEEEFP_H_ + +/* TODO */ + +#endif /* _MACHINE_IEEEFP_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/ieeefp.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/in_cksum.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/in_cksum.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/in_cksum.h (revision 292449) @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 1990 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. 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. + * + * from tahoe: in_cksum.c 1.2 86/01/05 + * from: @(#)in_cksum.c 1.3 (Berkeley) 1/19/91 + * from: Id: in_cksum.c,v 1.8 1995/12/03 18:35:19 bde Exp + * $FreeBSD$ + */ + +#ifndef _MACHINE_IN_CKSUM_H_ +#define _MACHINE_IN_CKSUM_H_ 1 + +#include + +#ifdef _KERNEL +#define in_cksum(m, len) in_cksum_skip(m, len, 0) +u_short in_addword(u_short sum, u_short b); +u_short in_cksum_skip(struct mbuf *m, int len, int skip); +u_int do_cksum(const void *, int); +#if defined(IPVERSION) && (IPVERSION == 4) +u_int in_cksum_hdr(const struct ip *); +#endif + +u_short in_pseudo(u_int sum, u_int b, u_int c); + +#endif /* _KERNEL */ +#endif /* _MACHINE_IN_CKSUM_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/in_cksum.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/intr.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/intr.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/intr.h (revision 292449) @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_INTR_MACHDEP_H_ +#define _MACHINE_INTR_MACHDEP_H_ + +struct trapframe; + +void riscv_init_interrupts(void); +int riscv_teardown_intr(void *); +int riscv_config_intr(u_int, enum intr_trigger, enum intr_polarity); +int riscv_setup_intr(const char *, driver_filter_t *, driver_intr_t *, + void *, int, int, void **); +void riscv_cpu_intr(struct trapframe *); + +typedef unsigned long * riscv_intrcnt_t; + +riscv_intrcnt_t riscv_intrcnt_create(const char *); +void riscv_intrcnt_setname(riscv_intrcnt_t, const char *); + +#endif /* !_MACHINE_INTR_MACHDEP_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/intr.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/kdb.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/kdb.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/kdb.h (revision 292449) @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2004 Marcel Moolenaar + * 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. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_KDB_H_ +#define _MACHINE_KDB_H_ + +#include + +#define KDB_STOPPEDPCB(pc) &stoppcbs[pc->pc_cpuid] + +static __inline void +kdb_cpu_clear_singlestep(void) +{ +} + +static __inline void +kdb_cpu_set_singlestep(void) +{ +} + +static __inline void +kdb_cpu_sync_icache(unsigned char *addr, size_t size) +{ + + cpu_icache_sync_range((vm_offset_t)addr, size); +} + +static __inline void +kdb_cpu_trap(int type, int code) +{ +} + +#endif /* _MACHINE_KDB_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/kdb.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/machdep.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/machdep.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/machdep.h (revision 292449) @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_MACHDEP_H_ +#define _MACHINE_MACHDEP_H_ + +struct riscv_bootparams { + vm_offset_t kern_l1pt; /* Kernel L1 base */ + vm_offset_t kern_stack; +}; + +extern vm_paddr_t physmap[]; +extern u_int physmap_idx; + +vm_offset_t fake_preload_metadata(struct riscv_bootparams *rbp); +void initriscv(struct riscv_bootparams *); + +#endif /* _MACHINE_MACHDEP_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/machdep.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/md_var.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/md_var.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/md_var.h (revision 292449) @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 1995 Bruce D. Evans. + * 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 author nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: FreeBSD: src/sys/i386/include/md_var.h,v 1.40 2001/07/12 + * $FreeBSD$ + */ + +#ifndef _MACHINE_MD_VAR_H_ +#define _MACHINE_MD_VAR_H_ + +extern long Maxmem; +extern char sigcode[]; +extern int szsigcode; +extern uint64_t *vm_page_dump; +extern int vm_page_dump_size; + +struct dumperinfo; + +void busdma_swi(void); +void dump_add_page(vm_paddr_t); +void dump_drop_page(vm_paddr_t); +int minidumpsys(struct dumperinfo *); + +#endif /* !_MACHINE_MD_VAR_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/md_var.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/memdev.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/memdev.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/memdev.h (revision 292449) @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2004 Mark R V Murray + * 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 + * in this position and unchanged. + * 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 AUTHORS ``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. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_MEMDEV_H_ +#define _MACHINE_MEMDEV_H_ + +#define CDEV_MINOR_MEM 0 +#define CDEV_MINOR_KMEM 1 + +d_open_t memopen; +d_read_t memrw; +#define memioctl (d_ioctl_t *)NULL +#define memmmap (d_mmap_t *)NULL + +#endif /* _MACHINE_MEMDEV_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/memdev.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/minidump.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/minidump.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/minidump.h (revision 292449) @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2006 Peter Wemm + * 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. + * + * From i386: FreeBSD: 157909 2006-04-21 04:28:43Z peter + * $FreeBSD$ + */ + +#ifndef _MACHINE_MINIDUMP_H_ +#define _MACHINE_MINIDUMP_H_ 1 + +#define MINIDUMP_MAGIC "minidump FreeBSD/riscv" +#define MINIDUMP_VERSION 1 + +struct minidumphdr { + char magic[24]; + uint32_t version; + uint32_t msgbufsize; + uint32_t bitmapsize; + uint32_t pmapsize; + uint64_t kernbase; + uint64_t dmapphys; + uint64_t dmapbase; + uint64_t dmapend; +}; + +#endif /* _MACHINE_MINIDUMP_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/minidump.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/ofw_machdep.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/ofw_machdep.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/ofw_machdep.h (revision 292449) @@ -0,0 +1,39 @@ +/*- + * Copyright (c) 2001 by Thomas Moestl . + * 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 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_OFW_MACHDEP_H_ +#define _MACHINE_OFW_MACHDEP_H_ + +#include + +typedef uint32_t cell_t; +struct mem_region { + vm_offset_t mr_start; + vm_size_t mr_size; +}; + +#endif /* _MACHINE_OFW_MACHDEP_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/ofw_machdep.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/param.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/param.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/param.h (revision 292449) @@ -0,0 +1,108 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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 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. + * + * from: @(#)param.h 5.8 (Berkeley) 6/28/91 + * $FreeBSD$ + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +/* + * Machine dependent constants for RISC-V. + */ + +#include + +#define STACKALIGNBYTES (16 - 1) +#define STACKALIGN(p) ((uint64_t)(p) & ~STACKALIGNBYTES) + +#ifndef MACHINE +#define MACHINE "riscv" +#endif +#ifndef MACHINE_ARCH +#define MACHINE_ARCH "riscv64" +#endif + +#if defined(SMP) || defined(KLD_MODULE) +#ifndef MAXCPU +#define MAXCPU 2 +#endif +#else +#define MAXCPU 1 +#endif /* SMP || KLD_MODULE */ + +#ifndef MAXMEMDOM +#define MAXMEMDOM 1 +#endif + +#define ALIGNBYTES _ALIGNBYTES +#define ALIGN(p) _ALIGN(p) +/* + * ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + */ +#define ALIGNED_POINTER(p, t) ((((u_long)(p)) & (sizeof(t) - 1)) == 0) + +/* + * CACHE_LINE_SIZE is the compile-time maximum cache line size for an + * architecture. It should be used with appropriate caution. + */ +#define CACHE_LINE_SHIFT 6 +#define CACHE_LINE_SIZE (1 << CACHE_LINE_SHIFT) + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) /* Page size */ +#define PAGE_MASK (PAGE_SIZE - 1) + +#define MAXPAGESIZES 1 /* maximum number of supported page sizes */ + +#ifndef KSTACK_PAGES +#define KSTACK_PAGES 4 /* pages of kernel stack (with pcb) */ +#endif + +#define KSTACK_GUARD_PAGES 1 /* pages of kstack guard; 0 disables */ +#define PCPU_PAGES 1 + +/* + * Mach derived conversion macros + */ +#define round_page(x) (((unsigned long)(x) + PAGE_MASK) & ~PAGE_MASK) +#define trunc_page(x) ((unsigned long)(x) & ~PAGE_MASK) + +#define atop(x) ((unsigned long)(x) >> PAGE_SHIFT) +#define ptoa(x) ((unsigned long)(x) << PAGE_SHIFT) + +#define riscv_btop(x) ((unsigned long)(x) >> PAGE_SHIFT) +#define riscv_ptob(x) ((unsigned long)(x) << PAGE_SHIFT) + +#define pgtok(x) ((unsigned long)(x) * (PAGE_SIZE / 1024)) + +#endif /* !_MACHINE_PARAM_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/param.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/pcb.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/pcb.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/pcb.h (revision 292449) @@ -0,0 +1,64 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_PCB_H_ +#define _MACHINE_PCB_H_ + +#ifndef LOCORE + +struct trapframe; + +struct pcb { + uint64_t pcb_ra; + uint64_t pcb_sp; + uint64_t pcb_gp; + uint64_t pcb_tp; + uint64_t pcb_t[7]; + uint64_t pcb_s[12]; + uint64_t pcb_a[8]; + uint64_t pcb_sepc; + vm_offset_t pcb_l1addr; /* L1 page tables base address */ + vm_offset_t pcb_onfault; +}; + +#ifdef _KERNEL +void makectx(struct trapframe *tf, struct pcb *pcb); +int savectx(struct pcb *pcb) __returns_twice; +#endif + +#endif /* !LOCORE */ + +#endif /* !_MACHINE_PCB_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/pcb.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/pcpu.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/pcpu.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/pcpu.h (revision 292449) @@ -0,0 +1,74 @@ +/*- + * Copyright (c) 1999 Luoqi Chen + * 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 AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: FreeBSD: src/sys/i386/include/globaldata.h,v 1.27 2001/04/27 + * $FreeBSD$ + */ + +#ifndef _MACHINE_PCPU_H_ +#define _MACHINE_PCPU_H_ + +#include +#include + +#define ALT_STACK_SIZE 128 + +#define PCPU_MD_FIELDS \ + char __pad[129] + +#ifdef _KERNEL + +struct pcb; +struct pcpu; +extern struct pcpu *pcpup; + +static inline struct pcpu * +get_pcpu(void) +{ + + return (pcpup); +} + +static inline struct thread * +get_curthread(void) +{ + struct thread *td; + + td = (struct thread *)*(uint64_t *)pcpup; + + return (td); +} + +#define curthread get_curthread() + +#define PCPU_GET(member) (get_pcpu()->pc_ ## member) +#define PCPU_ADD(member, value) (get_pcpu()->pc_ ## member += (value)) +#define PCPU_INC(member) PCPU_ADD(member, 1) +#define PCPU_PTR(member) (&get_pcpu()->pc_ ## member) +#define PCPU_SET(member,value) (get_pcpu()->pc_ ## member = (value)) + +#endif /* _KERNEL */ + +#endif /* !_MACHINE_PCPU_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/pcpu.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/pmap.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/pmap.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/pmap.h (revision 292449) @@ -0,0 +1,160 @@ +/*- + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department and William Jolitz of UUNET Technologies Inc. + * + * 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 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. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ + +#include + +#ifndef LOCORE + +#include +#include +#include + +#ifdef _KERNEL + +#define vtophys(va) pmap_kextract((vm_offset_t)(va)) + +#endif + +#define pmap_page_get_memattr(m) ((m)->md.pv_memattr) +#define pmap_page_is_write_mapped(m) (((m)->aflags & PGA_WRITEABLE) != 0) +void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma); + +/* + * Pmap stuff + */ + +struct md_page { + TAILQ_HEAD(,pv_entry) pv_list; + int pv_gen; + vm_memattr_t pv_memattr; +}; + +/* + * This structure is used to hold a virtual<->physical address + * association and is used mostly by bootstrap code + */ +struct pv_addr { + SLIST_ENTRY(pv_addr) pv_list; + vm_offset_t pv_va; + vm_paddr_t pv_pa; +}; + + +struct pmap { + struct mtx pm_mtx; + struct pmap_statistics pm_stats; /* pmap statictics */ + pd_entry_t *pm_l1; + TAILQ_HEAD(,pv_chunk) pm_pvchunk; /* list of mappings in pmap */ +}; + +typedef struct pv_entry { + vm_offset_t pv_va; /* virtual address for mapping */ + TAILQ_ENTRY(pv_entry) pv_next; +} *pv_entry_t; + +/* + * pv_entries are allocated in chunks per-process. This avoids the + * need to track per-pmap assignments. + */ +#define _NPCM 3 +#define _NPCPV 168 +struct pv_chunk { + struct pmap * pc_pmap; + TAILQ_ENTRY(pv_chunk) pc_list; + uint64_t pc_map[_NPCM]; /* bitmap; 1 = free */ + TAILQ_ENTRY(pv_chunk) pc_lru; + struct pv_entry pc_pventry[_NPCPV]; +}; + +typedef struct pmap *pmap_t; + +#ifdef _KERNEL +extern struct pmap kernel_pmap_store; +#define kernel_pmap (&kernel_pmap_store) +#define pmap_kernel() kernel_pmap + +#define PMAP_ASSERT_LOCKED(pmap) \ + mtx_assert(&(pmap)->pm_mtx, MA_OWNED) +#define PMAP_LOCK(pmap) mtx_lock(&(pmap)->pm_mtx) +#define PMAP_LOCK_ASSERT(pmap, type) \ + mtx_assert(&(pmap)->pm_mtx, (type)) +#define PMAP_LOCK_DESTROY(pmap) mtx_destroy(&(pmap)->pm_mtx) +#define PMAP_LOCK_INIT(pmap) mtx_init(&(pmap)->pm_mtx, "pmap", \ + NULL, MTX_DEF | MTX_DUPOK) +#define PMAP_OWNED(pmap) mtx_owned(&(pmap)->pm_mtx) +#define PMAP_MTX(pmap) (&(pmap)->pm_mtx) +#define PMAP_TRYLOCK(pmap) mtx_trylock(&(pmap)->pm_mtx) +#define PMAP_UNLOCK(pmap) mtx_unlock(&(pmap)->pm_mtx) + +#define PHYS_AVAIL_SIZE 10 +extern vm_paddr_t phys_avail[]; +extern vm_paddr_t dump_avail[]; +extern vm_offset_t virtual_avail; +extern vm_offset_t virtual_end; + +/* + * Macros to test if a mapping is mappable with an L1 Section mapping + * or an L2 Large Page mapping. + */ +#define L1_MAPPABLE_P(va, pa, size) \ + ((((va) | (pa)) & L1_OFFSET) == 0 && (size) >= L1_SIZE) + +void pmap_bootstrap(vm_offset_t, vm_paddr_t, vm_size_t); +void pmap_kenter_device(vm_offset_t, vm_size_t, vm_paddr_t); +vm_paddr_t pmap_kextract(vm_offset_t va); +void pmap_kremove(vm_offset_t); +void pmap_kremove_device(vm_offset_t, vm_size_t); + +void *pmap_mapdev(vm_offset_t, vm_size_t); +void *pmap_mapbios(vm_paddr_t, vm_size_t); +void pmap_unmapdev(vm_offset_t, vm_size_t); +void pmap_unmapbios(vm_offset_t, vm_size_t); + +boolean_t pmap_map_io_transient(vm_page_t *, vm_offset_t *, int, boolean_t); +void pmap_unmap_io_transient(vm_page_t *, vm_offset_t *, int, boolean_t); + +bool pmap_get_tables(pmap_t, vm_offset_t, pd_entry_t **, pd_entry_t **, + pt_entry_t **); + +#define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list)) + +#endif /* _KERNEL */ + +#endif /* !LOCORE */ + +#endif /* !_MACHINE_PMAP_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/pmap.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/pmc_mdep.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/pmc_mdep.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/pmc_mdep.h (revision 292449) @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2009 Rui Paulo + * 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. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_PMC_MDEP_H_ +#define _MACHINE_PMC_MDEP_H_ + +#define PMC_MDEP_CLASS_INDEX_RISCV 1 +/* + * On the RISC-V platform we don't support any PMCs yet. + */ +#include + +union pmc_md_op_pmcallocate { + uint64_t __pad[4]; +}; + +/* Logging */ +#define PMCLOG_READADDR PMCLOG_READ64 +#define PMCLOG_EMITADDR PMCLOG_EMIT64 + +#ifdef _KERNEL +union pmc_md_pmc { + struct pmc_md_riscv_pmc pm_riscv; +}; + +#define PMC_IN_KERNEL_STACK(S,START,END) \ + ((S) >= (START) && (S) < (END)) +#define PMC_IN_KERNEL(va) INKERNEL((va)) +#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS) +#define PMC_TRAPFRAME_TO_PC(TF) ((TF)->tf_ra) +#define PMC_TRAPFRAME_TO_FP(TF) (0) /* stub */ + +/* + * Prototypes + */ +struct pmc_mdep *pmc_riscv_initialize(void); +void pmc_riscv_finalize(struct pmc_mdep *_md); +#endif /* _KERNEL */ + +#endif /* !_MACHINE_PMC_MDEP_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/pmc_mdep.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/proc.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/proc.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/proc.h (revision 292449) @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 1991 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. 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. + * + * from: @(#)proc.h 7.1 (Berkeley) 5/15/91 + * from: FreeBSD: src/sys/i386/include/proc.h,v 1.11 2001/06/29 + * $FreeBSD$ + */ + +#ifndef _MACHINE_PROC_H_ +#define _MACHINE_PROC_H_ + +struct mdthread { + int md_spinlock_count; /* (k) */ + register_t md_saved_sstatus_ie; /* (k) */ +}; + +struct mdproc { + int dummy; +}; + +#define KINFO_PROC_SIZE 1088 + +#ifdef _KERNEL + +#define MAXARGS 8 +struct syscall_args { + u_int code; + struct sysent *callp; + register_t args[MAXARGS]; + int narg; +}; + +#endif + +#endif /* !_MACHINE_PROC_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/proc.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/profile.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/profile.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/profile.h (revision 292449) @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + * + * from: NetBSD: profile.h,v 1.9 1997/04/06 08:47:37 cgd Exp + * from: FreeBSD: src/sys/alpha/include/profile.h,v 1.4 1999/12/29 + * $FreeBSD$ + */ + +#ifndef _MACHINE_PROFILE_H_ +#define _MACHINE_PROFILE_H_ + +#if !defined(_KERNEL) && !defined(_SYS_CDEFS_H_) +#error this file needs sys/cdefs.h as a prerequisite +#endif + +#define FUNCTION_ALIGNMENT 32 + +typedef u_long fptrdiff_t; + +#ifdef _KERNEL + +#include + +#define _MCOUNT_DECL void mcount +#define MCOUNT + +#define MCOUNT_DECL(s) register_t s; +#define MCOUNT_ENTER(s) {s = intr_disable(); } +#define MCOUNT_EXIT(s) {intr_restore(s); } + +void bintr(void); +void btrap(void); +void eintr(void); +void user(void); + +#define MCOUNT_FROMPC_USER(pc) \ + ((pc < (uintfptr_t)VM_MAXUSER_ADDRESS) ? (uintfptr_t)user : pc) + +#define MCOUNT_FROMPC_INTR(pc) \ + ((pc >= (uintfptr_t)btrap && pc < (uintfptr_t)eintr) ? \ + ((pc >= (uintfptr_t)bintr) ? (uintfptr_t)bintr : \ + (uintfptr_t)btrap) : ~0UL) + +void mcount(uintfptr_t frompc, uintfptr_t selfpc); + +#else /* !_KERNEL */ + +typedef unsigned long long uintfptr_t; + +#define _MCOUNT_DECL void mcount +#define MCOUNT + +#endif /* _KERNEL */ + +#endif /* !_MACHINE_PROFILE_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/profile.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/psl.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/psl.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/psl.h (revision 292449) @@ -0,0 +1 @@ +/* $FreeBSD$ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/psl.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/pte.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/pte.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/pte.h (revision 292449) @@ -0,0 +1,100 @@ +/*- + * Copyright (c) 2014 Andrew Turner + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_PTE_H_ +#define _MACHINE_PTE_H_ + +#ifndef LOCORE +typedef uint64_t pd_entry_t; /* page directory entry */ +typedef uint64_t pt_entry_t; /* page table entry */ +#endif + +/* Level 0 table, 512GiB per entry */ +#define L0_SHIFT 39 + +/* Level 1 table, 1GiB per entry */ +#define L1_SHIFT 30 +#define L1_SIZE (1 << L1_SHIFT) +#define L1_OFFSET (L1_SIZE - 1) + +/* Level 2 table, 2MiB per entry */ +#define L2_SHIFT 21 +#define L2_SIZE (1 << L2_SHIFT) +#define L2_OFFSET (L2_SIZE - 1) + +/* Level 3 table, 4KiB per entry */ +#define L3_SHIFT 12 +#define L3_SIZE (1 << L3_SHIFT) +#define L3_OFFSET (L3_SIZE - 1) + +#define Ln_ENTRIES (1 << 9) +#define Ln_ADDR_MASK (Ln_ENTRIES - 1) + +/* Bits 9:7 are reserved for software */ +#define PTE_SW_MANAGED (1 << 8) +#define PTE_SW_WIRED (1 << 7) +#define PTE_DIRTY (1 << 6) /* Virtual page is written */ +#define PTE_REF (1 << 5) /* Virtual page is referenced */ +#define PTE_VALID (1 << 0) /* Virtual page is valid */ +#define PTE_TYPE_S 1 +#define PTE_TYPE_M (0xf << PTE_TYPE_S) +#define PTE_TYPE_PTR 0 +#define PTE_TYPE_PTR_G 1 +#define PTE_TYPE_SROURX 2 /* Supervisor read-only, user read-execute page. */ +#define PTE_TYPE_SRWURWX 3 /* Supervisor read-write, user read-write-execute page. */ +#define PTE_TYPE_SURO 4 /* Supervisor and user read-only page. */ +#define PTE_TYPE_SURW 5 /* Supervisor and user read-write page. */ +#define PTE_TYPE_SURX 6 /* Supervisor and user read-execute page. */ +#define PTE_TYPE_SURWX 7 /* Supervisor and User Read Write Execute */ +#define PTE_TYPE_SRO 8 /* Supervisor read-only page. */ +#define PTE_TYPE_SRW 9 /* Supervisor read-write page. */ +#define PTE_TYPE_SRX 10 /* Supervisor read-execute page. */ +#define PTE_TYPE_SRWX 11 /* Supervisor read-write-execute page. */ +#define PTE_TYPE_SRO_G 12 /* Supervisor read-only page--global mapping. */ +#define PTE_TYPE_SRW_G 13 /* Supervisor read-write page--global mapping. */ +#define PTE_TYPE_SRX_G 14 /* Supervisor read-execute page--global mapping. */ +#define PTE_TYPE_SRWX_G 15 /* Supervisor Read Write Execute Global */ + +#define PTE_PPN0_S 10 +#define PTE_PPN1_S 19 +#define PTE_PPN2_S 28 +#define PTE_PPN3_S 37 +#define PTE_SIZE 8 + +#endif /* !_MACHINE_PTE_H_ */ + +/* End of pte.h */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/pte.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/ptrace.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/ptrace.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/ptrace.h (revision 292449) @@ -0,0 +1 @@ +/* $FreeBSD$ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/ptrace.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/reg.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/reg.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/reg.h (revision 292449) @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_REG_H_ +#define _MACHINE_REG_H_ + +struct reg { + uint64_t ra; /* return address */ + uint64_t sp; /* stack pointer */ + uint64_t gp; /* global pointer */ + uint64_t tp; /* thread pointer */ + uint64_t t[7]; /* temporaries */ + uint64_t s[12]; /* saved registers */ + uint64_t a[8]; /* function arguments */ + uint64_t sepc; /* exception program counter */ + uint64_t sstatus; /* status register */ +}; + +struct fpreg { + int dummy; +}; + +struct dbreg { + int dummy; +}; + +#ifdef _KERNEL +/* + * XXX these interfaces are MI, so they should be declared in a MI place. + */ +int fill_regs(struct thread *, struct reg *); +int set_regs(struct thread *, struct reg *); +int fill_fpregs(struct thread *, struct fpreg *); +int set_fpregs(struct thread *, struct fpreg *); +int fill_dbregs(struct thread *, struct dbreg *); +int set_dbregs(struct thread *, struct dbreg *); +#endif + +#endif /* !_MACHINE_REG_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/reg.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/reloc.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/reloc.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/reloc.h (revision 292449) @@ -0,0 +1 @@ +/* $FreeBSD$ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/reloc.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/resource.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/resource.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/resource.h (revision 292449) @@ -0,0 +1,46 @@ +/*- + * Copyright 1998 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_RESOURCE_H_ +#define _MACHINE_RESOURCE_H_ 1 + +/* + * Definitions of resource types for Intel Architecture machines + * with support for legacy ISA devices and drivers. + */ + +#define SYS_RES_IRQ 1 /* interrupt lines */ +#define SYS_RES_DRQ 2 /* isa dma lines */ +#define SYS_RES_MEMORY 3 /* i/o memory */ +#define SYS_RES_IOPORT 4 /* i/o ports */ +#define SYS_RES_GPIO 5 /* general purpose i/o */ + +#endif /* !_MACHINE_RESOURCE_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/resource.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/riscvreg.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/riscvreg.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/riscvreg.h (revision 292449) @@ -0,0 +1,153 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_RISCVREG_H_ +#define _MACHINE_RISCVREG_H_ + +/* Machine mode requests */ +#define ECALL_MTIMECMP 0x1 +#define ECALL_CLEAR_PENDING 0x2 +#define ECALL_HTIF_CMD 0x3 +#define ECALL_HTIF_GET_ENTRY 0x4 +#define ECALL_MCPUID_GET 0x5 +#define ECALL_MIMPID_GET 0x6 + +#define EXCP_SHIFT 0 +#define EXCP_MASK (0xf << EXCP_SHIFT) +#define EXCP_INSTR_ADDR_MISALIGNED 0 +#define EXCP_INSTR_ACCESS_FAULT 1 +#define EXCP_INSTR_ILLEGAL 2 +#define EXCP_INSTR_BREAKPOINT 3 +#define EXCP_RESERVED_0 4 +#define EXCP_LOAD_ACCESS_FAULT 5 +#define EXCP_AMO_ADDR_MISALIGNED 6 +#define EXCP_STORE_ACCESS_FAULT 7 +#define EXCP_ENV_CALL 8 +#define EXCP_RESERVED_1 9 +#define EXCP_INTR (1 << 31) +#define EXCP_INTR_SOFTWARE 0 +#define EXCP_INTR_TIMER 1 +#define EXCP_INTR_HTIF 2 + +#define SSTATUS_IE (1 << 0) +#define SSTATUS_PIE (1 << 3) +#define SSTATUS_PS (1 << 4) + +#define MSTATUS_MPRV (1 << 16) +#define MSTATUS_PRV_SHIFT 1 +#define MSTATUS_PRV1_SHIFT 4 +#define MSTATUS_PRV2_SHIFT 7 +#define MSTATUS_PRV_MASK (0x3 << MSTATUS_PRV_SHIFT) +#define MSTATUS_PRV_U 0 /* user */ +#define MSTATUS_PRV_S 1 /* supervisor */ +#define MSTATUS_PRV_H 2 /* hypervisor */ +#define MSTATUS_PRV_M 3 /* machine */ + +#define MSTATUS_VM_SHIFT 17 +#define MSTATUS_VM_MASK 0x1f +#define MSTATUS_VM_MBARE 0 +#define MSTATUS_VM_MBB 1 +#define MSTATUS_VM_MBBID 2 +#define MSTATUS_VM_SV32 8 +#define MSTATUS_VM_SV39 9 +#define MSTATUS_VM_SV48 10 + +#define MIE_SSIE (1 << 1) +#define MIE_HSIE (1 << 2) +#define MIE_MSIE (1 << 3) +#define MIE_STIE (1 << 5) +#define MIE_HTIE (1 << 6) +#define MIE_MTIE (1 << 7) + +#define MIP_SSIP (1 << 1) +#define MIP_HSIP (1 << 2) +#define MIP_MSIP (1 << 3) +#define MIP_STIP (1 << 5) +#define MIP_HTIP (1 << 6) +#define MIP_MTIP (1 << 7) + +#define SR_IE (1 << 0) +#define SR_IE1 (1 << 3) +#define SR_IE2 (1 << 6) +#define SR_IE3 (1 << 9) + +#define SIE_SSIE (1 << 1) +#define SIE_STIE (1 << 5) + +/* Note: sip register is not yet implement in Spike simulator */ +#define SIP_STIP (1 << 5) + +#define CSR_ZIMM(val) \ + (__builtin_constant_p(val) && ((u_long)(val) < 32)) + +#define csr_swap(csr, val) \ +({ if (CSR_ZIMM(val)) \ + __asm __volatile("csrrwi %0, " #csr ", %1" \ + : "=r" (val) : "i" (val)); \ + else \ + __asm __volatile("csrrw %0, " #csr ", %1" \ + : "=r" (val) : "r" (val)); \ + val; \ +}) + +#define csr_write(csr, val) \ +({ if (CSR_ZIMM(val)) \ + __asm __volatile("csrwi " #csr ", %0" :: "i" (val)); \ + else \ + __asm __volatile("csrw " #csr ", %0" :: "r" (val)); \ +}) + +#define csr_set(csr, val) \ +({ if (CSR_ZIMM(val)) \ + __asm __volatile("csrsi " #csr ", %0" :: "i" (val)); \ + else \ + __asm __volatile("csrs " #csr ", %0" :: "r" (val)); \ +}) + +#define csr_clear(csr, val) \ +({ if (CSR_ZIMM(val)) \ + __asm __volatile("csrci " #csr ", %0" :: "i" (val)); \ + else \ + __asm __volatile("csrc " #csr ", %0" :: "r" (val)); \ +}) + +#define csr_read(csr) \ +({ u_long val; \ + __asm __volatile("csrr %0, " #csr : "=r" (val)); \ + val; \ +}) + +#endif /* !_MACHINE_RISCVREG_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/riscvreg.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/runq.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/runq.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/runq.h (revision 292449) @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2001 Jake Burkholder + * 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 AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_RUNQ_H_ +#define _MACHINE_RUNQ_H_ + +#define RQB_LEN (1) /* Number of priority status words. */ +#define RQB_L2BPW (6) /* Log2(sizeof(rqb_word_t) * NBBY)). */ +#define RQB_BPW (1<> RQB_L2BPW) + +#define RQB_FFS(word) (ffsl(word) - 1) + +/* + * Type of run queue status word. + */ +typedef unsigned long rqb_word_t; + +#endif Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/runq.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/setjmp.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/setjmp.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/setjmp.h (revision 292449) @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_SETJMP_H_ +#define _MACHINE_SETJMP_H_ + +#include + +#define _JBLEN 32 /* sp, ra, [f]s0-11, magic val, sigmask */ +#define _JB_SIGMASK 21 + +#ifdef __ASSEMBLER__ +#define _JB_MAGIC__SETJMP 0xbe87fd8a2910af00 +#define _JB_MAGIC_SETJMP 0xbe87fd8a2910af01 +#endif /* !__ASSEMBLER__ */ + +#ifndef __ASSEMBLER__ +/* + * jmp_buf and sigjmp_buf are encapsulated in different structs to force + * compile-time diagnostics for mismatches. The structs are the same + * internally to avoid some run-time errors for mismatches. + */ +#if __BSD_VISIBLE || __POSIX_VISIBLE || __XSI_VISIBLE +typedef struct _sigjmp_buf { long _sjb[_JBLEN + 1]; } sigjmp_buf[1]; +#endif + +typedef struct _jmp_buf { long _jb[_JBLEN + 1]; } jmp_buf[1]; +#endif /* __ASSEMBLER__ */ + +#endif /* !_MACHINE_SETJMP_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/setjmp.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/sf_buf.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/sf_buf.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/sf_buf.h (revision 292449) @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2003, 2005 Alan L. Cox + * 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 AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_SF_BUF_H_ +#define _MACHINE_SF_BUF_H_ + +/* + * On this machine, the only purpose for which sf_buf is used is to implement + * an opaque pointer required by the machine-independent parts of the kernel. + * That pointer references the vm_page that is "mapped" by the sf_buf. The + * actual mapping is provided by the direct virtual-to-physical mapping. + */ +static inline vm_offset_t +sf_buf_kva(struct sf_buf *sf) +{ + + return (PHYS_TO_DMAP(VM_PAGE_TO_PHYS((vm_page_t)sf))); +} + +static inline vm_page_t +sf_buf_page(struct sf_buf *sf) +{ + + return ((vm_page_t)sf); +} +#endif /* !_MACHINE_SF_BUF_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/sf_buf.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/signal.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/signal.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/signal.h (revision 292449) @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 1986, 1989, 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. 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. + * + * @(#)signal.h 8.1 (Berkeley) 6/11/93 + * from: FreeBSD: src/sys/i386/include/signal.h,v 1.13 2000/11/09 + * from: FreeBSD: src/sys/sparc64/include/signal.h,v 1.6 2001/09/30 18:52:17 + * $FreeBSD$ + */ + +#ifndef _MACHINE_SIGNAL_H_ +#define _MACHINE_SIGNAL_H_ + +#include + +typedef long sig_atomic_t; + +#if __BSD_VISIBLE + +struct sigcontext { + int _dummy; +}; + +#endif + +#endif /* !_MACHINE_SIGNAL_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/signal.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/smp.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/smp.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/smp.h (revision 292449) @@ -0,0 +1 @@ +/* $FreeBSD$ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/smp.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/stdarg.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/stdarg.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/stdarg.h (revision 292449) @@ -0,0 +1,79 @@ +/*- + * Copyright (c) 2002 David E. O'Brien. All rights reserved. + * 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. 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. + * + * @(#)stdarg.h 8.1 (Berkeley) 6/10/93 + * $FreeBSD$ + */ + +#ifndef _MACHINE_STDARG_H_ +#define _MACHINE_STDARG_H_ + +#include +#include + +#ifndef _VA_LIST_DECLARED +#define _VA_LIST_DECLARED +typedef __va_list va_list; +#endif + +#ifdef __GNUCLIKE_BUILTIN_STDARG + +#define va_start(ap, last) \ + __builtin_va_start((ap), (last)) + +#define va_arg(ap, type) \ + __builtin_va_arg((ap), type) + +#if __ISO_C_VISIBLE >= 1999 +#define va_copy(dest, src) \ + __builtin_va_copy((dest), (src)) +#endif + +#define va_end(ap) \ + __builtin_va_end(ap) + +#elif defined(lint) +/* Provide a fake implementation for lint's benefit */ +#define __va_size(type) \ + (((sizeof(type) + sizeof(long) - 1) / sizeof(long)) * sizeof(long)) +#define va_start(ap, last) \ + ((ap) = (va_list)&(last) + __va_size(last)) +#define va_copy(dst, src) \ + ((dst) = (src)) +#define va_arg(ap, type) \ + (*(type *)((ap) += __va_size(type), (ap) - __va_size(type))) +#define va_end(ap) + +#else /* !__GNUCLIKE_BUILTIN_STDARG */ + +#error no support for your compiler + +#endif /* __GNUCLIKE_BUILTIN_STDARG */ + +#endif /* !_MACHINE_STDARG_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/stdarg.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/sysarch.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/sysarch.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/sysarch.h (revision 292449) @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 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. 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. + * + * from: FreeBSD: src/sys/i386/include/sysarch.h,v 1.14 2000/09/21 + * $FreeBSD$ + */ + +/* + * Architecture specific syscalls (RISC-V) + */ +#ifndef _MACHINE_SYSARCH_H_ +#define _MACHINE_SYSARCH_H_ + +#ifndef _KERNEL + +__BEGIN_DECLS +int sysarch(int _number, void *_args); +__END_DECLS + +#endif + +#endif /* !_MACHINE_SYSARCH_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/sysarch.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/trap.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/trap.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/trap.h (revision 292449) @@ -0,0 +1 @@ +/* $FreeBSD$ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/trap.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/ucontext.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/ucontext.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/ucontext.h (revision 292449) @@ -0,0 +1,70 @@ +/*- + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * Portions of this software were developed by SRI International and the + * University of Cambridge Computer Laboratory under DARPA/AFRL contract + * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Portions of this software were developed by the University of Cambridge + * Computer Laboratory as part of the CTSRD Project, with support from the + * UK Higher Education Innovation Fund (HEIF). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_UCONTEXT_H_ +#define _MACHINE_UCONTEXT_H_ + +struct gpregs { + __register_t gp_ra; + __register_t gp_sp; + __register_t gp_gp; + __register_t gp_tp; + __register_t gp_t[7]; + __register_t gp_s[12]; + __register_t gp_a[8]; + __register_t gp_sepc; + __register_t gp_sstatus; +}; + +struct fpregs { + __uint128_t fp_x[32]; + __uint64_t fp_fcsr; + int fp_flags; + int pad; +}; + +struct __mcontext { + struct gpregs mc_gpregs; + struct fpregs mc_fpregs; + int mc_flags; +#define _MC_FP_VALID 0x1 /* Set when mc_fpregs has valid data */ + int mc_pad; + __uint64_t mc_spare[8]; /* Space for expansion */ +}; + +typedef struct __mcontext mcontext_t; + +#endif /* !_MACHINE_UCONTEXT_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/ucontext.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/vdso.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/vdso.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/vdso.h (revision 292449) @@ -0,0 +1,34 @@ +/*- + * Copyright 2012 Konstantin Belousov . + * 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. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_VDSO_H_ +#define _MACHINE_VDSO_H_ + +#define VDSO_TIMEHANDS_MD \ + uint32_t th_res[8]; + +#endif /* !_MACHINE_VDSO_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/vdso.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/vm.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/vm.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/vm.h (revision 292449) @@ -0,0 +1,39 @@ +/*- + * Copyright (c) 2009 Alan L. Cox + * 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 AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_VM_H_ +#define _MACHINE_VM_H_ + +/* Memory attribute configuration. */ +#define VM_MEMATTR_DEVICE 0 +#define VM_MEMATTR_UNCACHEABLE 1 +#define VM_MEMATTR_WRITE_BACK 2 + +#define VM_MEMATTR_DEFAULT VM_MEMATTR_WRITE_BACK + +#endif /* !_MACHINE_VM_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/vm.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/riscv/include/vmparam.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/riscv/include/vmparam.h (nonexistent) +++ user/alc/PQ_LAUNDRY/sys/riscv/include/vmparam.h (revision 292449) @@ -0,0 +1,239 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 1994 John S. Dyson + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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 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. + * + * from: @(#)vmparam.h 5.9 (Berkeley) 5/12/91 + * from: FreeBSD: src/sys/i386/include/vmparam.h,v 1.33 2000/03/30 + * $FreeBSD$ + */ + +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ + +/* + * Virtual memory related constants, all in bytes + */ +#ifndef MAXTSIZ +#define MAXTSIZ (32*1024*1024) /* max text size */ +#endif +#ifndef DFLDSIZ +#define DFLDSIZ (128*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ (128*1024*1024) /* max data size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ (2*1024*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ (8*1024*1024) /* max stack size */ +#endif +#ifndef SGROWSIZ +#define SGROWSIZ (128*1024) /* amount to grow stack */ +#endif + +/* + * The physical address space is sparsely populated. + */ +#define VM_PHYSSEG_SPARSE + +/* + * The number of PHYSSEG entries must be one greater than the number + * of phys_avail entries because the phys_avail entry that spans the + * largest physical address that is accessible by ISA DMA is split + * into two PHYSSEG entries. + */ +#define VM_PHYSSEG_MAX 64 + +/* + * Create two free page pools: VM_FREEPOOL_DEFAULT is the default pool + * from which physical pages are allocated and VM_FREEPOOL_DIRECT is + * the pool from which physical pages for small UMA objects are + * allocated. + */ +#define VM_NFREEPOOL 2 +#define VM_FREEPOOL_DEFAULT 0 +#define VM_FREEPOOL_DIRECT 1 + +/* + * Create two free page lists: VM_FREELIST_DEFAULT is for physical + * pages that are above the largest physical address that is + * accessible by ISA DMA and VM_FREELIST_ISADMA is for physical pages + * that are below that address. + */ +#define VM_NFREELIST 2 +#define VM_FREELIST_DEFAULT 0 +#define VM_FREELIST_ISADMA 1 + +/* + * An allocation size of 16MB is supported in order to optimize the + * use of the direct map by UMA. Specifically, a cache line contains + * at most four TTEs, collectively mapping 16MB of physical memory. + * By reducing the number of distinct 16MB "pages" that are used by UMA, + * the physical memory allocator reduces the likelihood of both 4MB + * page TLB misses and cache misses caused by 4MB page TLB misses. + */ +#define VM_NFREEORDER 12 + +/* + * Enable superpage reservations: 1 level. + */ +#ifndef VM_NRESERVLEVEL +#define VM_NRESERVLEVEL 1 +#endif + +/* + * Level 0 reservations consist of 512 pages. + */ +#ifndef VM_LEVEL_0_ORDER +#define VM_LEVEL_0_ORDER 9 +#endif + +/** + * Address space layout. + * + * RISC-V implements up to a 48 bit virtual address space. The address space is + * split into 2 regions at each end of the 64 bit address space, with an + * out of range "hole" in the middle. + * + * We limit the size of the two spaces to 39 bits each. + * + * Upper region: 0xffffffffffffffff + * 0xffffffffc0000000 + * + * Hole: 0xffffffffbfffffff + * 0x0000000080000000 + * + * Lower region: 0x000000007fffffff + * 0x0000000000000000 + * + * We use the upper region for the kernel, and the lower region for userland. + * + * We define some interesting address constants: + * + * VM_MIN_ADDRESS and VM_MAX_ADDRESS define the start and end of the entire + * 64 bit address space, mostly just for convenience. + * + * VM_MIN_KERNEL_ADDRESS and VM_MAX_KERNEL_ADDRESS define the start and end of + * mappable kernel virtual address space. + * + * VM_MIN_USER_ADDRESS and VM_MAX_USER_ADDRESS define the start and end of the + * user address space. + */ +#define VM_MIN_ADDRESS (0x0000000000000000UL) +#define VM_MAX_ADDRESS (0xffffffffffffffffUL) + +/* 256 MiB of kernel addresses */ +#define VM_MIN_KERNEL_ADDRESS (0xffffffffc0000000UL) +#define VM_MAX_KERNEL_ADDRESS (0xffffffffcfffffffUL) + +/* Direct Map for 512 MiB of PA: 0x0 - 0x1fffffff */ +#define DMAP_MIN_ADDRESS (0xffffffffd0000000UL) +#define DMAP_MAX_ADDRESS (0xffffffffefffffffUL) + +#define DMAP_MIN_PHYSADDR (0x0000000000000000UL) +#define DMAP_MAX_PHYSADDR (DMAP_MAX_ADDRESS - DMAP_MIN_ADDRESS) + +/* True if pa is in the dmap range */ +#define PHYS_IN_DMAP(pa) ((pa) <= DMAP_MAX_PHYSADDR) +/* True if va is in the dmap range */ +#define VIRT_IN_DMAP(va) ((va) >= DMAP_MIN_ADDRESS && \ + (va) <= DMAP_MAX_ADDRESS) + +#define PHYS_TO_DMAP(pa) \ +({ \ + KASSERT(PHYS_IN_DMAP(pa), \ + ("%s: PA out of range, PA: 0x%lx", __func__, \ + (vm_paddr_t)(pa))); \ + (pa) | DMAP_MIN_ADDRESS; \ +}) + +#define DMAP_TO_PHYS(va) \ +({ \ + KASSERT(VIRT_IN_DMAP(va), \ + ("%s: VA out of range, VA: 0x%lx", __func__, \ + (vm_offset_t)(va))); \ + (va) & ~DMAP_MIN_ADDRESS; \ +}) + +#define VM_MIN_USER_ADDRESS (0x0000000000000000UL) +#define VM_MAX_USER_ADDRESS (0x0000000080000000UL) + +#define VM_MINUSER_ADDRESS (VM_MIN_USER_ADDRESS) +#define VM_MAXUSER_ADDRESS (VM_MAX_USER_ADDRESS) + +#define KERNBASE (VM_MIN_KERNEL_ADDRESS) +#define USRSTACK (VM_MAX_USER_ADDRESS) +#define KERNENTRY (0x200) + +/* + * How many physical pages per kmem arena virtual page. + */ +#ifndef VM_KMEM_SIZE_SCALE +#define VM_KMEM_SIZE_SCALE (3) +#endif + +/* + * Optional floor (in bytes) on the size of the kmem arena. + */ +#ifndef VM_KMEM_SIZE_MIN +#define VM_KMEM_SIZE_MIN (16 * 1024 * 1024) +#endif + +/* + * Optional ceiling (in bytes) on the size of the kmem arena: 60% of the + * kernel map. + */ +#ifndef VM_KMEM_SIZE_MAX +#define VM_KMEM_SIZE_MAX ((VM_MAX_KERNEL_ADDRESS - \ + VM_MIN_KERNEL_ADDRESS + 1) * 3 / 5) +#endif + +/* + * Initial pagein size of beginning of executable file. + */ +#ifndef VM_INITIAL_PAGEIN +#define VM_INITIAL_PAGEIN 16 +#endif + +/* + * RISCVTODO + * #define UMA_MD_SMALL_ALLOC + */ + +extern u_int tsb_kernel_ldd_phys; +extern vm_offset_t vm_max_kernel_address; +extern vm_offset_t init_pt_va; + +#define ZERO_REGION_SIZE (64 * 1024) /* 64KB */ + +#endif /* !_MACHINE_VMPARAM_H_ */ Property changes on: user/alc/PQ_LAUNDRY/sys/riscv/include/vmparam.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: user/alc/PQ_LAUNDRY/sys/sys/linker.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/sys/linker.h (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/sys/linker.h (revision 292449) @@ -1,352 +1,353 @@ /*- * Copyright (c) 1997-2000 Doug Rabson * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_LINKER_H_ #define _SYS_LINKER_H_ #ifdef _KERNEL #include #include #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_LINKER); #endif struct mod_depend; /* * Object representing a file which has been loaded by the linker. */ typedef struct linker_file* linker_file_t; typedef TAILQ_HEAD(, linker_file) linker_file_list_t; typedef caddr_t linker_sym_t; /* opaque symbol */ typedef c_caddr_t c_linker_sym_t; /* const opaque symbol */ typedef int (*linker_function_name_callback_t)(const char *, void *); /* * expanded out linker_sym_t */ typedef struct linker_symval { const char* name; caddr_t value; size_t size; } linker_symval_t; typedef int (*linker_function_nameval_callback_t)(linker_file_t, int, linker_symval_t *, void *); struct common_symbol { STAILQ_ENTRY(common_symbol) link; char* name; caddr_t address; }; struct linker_file { KOBJ_FIELDS; int refs; /* reference count */ int userrefs; /* kldload(2) count */ int flags; #define LINKER_FILE_LINKED 0x1 /* file has been fully linked */ TAILQ_ENTRY(linker_file) link; /* list of all loaded files */ char* filename; /* file which was loaded */ char* pathname; /* file name with full path */ int id; /* unique id */ caddr_t address; /* load address */ size_t size; /* size of file */ caddr_t ctors_addr; /* address of .ctors */ size_t ctors_size; /* size of .ctors */ int ndeps; /* number of dependencies */ linker_file_t* deps; /* list of dependencies */ STAILQ_HEAD(, common_symbol) common; /* list of common symbols */ TAILQ_HEAD(, module) modules; /* modules in this file */ TAILQ_ENTRY(linker_file) loaded; /* preload dependency support */ int loadcnt; /* load counter value */ /* * Function Boundary Tracing (FBT) or Statically Defined Tracing (SDT) * fields. */ int nenabled; /* number of enabled probes. */ int fbt_nentries; /* number of fbt entries created. */ }; /* * Object implementing a class of file (a.out, elf, etc.) */ typedef struct linker_class *linker_class_t; typedef TAILQ_HEAD(, linker_class) linker_class_list_t; struct linker_class { KOBJ_CLASS_FIELDS; TAILQ_ENTRY(linker_class) link; /* list of all file classes */ }; /* * Function type used when iterating over the list of linker files. */ typedef int linker_predicate_t(linker_file_t, void *); /* * The "file" for the kernel. */ extern linker_file_t linker_kernel_file; /* * Obtain a reference to a module, loading it if required. */ int linker_reference_module(const char* _modname, struct mod_depend *_verinfo, linker_file_t* _result); /* * Release a reference to a module, unloading it if there are no more * references. Note that one should either provide a module name and * optional version info or a linker file, but not both. */ int linker_release_module(const char *_modname, struct mod_depend *_verinfo, linker_file_t _file); /* * Iterate over all of the currently loaded linker files calling the * predicate function while the function returns 0. Returns the value * returned by the last predicate function. */ int linker_file_foreach(linker_predicate_t *_predicate, void *_context); /* * Lookup a symbol in a file. If deps is TRUE, look in dependencies * if not found in file. */ caddr_t linker_file_lookup_symbol(linker_file_t _file, const char* _name, int _deps); /* * Lookup a linker set in a file. Return pointers to the first entry, * last + 1, and count of entries. Use: for (p = start; p < stop; p++) {} * void *start is really: "struct yoursetmember ***start;" */ int linker_file_lookup_set(linker_file_t _file, const char *_name, void *_start, void *_stop, int *_count); /* * List all functions in a file. */ int linker_file_function_listall(linker_file_t, linker_function_nameval_callback_t, void *); /* * Functions soley for use by the linker class handlers. */ int linker_add_class(linker_class_t _cls); int linker_file_unload(linker_file_t _file, int flags); int linker_load_dependencies(linker_file_t _lf); linker_file_t linker_make_file(const char* _filename, linker_class_t _cls); /* * DDB Helpers, tuned specifically for ddb/db_kld.c */ int linker_ddb_lookup(const char *_symstr, c_linker_sym_t *_sym); int linker_ddb_search_symbol(caddr_t _value, c_linker_sym_t *_sym, long *_diffp); int linker_ddb_symbol_values(c_linker_sym_t _sym, linker_symval_t *_symval); int linker_ddb_search_symbol_name(caddr_t value, char *buf, u_int buflen, long *offset); /* * stack(9) helper for situations where kernel locking is required. */ int linker_search_symbol_name(caddr_t value, char *buf, u_int buflen, long *offset); /* HWPMC helper */ void *linker_hwpmc_list_objects(void); #endif /* _KERNEL */ /* * Module information subtypes */ #define MODINFO_END 0x0000 /* End of list */ #define MODINFO_NAME 0x0001 /* Name of module (string) */ #define MODINFO_TYPE 0x0002 /* Type of module (string) */ #define MODINFO_ADDR 0x0003 /* Loaded address */ #define MODINFO_SIZE 0x0004 /* Size of module */ #define MODINFO_EMPTY 0x0005 /* Has been deleted */ #define MODINFO_ARGS 0x0006 /* Parameters string */ #define MODINFO_METADATA 0x8000 /* Module-specfic */ #define MODINFOMD_AOUTEXEC 0x0001 /* a.out exec header */ #define MODINFOMD_ELFHDR 0x0002 /* ELF header */ #define MODINFOMD_SSYM 0x0003 /* start of symbols */ #define MODINFOMD_ESYM 0x0004 /* end of symbols */ #define MODINFOMD_DYNAMIC 0x0005 /* _DYNAMIC pointer */ /* These values are MD on these two platforms */ #if !defined(__sparc64__) && !defined(__powerpc__) #define MODINFOMD_ENVP 0x0006 /* envp[] */ #define MODINFOMD_HOWTO 0x0007 /* boothowto */ #define MODINFOMD_KERNEND 0x0008 /* kernend */ #endif #define MODINFOMD_SHDR 0x0009 /* section header table */ #define MODINFOMD_CTORS_ADDR 0x000a /* address of .ctors */ #define MODINFOMD_CTORS_SIZE 0x000b /* size of .ctors */ +#define MODINFOMD_FW_HANDLE 0x000c /* Firmware dependent handle */ #define MODINFOMD_NOCOPY 0x8000 /* don't copy this metadata to the kernel */ #define MODINFOMD_DEPLIST (0x4001 | MODINFOMD_NOCOPY) /* depends on */ #ifdef _KERNEL #define MD_FETCH(mdp, info, type) ({ \ type *__p; \ __p = (type *)preload_search_info((mdp), MODINFO_METADATA | (info)); \ __p ? *__p : 0; \ }) #endif #define LINKER_HINTS_VERSION 1 /* linker.hints file version */ #define LINKER_HINTS_MAX (1 << 20) /* Allow at most 1MB for linker.hints */ #ifdef _KERNEL /* * Module lookup */ extern vm_offset_t preload_addr_relocate; extern caddr_t preload_metadata; extern void * preload_fetch_addr(caddr_t _mod); extern size_t preload_fetch_size(caddr_t _mod); extern caddr_t preload_search_by_name(const char *_name); extern caddr_t preload_search_by_type(const char *_type); extern caddr_t preload_search_next_name(caddr_t _base); extern caddr_t preload_search_info(caddr_t _mod, int _inf); extern void preload_delete_name(const char *_name); extern void preload_bootstrap_relocate(vm_offset_t _offset); #ifdef KLD_DEBUG extern int kld_debug; #define KLD_DEBUG_FILE 1 /* file load/unload */ #define KLD_DEBUG_SYM 2 /* symbol lookup */ #define KLD_DPF(cat, args) \ do { \ if (kld_debug & KLD_DEBUG_##cat) printf args; \ } while (0) #else #define KLD_DPF(cat, args) #endif typedef int elf_lookup_fn(linker_file_t, Elf_Size, int, Elf_Addr *); /* Support functions */ int elf_reloc(linker_file_t _lf, Elf_Addr base, const void *_rel, int _type, elf_lookup_fn _lu); int elf_reloc_local(linker_file_t _lf, Elf_Addr base, const void *_rel, int _type, elf_lookup_fn _lu); Elf_Addr elf_relocaddr(linker_file_t _lf, Elf_Addr addr); const Elf_Sym *elf_get_sym(linker_file_t _lf, Elf_Size _symidx); const char *elf_get_symname(linker_file_t _lf, Elf_Size _symidx); typedef struct linker_ctf { const uint8_t *ctftab; /* Decompressed CTF data. */ int ctfcnt; /* Number of CTF data bytes. */ const Elf_Sym *symtab; /* Ptr to the symbol table. */ int nsym; /* Number of symbols. */ const char *strtab; /* Ptr to the string table. */ int strcnt; /* Number of string bytes. */ uint32_t **ctfoffp; /* Ptr to array of obj/fnc offsets. */ uint32_t **typoffp; /* Ptr to array of type offsets. */ long *typlenp; /* Ptr to number of type data entries. */ } linker_ctf_t; int linker_ctf_get(linker_file_t, linker_ctf_t *); int elf_cpu_load_file(linker_file_t); int elf_cpu_unload_file(linker_file_t); /* values for type */ #define ELF_RELOC_REL 1 #define ELF_RELOC_RELA 2 /* * This is version 1 of the KLD file status structure. It is identified * by its _size_ in the version field. */ struct kld_file_stat_1 { int version; /* set to sizeof(struct kld_file_stat_1) */ char name[MAXPATHLEN]; int refs; int id; caddr_t address; /* load address */ size_t size; /* size in bytes */ }; #endif /* _KERNEL */ struct kld_file_stat { int version; /* set to sizeof(struct kld_file_stat) */ char name[MAXPATHLEN]; int refs; int id; caddr_t address; /* load address */ size_t size; /* size in bytes */ char pathname[MAXPATHLEN]; }; struct kld_sym_lookup { int version; /* set to sizeof(struct kld_sym_lookup) */ char *symname; /* Symbol name we are looking up */ u_long symvalue; size_t symsize; }; #define KLDSYM_LOOKUP 1 /* * Flags for kldunloadf() and linker_file_unload() */ #define LINKER_UNLOAD_NORMAL 0 #define LINKER_UNLOAD_FORCE 1 #ifndef _KERNEL #include __BEGIN_DECLS int kldload(const char* _file); int kldunload(int _fileid); int kldunloadf(int _fileid, int flags); int kldfind(const char* _file); int kldnext(int _fileid); int kldstat(int _fileid, struct kld_file_stat* _stat); int kldfirstmod(int _fileid); int kldsym(int _fileid, int _cmd, void *_data); __END_DECLS #endif #endif /* !_SYS_LINKER_H_ */ Index: user/alc/PQ_LAUNDRY/sys/sys/proc.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/sys/proc.h (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/sys/proc.h (revision 292449) @@ -1,1051 +1,1051 @@ /*- * Copyright (c) 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * 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. * 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. * * @(#)proc.h 8.15 (Berkeley) 5/19/95 * $FreeBSD$ */ #ifndef _SYS_PROC_H_ #define _SYS_PROC_H_ #include /* For struct callout. */ #include /* For struct klist. */ #include #ifndef _KERNEL #include #endif #include #include #include #include #include #include #include /* XXX. */ #include #include #include #include #include #ifndef _KERNEL #include /* For structs itimerval, timeval. */ #else #include #endif #include #include #include #include /* Machine-dependent proc substruct. */ /* * One structure allocated per session. * * List of locks * (m) locked by s_mtx mtx * (e) locked by proctree_lock sx * (c) const until freeing */ struct session { u_int s_count; /* Ref cnt; pgrps in session - atomic. */ struct proc *s_leader; /* (m + e) Session leader. */ struct vnode *s_ttyvp; /* (m) Vnode of controlling tty. */ struct cdev_priv *s_ttydp; /* (m) Device of controlling tty. */ struct tty *s_ttyp; /* (e) Controlling tty. */ pid_t s_sid; /* (c) Session ID. */ /* (m) Setlogin() name: */ char s_login[roundup(MAXLOGNAME, sizeof(long))]; struct mtx s_mtx; /* Mutex to protect members. */ }; /* * One structure allocated per process group. * * List of locks * (m) locked by pg_mtx mtx * (e) locked by proctree_lock sx * (c) const until freeing */ struct pgrp { LIST_ENTRY(pgrp) pg_hash; /* (e) Hash chain. */ LIST_HEAD(, proc) pg_members; /* (m + e) Pointer to pgrp members. */ struct session *pg_session; /* (c) Pointer to session. */ struct sigiolst pg_sigiolst; /* (m) List of sigio sources. */ pid_t pg_id; /* (c) Process group id. */ int pg_jobc; /* (m) Job control process count. */ struct mtx pg_mtx; /* Mutex to protect members */ }; /* * pargs, used to hold a copy of the command line, if it had a sane length. */ struct pargs { u_int ar_ref; /* Reference count. */ u_int ar_length; /* Length. */ u_char ar_args[1]; /* Arguments. */ }; /*- * Description of a process. * * This structure contains the information needed to manage a thread of * control, known in UN*X as a process; it has references to substructures * containing descriptions of things that the process uses, but may share * with related processes. The process structure and the substructures * are always addressable except for those marked "(CPU)" below, * which might be addressable only on a processor on which the process * is running. * * Below is a key of locks used to protect each member of struct proc. The * lock is indicated by a reference to a specific character in parens in the * associated comment. * * - not yet protected * a - only touched by curproc or parent during fork/wait * b - created at fork, never changes * (exception aiods switch vmspaces, but they are also * marked 'P_SYSTEM' so hopefully it will be left alone) * c - locked by proc mtx * d - locked by allproc_lock lock * e - locked by proctree_lock lock * f - session mtx * g - process group mtx * h - callout_lock mtx * i - by curproc or the master session mtx * j - locked by proc slock * k - only accessed by curthread * k*- only accessed by curthread and from an interrupt * l - the attaching proc or attaching proc parent * m - Giant * n - not locked, lazy * o - ktrace lock * q - td_contested lock * r - p_peers lock * t - thread lock * u - process stat lock * w - process timer lock * x - created at fork, only changes during single threading in exec * y - created at first aio, doesn't change until exit or exec at which * point we are single-threaded and only curthread changes it * z - zombie threads lock * * If the locking key specifies two identifiers (for example, p_pptr) then * either lock is sufficient for read access, but both locks must be held * for write access. */ struct cpuset; struct filecaps; struct kaioinfo; struct kaudit_record; struct kdtrace_proc; struct kdtrace_thread; struct mqueue_notifier; struct nlminfo; struct p_sched; struct proc; struct procdesc; struct racct; struct sbuf; struct sleepqueue; struct syscall_args; struct td_sched; struct thread; struct trapframe; struct turnstile; /* * XXX: Does this belong in resource.h or resourcevar.h instead? * Resource usage extension. The times in rusage structs in the kernel are * never up to date. The actual times are kept as runtimes and tick counts * (with control info in the "previous" times), and are converted when * userland asks for rusage info. Backwards compatibility prevents putting * this directly in the user-visible rusage struct. * * Locking for p_rux: (cu) means (u) for p_rux and (c) for p_crux. * Locking for td_rux: (t) for all fields. */ struct rusage_ext { uint64_t rux_runtime; /* (cu) Real time. */ uint64_t rux_uticks; /* (cu) Statclock hits in user mode. */ uint64_t rux_sticks; /* (cu) Statclock hits in sys mode. */ uint64_t rux_iticks; /* (cu) Statclock hits in intr mode. */ uint64_t rux_uu; /* (c) Previous user time in usec. */ uint64_t rux_su; /* (c) Previous sys time in usec. */ uint64_t rux_tu; /* (c) Previous total time in usec. */ }; /* * Kernel runnable context (thread). * This is what is put to sleep and reactivated. * Thread context. Processes may have multiple threads. */ struct thread { struct mtx *volatile td_lock; /* replaces sched lock */ struct proc *td_proc; /* (*) Associated process. */ TAILQ_ENTRY(thread) td_plist; /* (*) All threads in this proc. */ TAILQ_ENTRY(thread) td_runq; /* (t) Run queue. */ TAILQ_ENTRY(thread) td_slpq; /* (t) Sleep queue. */ TAILQ_ENTRY(thread) td_lockq; /* (t) Lock queue. */ LIST_ENTRY(thread) td_hash; /* (d) Hash chain. */ struct cpuset *td_cpuset; /* (t) CPU affinity mask. */ struct seltd *td_sel; /* Select queue/channel. */ struct sleepqueue *td_sleepqueue; /* (k) Associated sleep queue. */ struct turnstile *td_turnstile; /* (k) Associated turnstile. */ struct rl_q_entry *td_rlqe; /* (k) Associated range lock entry. */ struct umtx_q *td_umtxq; /* (c?) Link for when we're blocked. */ struct vm_domain_policy td_vm_dom_policy; /* (c) current numa domain policy */ lwpid_t td_tid; /* (b) Thread ID. */ sigqueue_t td_sigqueue; /* (c) Sigs arrived, not delivered. */ #define td_siglist td_sigqueue.sq_signals u_char td_lend_user_pri; /* (t) Lend user pri. */ /* Cleared during fork1() */ #define td_startzero td_flags int td_flags; /* (t) TDF_* flags. */ int td_inhibitors; /* (t) Why can not run. */ int td_pflags; /* (k) Private thread (TDP_*) flags. */ int td_dupfd; /* (k) Ret value from fdopen. XXX */ int td_sqqueue; /* (t) Sleepqueue queue blocked on. */ void *td_wchan; /* (t) Sleep address. */ const char *td_wmesg; /* (t) Reason for sleep. */ volatile u_char td_owepreempt; /* (k*) Preempt on last critical_exit */ u_char td_tsqueue; /* (t) Turnstile queue blocked on. */ short td_locks; /* (k) Debug: count of non-spin locks */ short td_rw_rlocks; /* (k) Count of rwlock read locks. */ short td_lk_slocks; /* (k) Count of lockmgr shared locks. */ short td_stopsched; /* (k) Scheduler stopped. */ struct turnstile *td_blocked; /* (t) Lock thread is blocked on. */ const char *td_lockname; /* (t) Name of lock blocked on. */ LIST_HEAD(, turnstile) td_contested; /* (q) Contested locks. */ struct lock_list_entry *td_sleeplocks; /* (k) Held sleep locks. */ int td_intr_nesting_level; /* (k) Interrupt recursion. */ int td_pinned; /* (k) Temporary cpu pin count. */ struct ucred *td_ucred; /* (k) Reference to credentials. */ struct plimit *td_limit; /* (k) Resource limits. */ u_int td_estcpu; /* (t) estimated cpu utilization */ int td_slptick; /* (t) Time at sleep. */ int td_blktick; /* (t) Time spent blocked. */ int td_swvoltick; /* (t) Time at last SW_VOL switch. */ u_int td_cow; /* (*) Number of copy-on-write faults */ struct rusage td_ru; /* (t) rusage information. */ struct rusage_ext td_rux; /* (t) Internal rusage information. */ uint64_t td_incruntime; /* (t) Cpu ticks to transfer to proc. */ uint64_t td_runtime; /* (t) How many cpu ticks we've run. */ u_int td_pticks; /* (t) Statclock hits for profiling */ u_int td_sticks; /* (t) Statclock hits in system mode. */ u_int td_iticks; /* (t) Statclock hits in intr mode. */ u_int td_uticks; /* (t) Statclock hits in user mode. */ int td_intrval; /* (t) Return value for sleepq. */ sigset_t td_oldsigmask; /* (k) Saved mask from pre sigpause. */ volatile u_int td_generation; /* (k) For detection of preemption */ stack_t td_sigstk; /* (k) Stack ptr and on-stack flag. */ int td_xsig; /* (c) Signal for ptrace */ u_long td_profil_addr; /* (k) Temporary addr until AST. */ u_int td_profil_ticks; /* (k) Temporary ticks until AST. */ char td_name[MAXCOMLEN + 1]; /* (*) Thread name. */ struct file *td_fpop; /* (k) file referencing cdev under op */ int td_dbgflags; /* (c) Userland debugger flags */ struct ksiginfo td_dbgksi; /* (c) ksi reflected to debugger. */ int td_ng_outbound; /* (k) Thread entered ng from above. */ struct osd td_osd; /* (k) Object specific data. */ struct vm_map_entry *td_map_def_user; /* (k) Deferred entries. */ pid_t td_dbg_forked; /* (c) Child pid for debugger. */ u_int td_vp_reserv; /* (k) Count of reserved vnodes. */ int td_no_sleeping; /* (k) Sleeping disabled count. */ int td_dom_rr_idx; /* (k) RR Numa domain selection. */ void *td_su; /* (k) FFS SU private */ #define td_endzero td_sigmask /* Copied during fork1() or create_thread(). */ #define td_startcopy td_endzero sigset_t td_sigmask; /* (c) Current signal mask. */ u_char td_rqindex; /* (t) Run queue index. */ u_char td_base_pri; /* (t) Thread base kernel priority. */ u_char td_priority; /* (t) Thread active priority. */ u_char td_pri_class; /* (t) Scheduling class. */ u_char td_user_pri; /* (t) User pri from estcpu and nice. */ u_char td_base_user_pri; /* (t) Base user pri */ u_int td_dbg_sc_code; /* (c) Syscall code to debugger. */ u_int td_dbg_sc_narg; /* (c) Syscall arg count to debugger.*/ #define td_endcopy td_pcb /* * Fields that must be manually set in fork1() or create_thread() * or already have been set in the allocator, constructor, etc. */ struct pcb *td_pcb; /* (k) Kernel VA of pcb and kstack. */ enum { TDS_INACTIVE = 0x0, TDS_INHIBITED, TDS_CAN_RUN, TDS_RUNQ, TDS_RUNNING } td_state; /* (t) thread state */ union { register_t tdu_retval[2]; off_t tdu_off; } td_uretoff; /* (k) Syscall aux returns. */ #define td_retval td_uretoff.tdu_retval u_int td_cowgen; /* (k) Generation of COW pointers. */ struct callout td_slpcallout; /* (h) Callout for sleep. */ struct trapframe *td_frame; /* (k) */ struct vm_object *td_kstack_obj;/* (a) Kstack object. */ vm_offset_t td_kstack; /* (a) Kernel VA of kstack. */ int td_kstack_pages; /* (a) Size of the kstack. */ volatile u_int td_critnest; /* (k*) Critical section nest level. */ struct mdthread td_md; /* (k) Any machine-dependent fields. */ struct td_sched *td_sched; /* (*) Scheduler-specific data. */ struct kaudit_record *td_ar; /* (k) Active audit record, if any. */ struct lpohead td_lprof[2]; /* (a) lock profiling objects. */ struct kdtrace_thread *td_dtrace; /* (*) DTrace-specific data. */ int td_errno; /* Error returned by last syscall. */ struct vnet *td_vnet; /* (k) Effective vnet. */ const char *td_vnet_lpush; /* (k) Debugging vnet push / pop. */ struct trapframe *td_intr_frame;/* (k) Frame of the current irq */ struct proc *td_rfppwait_p; /* (k) The vforked child */ struct vm_page **td_ma; /* (k) uio pages held */ int td_ma_cnt; /* (k) size of *td_ma */ void *td_emuldata; /* Emulator state data */ int td_lastcpu; /* (t) Last cpu we were on. */ int td_oncpu; /* (t) Which cpu we are on. */ }; struct mtx *thread_lock_block(struct thread *); void thread_lock_unblock(struct thread *, struct mtx *); void thread_lock_set(struct thread *, struct mtx *); #define THREAD_LOCK_ASSERT(td, type) \ do { \ struct mtx *__m = (td)->td_lock; \ if (__m != &blocked_lock) \ mtx_assert(__m, (type)); \ } while (0) #ifdef INVARIANTS #define THREAD_LOCKPTR_ASSERT(td, lock) \ do { \ struct mtx *__m = (td)->td_lock; \ KASSERT((__m == &blocked_lock || __m == (lock)), \ ("Thread %p lock %p does not match %p", td, __m, (lock))); \ } while (0) #define TD_LOCKS_INC(td) ((td)->td_locks++) #define TD_LOCKS_DEC(td) ((td)->td_locks--) #else #define THREAD_LOCKPTR_ASSERT(td, lock) #define TD_LOCKS_INC(td) #define TD_LOCKS_DEC(td) #endif /* * Flags kept in td_flags: * To change these you MUST have the scheduler lock. */ #define TDF_BORROWING 0x00000001 /* Thread is borrowing pri from another. */ #define TDF_INPANIC 0x00000002 /* Caused a panic, let it drive crashdump. */ #define TDF_INMEM 0x00000004 /* Thread's stack is in memory. */ #define TDF_SINTR 0x00000008 /* Sleep is interruptible. */ #define TDF_TIMEOUT 0x00000010 /* Timing out during sleep. */ #define TDF_IDLETD 0x00000020 /* This is a per-CPU idle thread. */ #define TDF_CANSWAP 0x00000040 /* Thread can be swapped. */ #define TDF_SLEEPABORT 0x00000080 /* sleepq_abort was called. */ #define TDF_KTH_SUSP 0x00000100 /* kthread is suspended */ #define TDF_ALLPROCSUSP 0x00000200 /* suspended by SINGLE_ALLPROC */ #define TDF_BOUNDARY 0x00000400 /* Thread suspended at user boundary */ #define TDF_ASTPENDING 0x00000800 /* Thread has some asynchronous events. */ #define TDF_TIMOFAIL 0x00001000 /* Timeout from sleep after we were awake. */ #define TDF_SBDRY 0x00002000 /* Stop only on usermode boundary. */ #define TDF_UPIBLOCKED 0x00004000 /* Thread blocked on user PI mutex. */ #define TDF_NEEDSUSPCHK 0x00008000 /* Thread may need to suspend. */ #define TDF_NEEDRESCHED 0x00010000 /* Thread needs to yield. */ #define TDF_NEEDSIGCHK 0x00020000 /* Thread may need signal delivery. */ #define TDF_NOLOAD 0x00040000 /* Ignore during load avg calculations. */ #define TDF_UNUSED19 0x00080000 /* --available-- */ #define TDF_THRWAKEUP 0x00100000 /* Libthr thread must not suspend itself. */ #define TDF_UNUSED21 0x00200000 /* --available-- */ #define TDF_SWAPINREQ 0x00400000 /* Swapin request due to wakeup. */ #define TDF_UNUSED23 0x00800000 /* --available-- */ #define TDF_SCHED0 0x01000000 /* Reserved for scheduler private use */ #define TDF_SCHED1 0x02000000 /* Reserved for scheduler private use */ #define TDF_SCHED2 0x04000000 /* Reserved for scheduler private use */ #define TDF_SCHED3 0x08000000 /* Reserved for scheduler private use */ #define TDF_ALRMPEND 0x10000000 /* Pending SIGVTALRM needs to be posted. */ #define TDF_PROFPEND 0x20000000 /* Pending SIGPROF needs to be posted. */ #define TDF_MACPEND 0x40000000 /* AST-based MAC event pending. */ /* Userland debug flags */ #define TDB_SUSPEND 0x00000001 /* Thread is suspended by debugger */ #define TDB_XSIG 0x00000002 /* Thread is exchanging signal under trace */ #define TDB_USERWR 0x00000004 /* Debugger modified memory or registers */ #define TDB_SCE 0x00000008 /* Thread performs syscall enter */ #define TDB_SCX 0x00000010 /* Thread performs syscall exit */ #define TDB_EXEC 0x00000020 /* TDB_SCX from exec(2) family */ #define TDB_FORK 0x00000040 /* TDB_SCX from fork(2) that created new process */ #define TDB_STOPATFORK 0x00000080 /* Stop at the return from fork (child only) */ #define TDB_CHILD 0x00000100 /* New child indicator for ptrace() */ /* * "Private" flags kept in td_pflags: * These are only written by curthread and thus need no locking. */ #define TDP_OLDMASK 0x00000001 /* Need to restore mask after suspend. */ #define TDP_INKTR 0x00000002 /* Thread is currently in KTR code. */ #define TDP_INKTRACE 0x00000004 /* Thread is currently in KTRACE code. */ #define TDP_BUFNEED 0x00000008 /* Do not recurse into the buf flush */ #define TDP_COWINPROGRESS 0x00000010 /* Snapshot copy-on-write in progress. */ #define TDP_ALTSTACK 0x00000020 /* Have alternate signal stack. */ #define TDP_DEADLKTREAT 0x00000040 /* Lock aquisition - deadlock treatment. */ #define TDP_NOFAULTING 0x00000080 /* Do not handle page faults. */ #define TDP_UNUSED9 0x00000100 /* --available-- */ #define TDP_OWEUPC 0x00000200 /* Call addupc() at next AST. */ #define TDP_ITHREAD 0x00000400 /* Thread is an interrupt thread. */ #define TDP_SYNCIO 0x00000800 /* Local override, disable async i/o. */ #define TDP_SCHED1 0x00001000 /* Reserved for scheduler private use */ #define TDP_SCHED2 0x00002000 /* Reserved for scheduler private use */ #define TDP_SCHED3 0x00004000 /* Reserved for scheduler private use */ #define TDP_SCHED4 0x00008000 /* Reserved for scheduler private use */ #define TDP_GEOM 0x00010000 /* Settle GEOM before finishing syscall */ #define TDP_SOFTDEP 0x00020000 /* Stuck processing softdep worklist */ #define TDP_NORUNNINGBUF 0x00040000 /* Ignore runningbufspace check */ #define TDP_WAKEUP 0x00080000 /* Don't sleep in umtx cond_wait */ #define TDP_INBDFLUSH 0x00100000 /* Already in BO_BDFLUSH, do not recurse */ #define TDP_KTHREAD 0x00200000 /* This is an official kernel thread */ #define TDP_CALLCHAIN 0x00400000 /* Capture thread's callchain */ #define TDP_IGNSUSP 0x00800000 /* Permission to ignore the MNTK_SUSPEND* */ #define TDP_AUDITREC 0x01000000 /* Audit record pending on thread */ #define TDP_RFPPWAIT 0x02000000 /* Handle RFPPWAIT on syscall exit */ #define TDP_RESETSPUR 0x04000000 /* Reset spurious page fault history. */ #define TDP_NERRNO 0x08000000 /* Last errno is already in td_errno */ #define TDP_UIOHELD 0x10000000 /* Current uio has pages held in td_ma */ #define TDP_FORKING 0x20000000 /* Thread is being created through fork() */ #define TDP_EXECVMSPC 0x40000000 /* Execve destroyed old vmspace */ /* * Reasons that the current thread can not be run yet. * More than one may apply. */ #define TDI_SUSPENDED 0x0001 /* On suspension queue. */ #define TDI_SLEEPING 0x0002 /* Actually asleep! (tricky). */ #define TDI_SWAPPED 0x0004 /* Stack not in mem. Bad juju if run. */ #define TDI_LOCK 0x0008 /* Stopped on a lock. */ #define TDI_IWAIT 0x0010 /* Awaiting interrupt. */ #define TD_IS_SLEEPING(td) ((td)->td_inhibitors & TDI_SLEEPING) #define TD_ON_SLEEPQ(td) ((td)->td_wchan != NULL) #define TD_IS_SUSPENDED(td) ((td)->td_inhibitors & TDI_SUSPENDED) #define TD_IS_SWAPPED(td) ((td)->td_inhibitors & TDI_SWAPPED) #define TD_ON_LOCK(td) ((td)->td_inhibitors & TDI_LOCK) #define TD_AWAITING_INTR(td) ((td)->td_inhibitors & TDI_IWAIT) #define TD_IS_RUNNING(td) ((td)->td_state == TDS_RUNNING) #define TD_ON_RUNQ(td) ((td)->td_state == TDS_RUNQ) #define TD_CAN_RUN(td) ((td)->td_state == TDS_CAN_RUN) #define TD_IS_INHIBITED(td) ((td)->td_state == TDS_INHIBITED) #define TD_ON_UPILOCK(td) ((td)->td_flags & TDF_UPIBLOCKED) #define TD_IS_IDLETHREAD(td) ((td)->td_flags & TDF_IDLETD) #define TD_SET_INHIB(td, inhib) do { \ (td)->td_state = TDS_INHIBITED; \ (td)->td_inhibitors |= (inhib); \ } while (0) #define TD_CLR_INHIB(td, inhib) do { \ if (((td)->td_inhibitors & (inhib)) && \ (((td)->td_inhibitors &= ~(inhib)) == 0)) \ (td)->td_state = TDS_CAN_RUN; \ } while (0) #define TD_SET_SLEEPING(td) TD_SET_INHIB((td), TDI_SLEEPING) #define TD_SET_SWAPPED(td) TD_SET_INHIB((td), TDI_SWAPPED) #define TD_SET_LOCK(td) TD_SET_INHIB((td), TDI_LOCK) #define TD_SET_SUSPENDED(td) TD_SET_INHIB((td), TDI_SUSPENDED) #define TD_SET_IWAIT(td) TD_SET_INHIB((td), TDI_IWAIT) #define TD_SET_EXITING(td) TD_SET_INHIB((td), TDI_EXITING) #define TD_CLR_SLEEPING(td) TD_CLR_INHIB((td), TDI_SLEEPING) #define TD_CLR_SWAPPED(td) TD_CLR_INHIB((td), TDI_SWAPPED) #define TD_CLR_LOCK(td) TD_CLR_INHIB((td), TDI_LOCK) #define TD_CLR_SUSPENDED(td) TD_CLR_INHIB((td), TDI_SUSPENDED) #define TD_CLR_IWAIT(td) TD_CLR_INHIB((td), TDI_IWAIT) #define TD_SET_RUNNING(td) (td)->td_state = TDS_RUNNING #define TD_SET_RUNQ(td) (td)->td_state = TDS_RUNQ #define TD_SET_CAN_RUN(td) (td)->td_state = TDS_CAN_RUN /* * Process structure. */ struct proc { LIST_ENTRY(proc) p_list; /* (d) List of all processes. */ TAILQ_HEAD(, thread) p_threads; /* (c) all threads. */ struct mtx p_slock; /* process spin lock */ struct ucred *p_ucred; /* (c) Process owner's identity. */ struct filedesc *p_fd; /* (b) Open files. */ struct filedesc_to_leader *p_fdtol; /* (b) Tracking node */ struct pstats *p_stats; /* (b) Accounting/statistics (CPU). */ struct plimit *p_limit; /* (c) Resource limits. */ struct callout p_limco; /* (c) Limit callout handle */ struct sigacts *p_sigacts; /* (x) Signal actions, state (CPU). */ int p_flag; /* (c) P_* flags. */ int p_flag2; /* (c) P2_* flags. */ enum { PRS_NEW = 0, /* In creation */ PRS_NORMAL, /* threads can be run. */ PRS_ZOMBIE } p_state; /* (j/c) Process status. */ pid_t p_pid; /* (b) Process identifier. */ LIST_ENTRY(proc) p_hash; /* (d) Hash chain. */ LIST_ENTRY(proc) p_pglist; /* (g + e) List of processes in pgrp. */ struct proc *p_pptr; /* (c + e) Pointer to parent process. */ LIST_ENTRY(proc) p_sibling; /* (e) List of sibling processes. */ LIST_HEAD(, proc) p_children; /* (e) Pointer to list of children. */ struct proc *p_reaper; /* (e) My reaper. */ LIST_HEAD(, proc) p_reaplist; /* (e) List of my descendants (if I am reaper). */ LIST_ENTRY(proc) p_reapsibling; /* (e) List of siblings - descendants of the same reaper. */ struct mtx p_mtx; /* (n) Lock for this struct. */ struct mtx p_statmtx; /* Lock for the stats */ struct mtx p_itimmtx; /* Lock for the virt/prof timers */ struct mtx p_profmtx; /* Lock for the profiling */ struct ksiginfo *p_ksi; /* Locked by parent proc lock */ sigqueue_t p_sigqueue; /* (c) Sigs not delivered to a td. */ #define p_siglist p_sigqueue.sq_signals /* The following fields are all zeroed upon creation in fork. */ #define p_startzero p_oppid pid_t p_oppid; /* (c + e) Save ppid in ptrace. XXX */ struct vmspace *p_vmspace; /* (b) Address space. */ u_int p_swtick; /* (c) Tick when swapped in or out. */ u_int p_cowgen; /* (c) Generation of COW pointers. */ struct itimerval p_realtimer; /* (c) Alarm timer. */ struct rusage p_ru; /* (a) Exit information. */ struct rusage_ext p_rux; /* (cu) Internal resource usage. */ struct rusage_ext p_crux; /* (c) Internal child resource usage. */ int p_profthreads; /* (c) Num threads in addupc_task. */ volatile int p_exitthreads; /* (j) Number of threads exiting */ int p_traceflag; /* (o) Kernel trace points. */ struct vnode *p_tracevp; /* (c + o) Trace to vnode. */ struct ucred *p_tracecred; /* (o) Credentials to trace with. */ struct vnode *p_textvp; /* (b) Vnode of executable. */ u_int p_lock; /* (c) Proclock (prevent swap) count. */ struct sigiolst p_sigiolst; /* (c) List of sigio sources. */ int p_sigparent; /* (c) Signal to parent on exit. */ int p_sig; /* (n) For core dump/debugger XXX. */ u_long p_code; /* (n) For core dump/debugger XXX. */ u_int p_stops; /* (c) Stop event bitmask. */ u_int p_stype; /* (c) Stop event type. */ char p_step; /* (c) Process is stopped. */ u_char p_pfsflags; /* (c) Procfs flags. */ struct nlminfo *p_nlminfo; /* (?) Only used by/for lockd. */ struct kaioinfo *p_aioinfo; /* (y) ASYNC I/O info. */ struct thread *p_singlethread;/* (c + j) If single threading this is it */ int p_suspcount; /* (j) Num threads in suspended mode. */ struct thread *p_xthread; /* (c) Trap thread */ int p_boundary_count;/* (j) Num threads at user boundary */ int p_pendingcnt; /* how many signals are pending */ struct itimers *p_itimers; /* (c) POSIX interval timers. */ struct procdesc *p_procdesc; /* (e) Process descriptor, if any. */ u_int p_treeflag; /* (e) P_TREE flags */ /* End area that is zeroed on creation. */ #define p_endzero p_magic /* The following fields are all copied upon creation in fork. */ #define p_startcopy p_endzero u_int p_magic; /* (b) Magic number. */ int p_osrel; /* (x) osreldate for the binary (from ELF note, if any) */ char p_comm[MAXCOMLEN + 1]; /* (b) Process name. */ - struct pgrp *p_pgrp; /* (c + e) Pointer to process group. */ struct sysentvec *p_sysent; /* (b) Syscall dispatch info. */ struct pargs *p_args; /* (c) Process arguments. */ rlim_t p_cpulimit; /* (c) Current CPU limit in seconds. */ signed char p_nice; /* (c) Process "nice" value. */ int p_fibnum; /* in this routing domain XXX MRT */ pid_t p_reapsubtree; /* (e) Pid of the direct child of the reaper which spawned our subtree. */ u_int p_xexit; /* (c) Exit code. */ u_int p_xsig; /* (c) Stop/kill sig. */ /* End area that is copied on creation. */ #define p_endcopy p_xsig + struct pgrp *p_pgrp; /* (c + e) Pointer to process group. */ struct knlist p_klist; /* (c) Knotes attached to this proc. */ int p_numthreads; /* (c) Number of threads. */ struct mdproc p_md; /* Any machine-dependent fields. */ struct callout p_itcallout; /* (h + c) Interval timer callout. */ u_short p_acflag; /* (c) Accounting flags. */ struct proc *p_peers; /* (r) */ struct proc *p_leader; /* (b) */ void *p_emuldata; /* (c) Emulator state data. */ struct label *p_label; /* (*) Proc (not subject) MAC label. */ struct p_sched *p_sched; /* (*) Scheduler-specific data. */ STAILQ_HEAD(, ktr_request) p_ktr; /* (o) KTR event queue. */ LIST_HEAD(, mqueue_notifier) p_mqnotifier; /* (c) mqueue notifiers.*/ struct kdtrace_proc *p_dtrace; /* (*) DTrace-specific data. */ struct cv p_pwait; /* (*) wait cv for exit/exec. */ struct cv p_dbgwait; /* (*) wait cv for debugger attach after fork. */ uint64_t p_prev_runtime; /* (c) Resource usage accounting. */ struct racct *p_racct; /* (b) Resource accounting. */ u_char p_throttled; /* (c) Flag for racct pcpu throttling */ struct vm_domain_policy p_vm_dom_policy; /* (c) process default VM domain, or -1 */ /* * An orphan is the child that has beed re-parented to the * debugger as a result of attaching to it. Need to keep * track of them for parent to be able to collect the exit * status of what used to be children. */ LIST_ENTRY(proc) p_orphan; /* (e) List of orphan processes. */ LIST_HEAD(, proc) p_orphans; /* (e) Pointer to list of orphans. */ }; #define p_session p_pgrp->pg_session #define p_pgid p_pgrp->pg_id #define NOCPU (-1) /* For when we aren't on a CPU. */ #define NOCPU_OLD (255) #define MAXCPU_OLD (254) #define PROC_SLOCK(p) mtx_lock_spin(&(p)->p_slock) #define PROC_SUNLOCK(p) mtx_unlock_spin(&(p)->p_slock) #define PROC_SLOCK_ASSERT(p, type) mtx_assert(&(p)->p_slock, (type)) #define PROC_STATLOCK(p) mtx_lock_spin(&(p)->p_statmtx) #define PROC_STATUNLOCK(p) mtx_unlock_spin(&(p)->p_statmtx) #define PROC_STATLOCK_ASSERT(p, type) mtx_assert(&(p)->p_statmtx, (type)) #define PROC_ITIMLOCK(p) mtx_lock_spin(&(p)->p_itimmtx) #define PROC_ITIMUNLOCK(p) mtx_unlock_spin(&(p)->p_itimmtx) #define PROC_ITIMLOCK_ASSERT(p, type) mtx_assert(&(p)->p_itimmtx, (type)) #define PROC_PROFLOCK(p) mtx_lock_spin(&(p)->p_profmtx) #define PROC_PROFUNLOCK(p) mtx_unlock_spin(&(p)->p_profmtx) #define PROC_PROFLOCK_ASSERT(p, type) mtx_assert(&(p)->p_profmtx, (type)) /* These flags are kept in p_flag. */ #define P_ADVLOCK 0x00001 /* Process may hold a POSIX advisory lock. */ #define P_CONTROLT 0x00002 /* Has a controlling terminal. */ #define P_KTHREAD 0x00004 /* Kernel thread (*). */ #define P_FOLLOWFORK 0x00008 /* Attach parent debugger to children. */ #define P_PPWAIT 0x00010 /* Parent is waiting for child to exec/exit. */ #define P_PROFIL 0x00020 /* Has started profiling. */ #define P_STOPPROF 0x00040 /* Has thread requesting to stop profiling. */ #define P_HADTHREADS 0x00080 /* Has had threads (no cleanup shortcuts) */ #define P_SUGID 0x00100 /* Had set id privileges since last exec. */ #define P_SYSTEM 0x00200 /* System proc: no sigs, stats or swapping. */ #define P_SINGLE_EXIT 0x00400 /* Threads suspending should exit, not wait. */ #define P_TRACED 0x00800 /* Debugged process being traced. */ #define P_WAITED 0x01000 /* Someone is waiting for us. */ #define P_WEXIT 0x02000 /* Working on exiting. */ #define P_EXEC 0x04000 /* Process called exec. */ #define P_WKILLED 0x08000 /* Killed, go to kernel/user boundary ASAP. */ #define P_CONTINUED 0x10000 /* Proc has continued from a stopped state. */ #define P_STOPPED_SIG 0x20000 /* Stopped due to SIGSTOP/SIGTSTP. */ #define P_STOPPED_TRACE 0x40000 /* Stopped because of tracing. */ #define P_STOPPED_SINGLE 0x80000 /* Only 1 thread can continue (not to user). */ #define P_PROTECTED 0x100000 /* Do not kill on memory overcommit. */ #define P_SIGEVENT 0x200000 /* Process pending signals changed. */ #define P_SINGLE_BOUNDARY 0x400000 /* Threads should suspend at user boundary. */ #define P_HWPMC 0x800000 /* Process is using HWPMCs */ #define P_JAILED 0x1000000 /* Process is in jail. */ #define P_TOTAL_STOP 0x2000000 /* Stopped in stop_all_proc. */ #define P_INEXEC 0x4000000 /* Process is in execve(). */ #define P_STATCHILD 0x8000000 /* Child process stopped or exited. */ #define P_INMEM 0x10000000 /* Loaded into memory. */ #define P_SWAPPINGOUT 0x20000000 /* Process is being swapped out. */ #define P_SWAPPINGIN 0x40000000 /* Process is being swapped in. */ #define P_PPTRACE 0x80000000 /* PT_TRACEME by vforked child. */ #define P_STOPPED (P_STOPPED_SIG|P_STOPPED_SINGLE|P_STOPPED_TRACE) #define P_SHOULDSTOP(p) ((p)->p_flag & P_STOPPED) #define P_KILLED(p) ((p)->p_flag & P_WKILLED) /* These flags are kept in p_flag2. */ #define P2_INHERIT_PROTECTED 0x00000001 /* New children get P_PROTECTED. */ #define P2_NOTRACE 0x00000002 /* No ptrace(2) attach or coredumps. */ #define P2_NOTRACE_EXEC 0x00000004 /* Keep P2_NOPTRACE on exec(2). */ #define P2_AST_SU 0x00000008 /* Handles SU ast for kthreads. */ /* Flags protected by proctree_lock, kept in p_treeflags. */ #define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */ #define P_TREE_FIRST_ORPHAN 0x00000002 /* First element of orphan list */ #define P_TREE_REAPER 0x00000004 /* Reaper of subtree */ /* * These were process status values (p_stat), now they are only used in * legacy conversion code. */ #define SIDL 1 /* Process being created by fork. */ #define SRUN 2 /* Currently runnable. */ #define SSLEEP 3 /* Sleeping on an address. */ #define SSTOP 4 /* Process debugging or suspension. */ #define SZOMB 5 /* Awaiting collection by parent. */ #define SWAIT 6 /* Waiting for interrupt. */ #define SLOCK 7 /* Blocked on a lock. */ #define P_MAGIC 0xbeefface #ifdef _KERNEL /* Types and flags for mi_switch(). */ #define SW_TYPE_MASK 0xff /* First 8 bits are switch type */ #define SWT_NONE 0 /* Unspecified switch. */ #define SWT_PREEMPT 1 /* Switching due to preemption. */ #define SWT_OWEPREEMPT 2 /* Switching due to opepreempt. */ #define SWT_TURNSTILE 3 /* Turnstile contention. */ #define SWT_SLEEPQ 4 /* Sleepq wait. */ #define SWT_SLEEPQTIMO 5 /* Sleepq timeout wait. */ #define SWT_RELINQUISH 6 /* yield call. */ #define SWT_NEEDRESCHED 7 /* NEEDRESCHED was set. */ #define SWT_IDLE 8 /* Switching from the idle thread. */ #define SWT_IWAIT 9 /* Waiting for interrupts. */ #define SWT_SUSPEND 10 /* Thread suspended. */ #define SWT_REMOTEPREEMPT 11 /* Remote processor preempted. */ #define SWT_REMOTEWAKEIDLE 12 /* Remote processor preempted idle. */ #define SWT_COUNT 13 /* Number of switch types. */ /* Flags */ #define SW_VOL 0x0100 /* Voluntary switch. */ #define SW_INVOL 0x0200 /* Involuntary switch. */ #define SW_PREEMPT 0x0400 /* The invol switch is a preemption */ /* How values for thread_single(). */ #define SINGLE_NO_EXIT 0 #define SINGLE_EXIT 1 #define SINGLE_BOUNDARY 2 #define SINGLE_ALLPROC 3 #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_PARGS); MALLOC_DECLARE(M_PGRP); MALLOC_DECLARE(M_SESSION); MALLOC_DECLARE(M_SUBPROC); #endif #define FOREACH_PROC_IN_SYSTEM(p) \ LIST_FOREACH((p), &allproc, p_list) #define FOREACH_THREAD_IN_PROC(p, td) \ TAILQ_FOREACH((td), &(p)->p_threads, td_plist) #define FIRST_THREAD_IN_PROC(p) TAILQ_FIRST(&(p)->p_threads) /* * We use process IDs <= pid_max <= PID_MAX; PID_MAX + 1 must also fit * in a pid_t, as it is used to represent "no process group". */ #define PID_MAX 99999 #define NO_PID 100000 extern pid_t pid_max; #define SESS_LEADER(p) ((p)->p_session->s_leader == (p)) #define STOPEVENT(p, e, v) do { \ WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, \ "checking stopevent %d", (e)); \ if ((p)->p_stops & (e)) { \ PROC_LOCK(p); \ stopevent((p), (e), (v)); \ PROC_UNLOCK(p); \ } \ } while (0) #define _STOPEVENT(p, e, v) do { \ PROC_LOCK_ASSERT(p, MA_OWNED); \ WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, &p->p_mtx.lock_object, \ "checking stopevent %d", (e)); \ if ((p)->p_stops & (e)) \ stopevent((p), (e), (v)); \ } while (0) /* Lock and unlock a process. */ #define PROC_LOCK(p) mtx_lock(&(p)->p_mtx) #define PROC_TRYLOCK(p) mtx_trylock(&(p)->p_mtx) #define PROC_UNLOCK(p) mtx_unlock(&(p)->p_mtx) #define PROC_LOCKED(p) mtx_owned(&(p)->p_mtx) #define PROC_LOCK_ASSERT(p, type) mtx_assert(&(p)->p_mtx, (type)) /* Lock and unlock a process group. */ #define PGRP_LOCK(pg) mtx_lock(&(pg)->pg_mtx) #define PGRP_UNLOCK(pg) mtx_unlock(&(pg)->pg_mtx) #define PGRP_LOCKED(pg) mtx_owned(&(pg)->pg_mtx) #define PGRP_LOCK_ASSERT(pg, type) mtx_assert(&(pg)->pg_mtx, (type)) #define PGRP_LOCK_PGSIGNAL(pg) do { \ if ((pg) != NULL) \ PGRP_LOCK(pg); \ } while (0) #define PGRP_UNLOCK_PGSIGNAL(pg) do { \ if ((pg) != NULL) \ PGRP_UNLOCK(pg); \ } while (0) /* Lock and unlock a session. */ #define SESS_LOCK(s) mtx_lock(&(s)->s_mtx) #define SESS_UNLOCK(s) mtx_unlock(&(s)->s_mtx) #define SESS_LOCKED(s) mtx_owned(&(s)->s_mtx) #define SESS_LOCK_ASSERT(s, type) mtx_assert(&(s)->s_mtx, (type)) /* Hold process U-area in memory, normally for ptrace/procfs work. */ #define PHOLD(p) do { \ PROC_LOCK(p); \ _PHOLD(p); \ PROC_UNLOCK(p); \ } while (0) #define _PHOLD(p) do { \ PROC_LOCK_ASSERT((p), MA_OWNED); \ KASSERT(!((p)->p_flag & P_WEXIT) || (p) == curproc, \ ("PHOLD of exiting process %p", p)); \ (p)->p_lock++; \ if (((p)->p_flag & P_INMEM) == 0) \ faultin((p)); \ } while (0) #define PROC_ASSERT_HELD(p) do { \ KASSERT((p)->p_lock > 0, ("process %p not held", p)); \ } while (0) #define PRELE(p) do { \ PROC_LOCK((p)); \ _PRELE((p)); \ PROC_UNLOCK((p)); \ } while (0) #define _PRELE(p) do { \ PROC_LOCK_ASSERT((p), MA_OWNED); \ PROC_ASSERT_HELD(p); \ (--(p)->p_lock); \ if (((p)->p_flag & P_WEXIT) && (p)->p_lock == 0) \ wakeup(&(p)->p_lock); \ } while (0) #define PROC_ASSERT_NOT_HELD(p) do { \ KASSERT((p)->p_lock == 0, ("process %p held", p)); \ } while (0) #define PROC_UPDATE_COW(p) do { \ PROC_LOCK_ASSERT((p), MA_OWNED); \ (p)->p_cowgen++; \ } while (0) /* Check whether a thread is safe to be swapped out. */ #define thread_safetoswapout(td) ((td)->td_flags & TDF_CANSWAP) /* Control whether or not it is safe for curthread to sleep. */ #define THREAD_NO_SLEEPING() ((curthread)->td_no_sleeping++) #define THREAD_SLEEPING_OK() ((curthread)->td_no_sleeping--) #define THREAD_CAN_SLEEP() ((curthread)->td_no_sleeping == 0) #define PIDHASH(pid) (&pidhashtbl[(pid) & pidhash]) extern LIST_HEAD(pidhashhead, proc) *pidhashtbl; extern u_long pidhash; #define TIDHASH(tid) (&tidhashtbl[(tid) & tidhash]) extern LIST_HEAD(tidhashhead, thread) *tidhashtbl; extern u_long tidhash; extern struct rwlock tidhash_lock; #define PGRPHASH(pgid) (&pgrphashtbl[(pgid) & pgrphash]) extern LIST_HEAD(pgrphashhead, pgrp) *pgrphashtbl; extern u_long pgrphash; extern struct sx allproc_lock; extern int allproc_gen; extern struct sx proctree_lock; extern struct mtx ppeers_lock; extern struct proc proc0; /* Process slot for swapper. */ extern struct thread thread0; /* Primary thread in proc0. */ extern struct vmspace vmspace0; /* VM space for proc0. */ extern int hogticks; /* Limit on kernel cpu hogs. */ extern int lastpid; extern int nprocs, maxproc; /* Current and max number of procs. */ extern int maxprocperuid; /* Max procs per uid. */ extern u_long ps_arg_cache_limit; LIST_HEAD(proclist, proc); TAILQ_HEAD(procqueue, proc); TAILQ_HEAD(threadqueue, thread); extern struct proclist allproc; /* List of all processes. */ extern struct proclist zombproc; /* List of zombie processes. */ extern struct proc *initproc, *pageproc; /* Process slots for init, pager. */ extern struct uma_zone *proc_zone; struct proc *pfind(pid_t); /* Find process by id. */ struct proc *pfind_locked(pid_t pid); struct pgrp *pgfind(pid_t); /* Find process group by id. */ struct proc *zpfind(pid_t); /* Find zombie process by id. */ /* * pget() flags. */ #define PGET_HOLD 0x00001 /* Hold the process. */ #define PGET_CANSEE 0x00002 /* Check against p_cansee(). */ #define PGET_CANDEBUG 0x00004 /* Check against p_candebug(). */ #define PGET_ISCURRENT 0x00008 /* Check that the found process is current. */ #define PGET_NOTWEXIT 0x00010 /* Check that the process is not in P_WEXIT. */ #define PGET_NOTINEXEC 0x00020 /* Check that the process is not in P_INEXEC. */ #define PGET_NOTID 0x00040 /* Do not assume tid if pid > PID_MAX. */ #define PGET_WANTREAD (PGET_HOLD | PGET_CANDEBUG | PGET_NOTWEXIT) int pget(pid_t pid, int flags, struct proc **pp); void ast(struct trapframe *framep); struct thread *choosethread(void); int cr_cansignal(struct ucred *cred, struct proc *proc, int signum); int enterpgrp(struct proc *p, pid_t pgid, struct pgrp *pgrp, struct session *sess); int enterthispgrp(struct proc *p, struct pgrp *pgrp); void faultin(struct proc *p); void fixjobc(struct proc *p, struct pgrp *pgrp, int entering); int fork1(struct thread *, int, int, struct proc **, int *, int, struct filecaps *); void fork_exit(void (*)(void *, struct trapframe *), void *, struct trapframe *); void fork_return(struct thread *, struct trapframe *); int inferior(struct proc *p); void kern_yield(int); void kick_proc0(void); int leavepgrp(struct proc *p); int maybe_preempt(struct thread *td); void maybe_yield(void); void mi_switch(int flags, struct thread *newtd); int p_candebug(struct thread *td, struct proc *p); int p_cansee(struct thread *td, struct proc *p); int p_cansched(struct thread *td, struct proc *p); int p_cansignal(struct thread *td, struct proc *p, int signum); int p_canwait(struct thread *td, struct proc *p); struct pargs *pargs_alloc(int len); void pargs_drop(struct pargs *pa); void pargs_hold(struct pargs *pa); int proc_getargv(struct thread *td, struct proc *p, struct sbuf *sb); int proc_getauxv(struct thread *td, struct proc *p, struct sbuf *sb); int proc_getenvv(struct thread *td, struct proc *p, struct sbuf *sb); void procinit(void); void proc_linkup0(struct proc *p, struct thread *td); void proc_linkup(struct proc *p, struct thread *td); struct proc *proc_realparent(struct proc *child); void proc_reap(struct thread *td, struct proc *p, int *status, int options); void proc_reparent(struct proc *child, struct proc *newparent); struct pstats *pstats_alloc(void); void pstats_fork(struct pstats *src, struct pstats *dst); void pstats_free(struct pstats *ps); void reaper_abandon_children(struct proc *p, bool exiting); int securelevel_ge(struct ucred *cr, int level); int securelevel_gt(struct ucred *cr, int level); void sess_hold(struct session *); void sess_release(struct session *); int setrunnable(struct thread *); void setsugid(struct proc *p); int should_yield(void); int sigonstack(size_t sp); void stopevent(struct proc *, u_int, u_int); struct thread *tdfind(lwpid_t, pid_t); void threadinit(void); void tidhash_add(struct thread *); void tidhash_remove(struct thread *); void cpu_idle(int); int cpu_idle_wakeup(int); extern void (*cpu_idle_hook)(sbintime_t); /* Hook to machdep CPU idler. */ void cpu_switch(struct thread *, struct thread *, struct mtx *); void cpu_throw(struct thread *, struct thread *) __dead2; void unsleep(struct thread *); void userret(struct thread *, struct trapframe *); void cpu_exit(struct thread *); void exit1(struct thread *, int, int) __dead2; int cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa); void cpu_fork(struct thread *, struct proc *, struct thread *, int); void cpu_set_fork_handler(struct thread *, void (*)(void *), void *); void cpu_set_syscall_retval(struct thread *, int); void cpu_set_upcall(struct thread *td, struct thread *td0); void cpu_set_upcall_kse(struct thread *, void (*)(void *), void *, stack_t *); int cpu_set_user_tls(struct thread *, void *tls_base); void cpu_thread_alloc(struct thread *); void cpu_thread_clean(struct thread *); void cpu_thread_exit(struct thread *); void cpu_thread_free(struct thread *); void cpu_thread_swapin(struct thread *); void cpu_thread_swapout(struct thread *); struct thread *thread_alloc(int pages); int thread_alloc_stack(struct thread *, int pages); void thread_cow_get_proc(struct thread *newtd, struct proc *p); void thread_cow_get(struct thread *newtd, struct thread *td); void thread_cow_free(struct thread *td); void thread_cow_update(struct thread *td); int thread_create(struct thread *td, struct rtprio *rtp, int (*initialize_thread)(struct thread *, void *), void *thunk); void thread_exit(void) __dead2; void thread_free(struct thread *td); void thread_link(struct thread *td, struct proc *p); void thread_reap(void); int thread_single(struct proc *p, int how); void thread_single_end(struct proc *p, int how); void thread_stash(struct thread *td); void thread_stopped(struct proc *p); void childproc_stopped(struct proc *child, int reason); void childproc_continued(struct proc *child); void childproc_exited(struct proc *child); int thread_suspend_check(int how); bool thread_suspend_check_needed(void); void thread_suspend_switch(struct thread *, struct proc *p); void thread_suspend_one(struct thread *td); void thread_unlink(struct thread *td); void thread_unsuspend(struct proc *p); void thread_wait(struct proc *p); struct thread *thread_find(struct proc *p, lwpid_t tid); void stop_all_proc(void); void resume_all_proc(void); static __inline int curthread_pflags_set(int flags) { struct thread *td; int save; td = curthread; save = ~flags | (td->td_pflags & flags); td->td_pflags |= flags; return (save); } static __inline void curthread_pflags_restore(int save) { curthread->td_pflags &= save; } #endif /* _KERNEL */ #endif /* !_SYS_PROC_H_ */ Index: user/alc/PQ_LAUNDRY/sys/vm/device_pager.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/vm/device_pager.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/vm/device_pager.c (revision 292449) @@ -1,427 +1,426 @@ /*- * Copyright (c) 1990 University of Utah. * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * 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. * 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. * * @(#)device_pager.c 8.1 (Berkeley) 6/11/93 */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void dev_pager_init(void); static vm_object_t dev_pager_alloc(void *, vm_ooffset_t, vm_prot_t, vm_ooffset_t, struct ucred *); static void dev_pager_dealloc(vm_object_t); static int dev_pager_getpages(vm_object_t, vm_page_t *, int, int *, int *); static void dev_pager_putpages(vm_object_t, vm_page_t *, int, int, int *); static boolean_t dev_pager_haspage(vm_object_t, vm_pindex_t, int *, int *); static void dev_pager_free_page(vm_object_t object, vm_page_t m); /* list of device pager objects */ static struct pagerlst dev_pager_object_list; /* protect list manipulation */ static struct mtx dev_pager_mtx; struct pagerops devicepagerops = { .pgo_init = dev_pager_init, .pgo_alloc = dev_pager_alloc, .pgo_dealloc = dev_pager_dealloc, .pgo_getpages = dev_pager_getpages, .pgo_putpages = dev_pager_putpages, .pgo_haspage = dev_pager_haspage, }; struct pagerops mgtdevicepagerops = { .pgo_alloc = dev_pager_alloc, .pgo_dealloc = dev_pager_dealloc, .pgo_getpages = dev_pager_getpages, .pgo_putpages = dev_pager_putpages, .pgo_haspage = dev_pager_haspage, }; static int old_dev_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot, vm_ooffset_t foff, struct ucred *cred, u_short *color); static void old_dev_pager_dtor(void *handle); static int old_dev_pager_fault(vm_object_t object, vm_ooffset_t offset, int prot, vm_page_t *mres); static struct cdev_pager_ops old_dev_pager_ops = { .cdev_pg_ctor = old_dev_pager_ctor, .cdev_pg_dtor = old_dev_pager_dtor, .cdev_pg_fault = old_dev_pager_fault }; static void dev_pager_init(void) { TAILQ_INIT(&dev_pager_object_list); mtx_init(&dev_pager_mtx, "dev_pager list", NULL, MTX_DEF); } vm_object_t cdev_pager_lookup(void *handle) { vm_object_t object; mtx_lock(&dev_pager_mtx); object = vm_pager_object_lookup(&dev_pager_object_list, handle); mtx_unlock(&dev_pager_mtx); return (object); } vm_object_t cdev_pager_allocate(void *handle, enum obj_type tp, struct cdev_pager_ops *ops, vm_ooffset_t size, vm_prot_t prot, vm_ooffset_t foff, struct ucred *cred) { vm_object_t object, object1; vm_pindex_t pindex; u_short color; if (tp != OBJT_DEVICE && tp != OBJT_MGTDEVICE) return (NULL); /* * Offset should be page aligned. */ if (foff & PAGE_MASK) return (NULL); size = round_page(size); pindex = OFF_TO_IDX(foff + size); if (ops->cdev_pg_ctor(handle, size, prot, foff, cred, &color) != 0) return (NULL); mtx_lock(&dev_pager_mtx); /* * Look up pager, creating as necessary. */ object1 = NULL; object = vm_pager_object_lookup(&dev_pager_object_list, handle); if (object == NULL) { /* * Allocate object and associate it with the pager. Initialize * the object's pg_color based upon the physical address of the * device's memory. */ mtx_unlock(&dev_pager_mtx); object1 = vm_object_allocate(tp, pindex); object1->flags |= OBJ_COLORED; object1->pg_color = color; object1->handle = handle; object1->un_pager.devp.ops = ops; object1->un_pager.devp.dev = handle; TAILQ_INIT(&object1->un_pager.devp.devp_pglist); mtx_lock(&dev_pager_mtx); object = vm_pager_object_lookup(&dev_pager_object_list, handle); if (object != NULL) { /* * We raced with other thread while allocating object. */ if (pindex > object->size) object->size = pindex; KASSERT(object->type == tp, ("Inconsistent device pager type %p %d", object, tp)); } else { object = object1; object1 = NULL; object->handle = handle; TAILQ_INSERT_TAIL(&dev_pager_object_list, object, pager_object_list); } } else { if (pindex > object->size) object->size = pindex; KASSERT(object->type == tp, ("Inconsistent device pager type %p %d", object, tp)); } mtx_unlock(&dev_pager_mtx); if (object1 != NULL) { object1->handle = object1; mtx_lock(&dev_pager_mtx); TAILQ_INSERT_TAIL(&dev_pager_object_list, object1, pager_object_list); mtx_unlock(&dev_pager_mtx); vm_object_deallocate(object1); } return (object); } static vm_object_t dev_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, vm_ooffset_t foff, struct ucred *cred) { return (cdev_pager_allocate(handle, OBJT_DEVICE, &old_dev_pager_ops, size, prot, foff, cred)); } void cdev_pager_free_page(vm_object_t object, vm_page_t m) { VM_OBJECT_ASSERT_WLOCKED(object); if (object->type == OBJT_MGTDEVICE) { KASSERT((m->oflags & VPO_UNMANAGED) == 0, ("unmanaged %p", m)); pmap_remove_all(m); vm_page_lock(m); vm_page_remove(m); vm_page_unlock(m); } else if (object->type == OBJT_DEVICE) dev_pager_free_page(object, m); } static void dev_pager_free_page(vm_object_t object, vm_page_t m) { VM_OBJECT_ASSERT_WLOCKED(object); KASSERT((object->type == OBJT_DEVICE && (m->oflags & VPO_UNMANAGED) != 0), ("Managed device or page obj %p m %p", object, m)); TAILQ_REMOVE(&object->un_pager.devp.devp_pglist, m, plinks.q); vm_page_putfake(m); } static void dev_pager_dealloc(vm_object_t object) { vm_page_t m; VM_OBJECT_WUNLOCK(object); object->un_pager.devp.ops->cdev_pg_dtor(object->un_pager.devp.dev); mtx_lock(&dev_pager_mtx); TAILQ_REMOVE(&dev_pager_object_list, object, pager_object_list); mtx_unlock(&dev_pager_mtx); VM_OBJECT_WLOCK(object); if (object->type == OBJT_DEVICE) { /* * Free up our fake pages. */ while ((m = TAILQ_FIRST(&object->un_pager.devp.devp_pglist)) != NULL) dev_pager_free_page(object, m); } object->handle = NULL; object->type = OBJT_DEAD; } static int dev_pager_getpages(vm_object_t object, vm_page_t *ma, int count, int *rbehind, int *rahead) { int error; /* Since our haspage reports zero after/before, the count is 1. */ KASSERT(count == 1, ("%s: count %d", __func__, count)); VM_OBJECT_ASSERT_WLOCKED(object); error = object->un_pager.devp.ops->cdev_pg_fault(object, IDX_TO_OFF(ma[0]->pindex), PROT_READ, &ma[0]); VM_OBJECT_ASSERT_WLOCKED(object); if (error == VM_PAGER_OK) { KASSERT((object->type == OBJT_DEVICE && (ma[0]->oflags & VPO_UNMANAGED) != 0) || (object->type == OBJT_MGTDEVICE && (ma[0]->oflags & VPO_UNMANAGED) == 0), ("Wrong page type %p %p", ma[0], object)); if (object->type == OBJT_DEVICE) { TAILQ_INSERT_TAIL(&object->un_pager.devp.devp_pglist, ma[0], plinks.q); } if (rbehind) *rbehind = 0; if (rahead) *rahead = 0; } return (error); } static int old_dev_pager_fault(vm_object_t object, vm_ooffset_t offset, int prot, vm_page_t *mres) { vm_paddr_t paddr; vm_page_t m_paddr, page; struct cdev *dev; struct cdevsw *csw; struct file *fpop; struct thread *td; vm_memattr_t memattr; int ref, ret; memattr = object->memattr; VM_OBJECT_WUNLOCK(object); dev = object->handle; csw = dev_refthread(dev, &ref); if (csw == NULL) { VM_OBJECT_WLOCK(object); return (VM_PAGER_FAIL); } td = curthread; fpop = td->td_fpop; td->td_fpop = NULL; ret = csw->d_mmap(dev, offset, &paddr, prot, &memattr); td->td_fpop = fpop; dev_relthread(dev, ref); if (ret != 0) { printf( "WARNING: dev_pager_getpage: map function returns error %d", ret); VM_OBJECT_WLOCK(object); return (VM_PAGER_FAIL); } /* If "paddr" is a real page, perform a sanity check on "memattr". */ if ((m_paddr = vm_phys_paddr_to_vm_page(paddr)) != NULL && pmap_page_get_memattr(m_paddr) != memattr) { memattr = pmap_page_get_memattr(m_paddr); printf( "WARNING: A device driver has set \"memattr\" inconsistently.\n"); } if (((*mres)->flags & PG_FICTITIOUS) != 0) { /* * If the passed in result page is a fake page, update it with * the new physical address. */ page = *mres; VM_OBJECT_WLOCK(object); vm_page_updatefake(page, paddr, memattr); } else { /* * Replace the passed in reqpage page with our own fake page and * free up the all of the original pages. */ page = vm_page_getfake(paddr, memattr); VM_OBJECT_WLOCK(object); - if (vm_page_replace(page, object, (*mres)->pindex) != *mres) - panic("old_dev_pager_fault: invalid page replacement"); + vm_page_replace_checked(page, object, (*mres)->pindex, *mres); vm_page_lock(*mres); vm_page_free(*mres); vm_page_unlock(*mres); *mres = page; } page->valid = VM_PAGE_BITS_ALL; return (VM_PAGER_OK); } static void dev_pager_putpages(vm_object_t object, vm_page_t *m, int count, int flags, int *rtvals) { panic("dev_pager_putpage called"); } static boolean_t dev_pager_haspage(vm_object_t object, vm_pindex_t pindex, int *before, int *after) { if (before != NULL) *before = 0; if (after != NULL) *after = 0; return (TRUE); } static int old_dev_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot, vm_ooffset_t foff, struct ucred *cred, u_short *color) { struct cdev *dev; struct cdevsw *csw; vm_memattr_t dummy; vm_ooffset_t off; vm_paddr_t paddr; unsigned int npages; int ref; /* * Make sure this device can be mapped. */ dev = handle; csw = dev_refthread(dev, &ref); if (csw == NULL) return (ENXIO); /* * Check that the specified range of the device allows the desired * protection. * * XXX assumes VM_PROT_* == PROT_* */ npages = OFF_TO_IDX(size); paddr = 0; /* Make paddr initialized for the case of size == 0. */ for (off = foff; npages--; off += PAGE_SIZE) { if (csw->d_mmap(dev, off, &paddr, (int)prot, &dummy) != 0) { dev_relthread(dev, ref); return (EINVAL); } } dev_ref(dev); dev_relthread(dev, ref); *color = atop(paddr) - OFF_TO_IDX(off - PAGE_SIZE); return (0); } static void old_dev_pager_dtor(void *handle) { dev_rel(handle); } Index: user/alc/PQ_LAUNDRY/sys/vm/sg_pager.c =================================================================== --- user/alc/PQ_LAUNDRY/sys/vm/sg_pager.c (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/vm/sg_pager.c (revision 292449) @@ -1,222 +1,221 @@ /*- * Copyright (c) 2009 Hudson River Trading LLC * Written by: John H. Baldwin * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * This pager manages OBJT_SG objects. These objects are backed by * a scatter/gather list of physical address ranges. */ #include #include #include #include #include #include #include #include #include #include #include #include static vm_object_t sg_pager_alloc(void *, vm_ooffset_t, vm_prot_t, vm_ooffset_t, struct ucred *); static void sg_pager_dealloc(vm_object_t); static int sg_pager_getpages(vm_object_t, vm_page_t *, int, int *, int *); static void sg_pager_putpages(vm_object_t, vm_page_t *, int, boolean_t, int *); static boolean_t sg_pager_haspage(vm_object_t, vm_pindex_t, int *, int *); struct pagerops sgpagerops = { .pgo_alloc = sg_pager_alloc, .pgo_dealloc = sg_pager_dealloc, .pgo_getpages = sg_pager_getpages, .pgo_putpages = sg_pager_putpages, .pgo_haspage = sg_pager_haspage, }; static vm_object_t sg_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, vm_ooffset_t foff, struct ucred *cred) { struct sglist *sg; vm_object_t object; vm_pindex_t npages, pindex; int i; /* * Offset should be page aligned. */ if (foff & PAGE_MASK) return (NULL); /* * The scatter/gather list must only include page-aligned * ranges. */ npages = 0; sg = handle; for (i = 0; i < sg->sg_nseg; i++) { if ((sg->sg_segs[i].ss_paddr % PAGE_SIZE) != 0 || (sg->sg_segs[i].ss_len % PAGE_SIZE) != 0) return (NULL); npages += sg->sg_segs[i].ss_len / PAGE_SIZE; } /* * The scatter/gather list has a fixed size. Refuse requests * to map beyond that. */ size = round_page(size); pindex = OFF_TO_IDX(foff + size); if (pindex > npages) return (NULL); /* * Allocate a new object and associate it with the * scatter/gather list. It is ok for our purposes to have * multiple VM objects associated with the same scatter/gather * list because scatter/gather lists are static. This is also * simpler than ensuring a unique object per scatter/gather * list. */ object = vm_object_allocate(OBJT_SG, npages); object->handle = sglist_hold(sg); TAILQ_INIT(&object->un_pager.sgp.sgp_pglist); return (object); } static void sg_pager_dealloc(vm_object_t object) { struct sglist *sg; vm_page_t m; /* * Free up our fake pages. */ while ((m = TAILQ_FIRST(&object->un_pager.sgp.sgp_pglist)) != 0) { TAILQ_REMOVE(&object->un_pager.sgp.sgp_pglist, m, plinks.q); vm_page_putfake(m); } sg = object->handle; sglist_free(sg); object->handle = NULL; object->type = OBJT_DEAD; } static int sg_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind, int *rahead) { struct sglist *sg; vm_page_t m_paddr, page; vm_pindex_t offset; vm_paddr_t paddr; vm_memattr_t memattr; size_t space; int i; /* Since our haspage reports zero after/before, the count is 1. */ KASSERT(count == 1, ("%s: count %d", __func__, count)); VM_OBJECT_ASSERT_WLOCKED(object); sg = object->handle; memattr = object->memattr; VM_OBJECT_WUNLOCK(object); offset = m[0]->pindex; /* * Lookup the physical address of the requested page. An initial * value of '1' instead of '0' is used so we can assert that the * page is found since '0' can be a valid page-aligned physical * address. */ space = 0; paddr = 1; for (i = 0; i < sg->sg_nseg; i++) { if (space + sg->sg_segs[i].ss_len <= (offset * PAGE_SIZE)) { space += sg->sg_segs[i].ss_len; continue; } paddr = sg->sg_segs[i].ss_paddr + offset * PAGE_SIZE - space; break; } KASSERT(paddr != 1, ("invalid SG page index")); /* If "paddr" is a real page, perform a sanity check on "memattr". */ if ((m_paddr = vm_phys_paddr_to_vm_page(paddr)) != NULL && pmap_page_get_memattr(m_paddr) != memattr) { memattr = pmap_page_get_memattr(m_paddr); printf( "WARNING: A device driver has set \"memattr\" inconsistently.\n"); } /* Return a fake page for the requested page. */ KASSERT(!(m[0]->flags & PG_FICTITIOUS), ("backing page for SG is fake")); /* Construct a new fake page. */ page = vm_page_getfake(paddr, memattr); VM_OBJECT_WLOCK(object); TAILQ_INSERT_TAIL(&object->un_pager.sgp.sgp_pglist, page, plinks.q); - if (vm_page_replace(page, object, offset) != m[0]) - panic("sg_pager_getpages: invalid place replacement"); + vm_page_replace_checked(page, object, offset, m[0]); m[0] = page; page->valid = VM_PAGE_BITS_ALL; if (rbehind) *rbehind = 0; if (rahead) *rahead = 0; return (VM_PAGER_OK); } static void sg_pager_putpages(vm_object_t object, vm_page_t *m, int count, boolean_t sync, int *rtvals) { panic("sg_pager_putpage called"); } static boolean_t sg_pager_haspage(vm_object_t object, vm_pindex_t pindex, int *before, int *after) { if (before != NULL) *before = 0; if (after != NULL) *after = 0; return (TRUE); } Index: user/alc/PQ_LAUNDRY/sys/vm/vm_page.h =================================================================== --- user/alc/PQ_LAUNDRY/sys/vm/vm_page.h (revision 292448) +++ user/alc/PQ_LAUNDRY/sys/vm/vm_page.h (revision 292449) @@ -1,683 +1,698 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * The Mach Operating System project at Carnegie-Mellon University. * * 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. * 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. * * from: @(#)vm_page.h 8.2 (Berkeley) 12/13/93 * * * Copyright (c) 1987, 1990 Carnegie-Mellon University. * All rights reserved. * * Authors: Avadis Tevanian, Jr., Michael Wayne Young * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * * $FreeBSD$ */ /* * Resident memory system definitions. */ #ifndef _VM_PAGE_ #define _VM_PAGE_ #include /* * Management of resident (logical) pages. * * A small structure is kept for each resident * page, indexed by page number. Each structure * is an element of several collections: * * A radix tree used to quickly * perform object/offset lookups * * A list of all pages for a given object, * so they can be quickly deactivated at * time of deallocation. * * An ordered list of pages due for pageout. * * In addition, the structure contains the object * and offset to which this page belongs (for pageout), * and sundry status bits. * * In general, operations on this structure's mutable fields are * synchronized using either one of or a combination of the lock on the * object that the page belongs to (O), the pool lock for the page (P), * or the lock for either the free or paging queue (Q). If a field is * annotated below with two of these locks, then holding either lock is * sufficient for read access, but both locks are required for write * access. * * In contrast, the synchronization of accesses to the page's * dirty field is machine dependent (M). In the * machine-independent layer, the lock on the object that the * page belongs to must be held in order to operate on the field. * However, the pmap layer is permitted to set all bits within * the field without holding that lock. If the underlying * architecture does not support atomic read-modify-write * operations on the field's type, then the machine-independent * layer uses a 32-bit atomic on the aligned 32-bit word that * contains the dirty field. In the machine-independent layer, * the implementation of read-modify-write operations on the * field is encapsulated in vm_page_clear_dirty_mask(). */ #if PAGE_SIZE == 4096 #define VM_PAGE_BITS_ALL 0xffu typedef uint8_t vm_page_bits_t; #elif PAGE_SIZE == 8192 #define VM_PAGE_BITS_ALL 0xffffu typedef uint16_t vm_page_bits_t; #elif PAGE_SIZE == 16384 #define VM_PAGE_BITS_ALL 0xffffffffu typedef uint32_t vm_page_bits_t; #elif PAGE_SIZE == 32768 #define VM_PAGE_BITS_ALL 0xfffffffffffffffflu typedef uint64_t vm_page_bits_t; #endif struct vm_page { union { TAILQ_ENTRY(vm_page) q; /* page queue or free list (Q) */ struct { SLIST_ENTRY(vm_page) ss; /* private slists */ void *pv; } s; struct { u_long p; u_long v; } memguard; } plinks; TAILQ_ENTRY(vm_page) listq; /* pages in same object (O) */ vm_object_t object; /* which object am I in (O,P) */ vm_pindex_t pindex; /* offset into object (O,P) */ vm_paddr_t phys_addr; /* physical address of page */ struct md_page md; /* machine dependant stuff */ u_int wire_count; /* wired down maps refs (P) */ volatile u_int busy_lock; /* busy owners lock */ uint16_t hold_count; /* page hold count (P) */ uint16_t flags; /* page PG_* flags (P) */ uint8_t aflags; /* access is atomic */ uint8_t oflags; /* page VPO_* flags (O) */ uint8_t queue; /* page queue index (P,Q) */ int8_t psind; /* pagesizes[] index (O) */ int8_t segind; uint8_t order; /* index of the buddy queue */ uint8_t pool; u_char act_count; /* page usage count (P) */ /* NOTE that these must support one bit per DEV_BSIZE in a page */ /* so, on normal X86 kernels, they must be at least 8 bits wide */ vm_page_bits_t valid; /* map of valid DEV_BSIZE chunks (O) */ vm_page_bits_t dirty; /* map of dirty DEV_BSIZE chunks (M) */ }; /* * Page flags stored in oflags: * * Access to these page flags is synchronized by the lock on the object * containing the page (O). * * Note: VPO_UNMANAGED (used by OBJT_DEVICE, OBJT_PHYS and OBJT_SG) * indicates that the page is not under PV management but * otherwise should be treated as a normal page. Pages not * under PV management cannot be paged out via the * object/vm_page_t because there is no knowledge of their pte * mappings, and such pages are also not on any PQ queue. * */ #define VPO_UNUSED01 0x01 /* --available-- */ #define VPO_SWAPSLEEP 0x02 /* waiting for swap to finish */ #define VPO_UNMANAGED 0x04 /* no PV management for page */ #define VPO_SWAPINPROG 0x08 /* swap I/O in progress on page */ #define VPO_NOSYNC 0x10 /* do not collect for syncer */ /* * Busy page implementation details. * The algorithm is taken mostly by rwlock(9) and sx(9) locks implementation, * even if the support for owner identity is removed because of size * constraints. Checks on lock recursion are then not possible, while the * lock assertions effectiveness is someway reduced. */ #define VPB_BIT_SHARED 0x01 #define VPB_BIT_EXCLUSIVE 0x02 #define VPB_BIT_WAITERS 0x04 #define VPB_BIT_FLAGMASK \ (VPB_BIT_SHARED | VPB_BIT_EXCLUSIVE | VPB_BIT_WAITERS) #define VPB_SHARERS_SHIFT 3 #define VPB_SHARERS(x) \ (((x) & ~VPB_BIT_FLAGMASK) >> VPB_SHARERS_SHIFT) #define VPB_SHARERS_WORD(x) ((x) << VPB_SHARERS_SHIFT | VPB_BIT_SHARED) #define VPB_ONE_SHARER (1 << VPB_SHARERS_SHIFT) #define VPB_SINGLE_EXCLUSIVER VPB_BIT_EXCLUSIVE #define VPB_UNBUSIED VPB_SHARERS_WORD(0) #define PQ_NONE 255 #define PQ_INACTIVE 0 #define PQ_ACTIVE 1 #define PQ_LAUNDRY 2 #define PQ_COUNT 3 TAILQ_HEAD(pglist, vm_page); SLIST_HEAD(spglist, vm_page); struct vm_pagequeue { struct mtx pq_mutex; struct pglist pq_pl; int pq_cnt; int * const pq_vcnt; const char * const pq_name; } __aligned(CACHE_LINE_SIZE); struct vm_domain { struct vm_pagequeue vmd_pagequeues[PQ_COUNT]; u_int vmd_page_count; u_int vmd_free_count; long vmd_segs; /* bitmask of the segments */ boolean_t vmd_oom; int vmd_pass; /* local pagedaemon pass */ int vmd_oom_seq; int vmd_last_active_scan; struct vm_page vmd_laundry_marker; struct vm_page vmd_marker; /* marker for pagedaemon private use */ struct vm_page vmd_inacthead; /* marker for LRU-defeating insertions */ }; extern struct vm_domain vm_dom[MAXMEMDOM]; #define vm_pagequeue_assert_locked(pq) mtx_assert(&(pq)->pq_mutex, MA_OWNED) #define vm_pagequeue_lock(pq) mtx_lock(&(pq)->pq_mutex) #define vm_pagequeue_unlock(pq) mtx_unlock(&(pq)->pq_mutex) #ifdef _KERNEL static __inline void vm_pagequeue_cnt_add(struct vm_pagequeue *pq, int addend) { #ifdef notyet vm_pagequeue_assert_locked(pq); #endif pq->pq_cnt += addend; atomic_add_int(pq->pq_vcnt, addend); } #define vm_pagequeue_cnt_inc(pq) vm_pagequeue_cnt_add((pq), 1) #define vm_pagequeue_cnt_dec(pq) vm_pagequeue_cnt_add((pq), -1) #endif /* _KERNEL */ extern struct mtx_padalign vm_page_queue_free_mtx; extern struct mtx_padalign pa_lock[]; #if defined(__arm__) #define PDRSHIFT PDR_SHIFT #elif !defined(PDRSHIFT) #define PDRSHIFT 21 #endif #define pa_index(pa) ((pa) >> PDRSHIFT) #define PA_LOCKPTR(pa) ((struct mtx *)(&pa_lock[pa_index(pa) % PA_LOCK_COUNT])) #define PA_LOCKOBJPTR(pa) ((struct lock_object *)PA_LOCKPTR((pa))) #define PA_LOCK(pa) mtx_lock(PA_LOCKPTR(pa)) #define PA_TRYLOCK(pa) mtx_trylock(PA_LOCKPTR(pa)) #define PA_UNLOCK(pa) mtx_unlock(PA_LOCKPTR(pa)) #define PA_UNLOCK_COND(pa) \ do { \ if ((pa) != 0) { \ PA_UNLOCK((pa)); \ (pa) = 0; \ } \ } while (0) #define PA_LOCK_ASSERT(pa, a) mtx_assert(PA_LOCKPTR(pa), (a)) #ifdef KLD_MODULE #define vm_page_lock(m) vm_page_lock_KBI((m), LOCK_FILE, LOCK_LINE) #define vm_page_unlock(m) vm_page_unlock_KBI((m), LOCK_FILE, LOCK_LINE) #define vm_page_trylock(m) vm_page_trylock_KBI((m), LOCK_FILE, LOCK_LINE) #else /* !KLD_MODULE */ #define vm_page_lockptr(m) (PA_LOCKPTR(VM_PAGE_TO_PHYS((m)))) #define vm_page_lock(m) mtx_lock(vm_page_lockptr((m))) #define vm_page_unlock(m) mtx_unlock(vm_page_lockptr((m))) #define vm_page_trylock(m) mtx_trylock(vm_page_lockptr((m))) #endif #if defined(INVARIANTS) #define vm_page_assert_locked(m) \ vm_page_assert_locked_KBI((m), __FILE__, __LINE__) #define vm_page_lock_assert(m, a) \ vm_page_lock_assert_KBI((m), (a), __FILE__, __LINE__) #else #define vm_page_assert_locked(m) #define vm_page_lock_assert(m, a) #endif /* * The vm_page's aflags are updated using atomic operations. To set or clear * these flags, the functions vm_page_aflag_set() and vm_page_aflag_clear() * must be used. Neither these flags nor these functions are part of the KBI. * * PGA_REFERENCED may be cleared only if the page is locked. It is set by * both the MI and MD VM layers. However, kernel loadable modules should not * directly set this flag. They should call vm_page_reference() instead. * * PGA_WRITEABLE is set exclusively on managed pages by pmap_enter(). * When it does so, the object must be locked, or the page must be * exclusive busied. The MI VM layer must never access this flag * directly. Instead, it should call pmap_page_is_write_mapped(). * * PGA_EXECUTABLE may be set by pmap routines, and indicates that a page has * at least one executable mapping. It is not consumed by the MI VM layer. */ #define PGA_WRITEABLE 0x01 /* page may be mapped writeable */ #define PGA_REFERENCED 0x02 /* page has been referenced */ #define PGA_EXECUTABLE 0x04 /* page may be mapped executable */ /* * Page flags. If changed at any other time than page allocation or * freeing, the modification must be protected by the vm_page lock. */ #define PG_CACHED 0x0001 /* page is cached */ #define PG_FICTITIOUS 0x0004 /* physical page doesn't exist */ #define PG_ZERO 0x0008 /* page is zeroed */ #define PG_MARKER 0x0010 /* special queue marker page */ #define PG_NODUMP 0x0080 /* don't include this page in a dump */ #define PG_UNHOLDFREE 0x0100 /* delayed free of a held page */ /* * Misc constants. */ #define ACT_DECLINE 1 #define ACT_ADVANCE 3 #define ACT_INIT 5 #define ACT_MAX 64 #ifdef _KERNEL #include #include /* * Each pageable resident page falls into one of four lists: * * free * Available for allocation now. * * cache * Almost available for allocation. Still associated with * an object, but clean and immediately freeable. * * The following lists are LRU sorted: * * inactive * Low activity, candidates for reclamation. * This is the list of pages that should be * paged out next. * * active * Pages that are "active" i.e. they have been * recently referenced. * */ extern int vm_page_zero_count; extern vm_page_t vm_page_array; /* First resident page in table */ extern long vm_page_array_size; /* number of vm_page_t's */ extern long first_page; /* first physical page number */ #define VM_PAGE_TO_PHYS(entry) ((entry)->phys_addr) /* * PHYS_TO_VM_PAGE() returns the vm_page_t object that represents a memory * page to which the given physical address belongs. The correct vm_page_t * object is returned for addresses that are not page-aligned. */ vm_page_t PHYS_TO_VM_PAGE(vm_paddr_t pa); /* * Page allocation parameters for vm_page for the functions * vm_page_alloc(), vm_page_grab(), vm_page_alloc_contig() and * vm_page_alloc_freelist(). Some functions support only a subset * of the flags, and ignore others, see the flags legend. * * Bits 0 - 1 define class. * Bits 2 - 15 dedicated for flags. * Legend: * (a) - vm_page_alloc() supports the flag. * (c) - vm_page_alloc_contig() supports the flag. * (f) - vm_page_alloc_freelist() supports the flag. * (g) - vm_page_grab() supports the flag. * Bits above 15 define the count of additional pages that the caller * intends to allocate. */ #define VM_ALLOC_NORMAL 0 #define VM_ALLOC_INTERRUPT 1 #define VM_ALLOC_SYSTEM 2 #define VM_ALLOC_CLASS_MASK 3 #define VM_ALLOC_WIRED 0x0020 /* (acfg) Allocate non pageable page */ #define VM_ALLOC_ZERO 0x0040 /* (acfg) Try to obtain a zeroed page */ #define VM_ALLOC_NOOBJ 0x0100 /* (acg) No associated object */ #define VM_ALLOC_NOBUSY 0x0200 /* (acg) Do not busy the page */ #define VM_ALLOC_IFCACHED 0x0400 /* (ag) Fail if page is not cached */ #define VM_ALLOC_IFNOTCACHED 0x0800 /* (ag) Fail if page is cached */ #define VM_ALLOC_IGN_SBUSY 0x1000 /* (g) Ignore shared busy flag */ #define VM_ALLOC_NODUMP 0x2000 /* (ag) don't include in dump */ #define VM_ALLOC_SBUSY 0x4000 /* (acg) Shared busy the page */ #define VM_ALLOC_NOWAIT 0x8000 /* (g) Do not sleep, return NULL */ #define VM_ALLOC_COUNT_SHIFT 16 #define VM_ALLOC_COUNT(count) ((count) << VM_ALLOC_COUNT_SHIFT) #ifdef M_NOWAIT static inline int malloc2vm_flags(int malloc_flags) { int pflags; KASSERT((malloc_flags & M_USE_RESERVE) == 0 || (malloc_flags & M_NOWAIT) != 0, ("M_USE_RESERVE requires M_NOWAIT")); pflags = (malloc_flags & M_USE_RESERVE) != 0 ? VM_ALLOC_INTERRUPT : VM_ALLOC_SYSTEM; if ((malloc_flags & M_ZERO) != 0) pflags |= VM_ALLOC_ZERO; if ((malloc_flags & M_NODUMP) != 0) pflags |= VM_ALLOC_NODUMP; return (pflags); } #endif void vm_page_busy_downgrade(vm_page_t m); void vm_page_busy_sleep(vm_page_t m, const char *msg); void vm_page_flash(vm_page_t m); void vm_page_hold(vm_page_t mem); void vm_page_unhold(vm_page_t mem); void vm_page_free(vm_page_t m); void vm_page_free_zero(vm_page_t m); void vm_page_activate (vm_page_t); void vm_page_advise(vm_page_t m, int advice); vm_page_t vm_page_alloc (vm_object_t, vm_pindex_t, int); vm_page_t vm_page_alloc_contig(vm_object_t object, vm_pindex_t pindex, int req, u_long npages, vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary, vm_memattr_t memattr); vm_page_t vm_page_alloc_freelist(int, int); vm_page_t vm_page_grab (vm_object_t, vm_pindex_t, int); void vm_page_cache(vm_page_t); void vm_page_cache_free(vm_object_t, vm_pindex_t, vm_pindex_t); void vm_page_cache_transfer(vm_object_t, vm_pindex_t, vm_object_t); int vm_page_try_to_free (vm_page_t); void vm_page_deactivate (vm_page_t); void vm_page_deactivate_noreuse(vm_page_t); void vm_page_dequeue(vm_page_t m); void vm_page_dequeue_locked(vm_page_t m); vm_page_t vm_page_find_least(vm_object_t, vm_pindex_t); vm_page_t vm_page_getfake(vm_paddr_t paddr, vm_memattr_t memattr); void vm_page_initfake(vm_page_t m, vm_paddr_t paddr, vm_memattr_t memattr); int vm_page_insert (vm_page_t, vm_object_t, vm_pindex_t); boolean_t vm_page_is_cached(vm_object_t object, vm_pindex_t pindex); void vm_page_launder(vm_page_t m); vm_page_t vm_page_lookup (vm_object_t, vm_pindex_t); vm_page_t vm_page_next(vm_page_t m); int vm_page_pa_tryrelock(pmap_t, vm_paddr_t, vm_paddr_t *); struct vm_pagequeue *vm_page_pagequeue(vm_page_t m); vm_page_t vm_page_prev(vm_page_t m); boolean_t vm_page_ps_is_valid(vm_page_t m); void vm_page_putfake(vm_page_t m); void vm_page_readahead_finish(vm_page_t m); void vm_page_reference(vm_page_t m); void vm_page_remove (vm_page_t); int vm_page_rename (vm_page_t, vm_object_t, vm_pindex_t); vm_page_t vm_page_replace(vm_page_t mnew, vm_object_t object, vm_pindex_t pindex); void vm_page_requeue(vm_page_t m); void vm_page_requeue_locked(vm_page_t m); int vm_page_sbusied(vm_page_t m); void vm_page_set_valid_range(vm_page_t m, int base, int size); int vm_page_sleep_if_busy(vm_page_t m, const char *msg); vm_offset_t vm_page_startup(vm_offset_t vaddr); void vm_page_sunbusy(vm_page_t m); int vm_page_trysbusy(vm_page_t m); void vm_page_unhold_pages(vm_page_t *ma, int count); boolean_t vm_page_unwire(vm_page_t m, uint8_t queue); void vm_page_updatefake(vm_page_t m, vm_paddr_t paddr, vm_memattr_t memattr); void vm_page_wire (vm_page_t); void vm_page_xunbusy_hard(vm_page_t m); void vm_page_set_validclean (vm_page_t, int, int); void vm_page_clear_dirty (vm_page_t, int, int); void vm_page_set_invalid (vm_page_t, int, int); int vm_page_is_valid (vm_page_t, int, int); void vm_page_test_dirty (vm_page_t); vm_page_bits_t vm_page_bits(int base, int size); void vm_page_zero_invalid(vm_page_t m, boolean_t setvalid); void vm_page_free_toq(vm_page_t m); void vm_page_zero_idle_wakeup(void); void vm_page_dirty_KBI(vm_page_t m); void vm_page_lock_KBI(vm_page_t m, const char *file, int line); void vm_page_unlock_KBI(vm_page_t m, const char *file, int line); int vm_page_trylock_KBI(vm_page_t m, const char *file, int line); #if defined(INVARIANTS) || defined(INVARIANT_SUPPORT) void vm_page_assert_locked_KBI(vm_page_t m, const char *file, int line); void vm_page_lock_assert_KBI(vm_page_t m, int a, const char *file, int line); #endif #define vm_page_assert_sbusied(m) \ KASSERT(vm_page_sbusied(m), \ ("vm_page_assert_sbusied: page %p not shared busy @ %s:%d", \ (m), __FILE__, __LINE__)) #define vm_page_assert_unbusied(m) \ KASSERT(!vm_page_busied(m), \ ("vm_page_assert_unbusied: page %p busy @ %s:%d", \ (m), __FILE__, __LINE__)) #define vm_page_assert_xbusied(m) \ KASSERT(vm_page_xbusied(m), \ ("vm_page_assert_xbusied: page %p not exclusive busy @ %s:%d", \ (m), __FILE__, __LINE__)) #define vm_page_busied(m) \ ((m)->busy_lock != VPB_UNBUSIED) #define vm_page_sbusy(m) do { \ if (!vm_page_trysbusy(m)) \ panic("%s: page %p failed shared busying", __func__, \ (m)); \ } while (0) #define vm_page_tryxbusy(m) \ (atomic_cmpset_acq_int(&(m)->busy_lock, VPB_UNBUSIED, \ VPB_SINGLE_EXCLUSIVER)) #define vm_page_xbusied(m) \ (((m)->busy_lock & VPB_SINGLE_EXCLUSIVER) != 0) #define vm_page_xbusy(m) do { \ if (!vm_page_tryxbusy(m)) \ panic("%s: page %p failed exclusive busying", __func__, \ (m)); \ } while (0) #define vm_page_xunbusy(m) do { \ if (!atomic_cmpset_rel_int(&(m)->busy_lock, \ VPB_SINGLE_EXCLUSIVER, VPB_UNBUSIED)) \ vm_page_xunbusy_hard(m); \ } while (0) #ifdef INVARIANTS void vm_page_object_lock_assert(vm_page_t m); #define VM_PAGE_OBJECT_LOCK_ASSERT(m) vm_page_object_lock_assert(m) void vm_page_assert_pga_writeable(vm_page_t m, uint8_t bits); #define VM_PAGE_ASSERT_PGA_WRITEABLE(m, bits) \ vm_page_assert_pga_writeable(m, bits) #else #define VM_PAGE_OBJECT_LOCK_ASSERT(m) (void)0 #define VM_PAGE_ASSERT_PGA_WRITEABLE(m, bits) (void)0 #endif /* * We want to use atomic updates for the aflags field, which is 8 bits wide. * However, not all architectures support atomic operations on 8-bit * destinations. In order that we can easily use a 32-bit operation, we * require that the aflags field be 32-bit aligned. */ CTASSERT(offsetof(struct vm_page, aflags) % sizeof(uint32_t) == 0); /* * Clear the given bits in the specified page. */ static inline void vm_page_aflag_clear(vm_page_t m, uint8_t bits) { uint32_t *addr, val; /* * The PGA_REFERENCED flag can only be cleared if the page is locked. */ if ((bits & PGA_REFERENCED) != 0) vm_page_assert_locked(m); /* * Access the whole 32-bit word containing the aflags field with an * atomic update. Parallel non-atomic updates to the other fields * within this word are handled properly by the atomic update. */ addr = (void *)&m->aflags; KASSERT(((uintptr_t)addr & (sizeof(uint32_t) - 1)) == 0, ("vm_page_aflag_clear: aflags is misaligned")); val = bits; #if BYTE_ORDER == BIG_ENDIAN val <<= 24; #endif atomic_clear_32(addr, val); } /* * Set the given bits in the specified page. */ static inline void vm_page_aflag_set(vm_page_t m, uint8_t bits) { uint32_t *addr, val; VM_PAGE_ASSERT_PGA_WRITEABLE(m, bits); /* * Access the whole 32-bit word containing the aflags field with an * atomic update. Parallel non-atomic updates to the other fields * within this word are handled properly by the atomic update. */ addr = (void *)&m->aflags; KASSERT(((uintptr_t)addr & (sizeof(uint32_t) - 1)) == 0, ("vm_page_aflag_set: aflags is misaligned")); val = bits; #if BYTE_ORDER == BIG_ENDIAN val <<= 24; #endif atomic_set_32(addr, val); } /* * vm_page_dirty: * * Set all bits in the page's dirty field. * * The object containing the specified page must be locked if the * call is made from the machine-independent layer. * * See vm_page_clear_dirty_mask(). */ static __inline void vm_page_dirty(vm_page_t m) { /* Use vm_page_dirty_KBI() under INVARIANTS to save memory. */ #if defined(KLD_MODULE) || defined(INVARIANTS) vm_page_dirty_KBI(m); #else m->dirty = VM_PAGE_BITS_ALL; #endif } /* * vm_page_remque: * * If the given page is in a page queue, then remove it from that page * queue. * * The page must be locked. */ static inline void vm_page_remque(vm_page_t m) { if (m->queue != PQ_NONE) vm_page_dequeue(m); } /* * vm_page_undirty: * * Set page to not be dirty. Note: does not clear pmap modify bits */ static __inline void vm_page_undirty(vm_page_t m) { VM_PAGE_OBJECT_LOCK_ASSERT(m); m->dirty = 0; } +static inline void +vm_page_replace_checked(vm_page_t mnew, vm_object_t object, vm_pindex_t pindex, + vm_page_t mold) +{ + vm_page_t mret; + + mret = vm_page_replace(mnew, object, pindex); + KASSERT(mret == mold, + ("invalid page replacement, mold=%p, mret=%p", mold, mret)); + + /* Unused if !INVARIANTS. */ + (void)mold; + (void)mret; +} + #endif /* _KERNEL */ #endif /* !_VM_PAGE_ */ Index: user/alc/PQ_LAUNDRY/sys =================================================================== --- user/alc/PQ_LAUNDRY/sys (revision 292448) +++ user/alc/PQ_LAUNDRY/sys (revision 292449) Property changes on: user/alc/PQ_LAUNDRY/sys ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/sys:r292390-292448 Index: user/alc/PQ_LAUNDRY/usr.bin/calendar/calendars/calendar.freebsd =================================================================== --- user/alc/PQ_LAUNDRY/usr.bin/calendar/calendars/calendar.freebsd (revision 292448) +++ user/alc/PQ_LAUNDRY/usr.bin/calendar/calendars/calendar.freebsd (revision 292449) @@ -1,388 +1,389 @@ /* * FreeBSD * * $FreeBSD$ */ #ifndef _calendar_freebsd_ #define _calendar_freebsd_ 01/01 Dimitry Andric born in Utrecht, the Netherlands, 1969 01/01 Alexander Langer born in Duesseldorf, Nordrhein-Westfalen, Germany, 1981 01/02 Ion-Mihai "IOnut" Tetcu born in Bucharest, Romania, 1980 01/02 Patrick Li born in Beijing, People's Republic of China, 1985 01/03 Tetsurou Okazaki born in Mobara, Chiba, Japan, 1972 01/04 Hiroyuki Hanai born in Kagawa pre., Japan, 1969 01/06 Philippe Audeoud born in Bretigny-Sur-Orge, France, 1980 01/08 Michael L. Hostbaek born in Copenhagen, Denmark, 1977 01/10 Jean-Yves Lefort born in Charleroi, Belgium, 1980 01/12 Yen-Ming Lee born in Taipei, Taiwan, Republic of China, 1977 01/12 Ying-Chieh Liao born in Taipei, Taiwan, Republic of China, 1979 01/14 Yi-Jheng Lin born in Taichung, Taiwan, Republic of China, 1985 01/16 Ariff Abdullah born in Kuala Lumpur, Malaysia, 1978 01/16 Dmitry Sivachenko born in Moscow, USSR, 1978 01/16 Vanilla I. Shu born in Taipei, Taiwan, Republic of China, 1978 01/17 Raphael Kubo da Costa born in Sao Paulo, Sao Paulo, Brazil, 1989 01/18 Dejan Lesjak born in Ljubljana, Slovenia, Yugoslavia, 1977 01/19 Marshall Kirk McKusick born in Wilmington, Delaware, United States, 1954 01/19 Ruslan Ermilov born in Simferopol, USSR, 1974 01/19 Marcelo S. Araujo born in Joinville, Santa Catarina, Brazil, 1981 01/20 Poul-Henning Kamp born in Korsoer, Denmark, 1966 01/22 Johann Visagie born in Cape Town, South Africa, 1970 01/23 Hideyuki KURASHINA born in Niigata, Japan, 1982 01/24 Fabien Thomas born in Avignon, France, 1971 01/24 Matteo Riondato born in Padova, Italy, 1986 01/25 Bernd Walter born in Moers, Nordrhein-Westfalen, Germany, 1974 01/26 Andrew Gallatin born in Buffalo, New York, United States, 1970 01/27 Nick Sayer born in San Diego, California, United States, 1968 01/27 Jacques Anthony Vidrine born in Baton Rouge, Louisiana, United States, 1971 01/27 Garrett Cooper born in Seattle, Washington, United States, 1984 01/31 Hidetoshi Shimokawa born in Yokohama, Kanagawa, Japan, 1970 02/01 Doug Rabson born in London, England, 1966 02/01 Nicola Vitale born in Busto Arsizio, Varese, Italy, 1976 02/01 Paul Saab born in Champaign-Urbana, Illinois, United States, 1978 02/01 Martin Wilke born in Ludwigsfelde, Brandenburg, Germany, 1980 02/01 Christian Brueffer born in Gronau, Nordrhein-Westfalen, Germany, 1982 02/01 Steven Kreuzer born in Oceanside, New York, United States, 1982 02/01 Juli Mallett born in Washington, Pennsylvania, United States, 1985 02/02 Diomidis D. Spinellis born in Athens, Greece, 1967 02/02 Michael W Lucas born in Detroit, Michigan, United States, 1967 02/02 Dmitry Chagin born in Stalingrad, USSR, 1976 02/02 Yoichi Nakayama born in Tsu, Mie, Japan, 1976 02/03 Jason Helfman born in Royal Oak, Michigan, United States, 1972 02/04 Eitan Adler born in West Hempstead, New York, United States, 1991 02/05 Frank Laszlo born in Howell, Michigan, United States, 1983 02/06 Julien Charbon born in Saint Etienne, Loire, France, 1978 02/10 David Greenman born in Portland, Oregon, United States, 1968 02/10 Paul Richards born in Ammanford, Carmarthenshire, United Kingdom, 1968 02/10 Simon Barner born in Rosenheim, Bayern, Germany, 1980 02/10 Jason E. Hale born in Pittsburgh, Pennsylvania, Unites States, 1982 02/13 Jesper Skriver born in Aarhus, Denmark, 1975 02/13 Steve Wills born in Lynchburg, Virginia, United States, 1975 02/13 Andrey Slusar born in Odessa, USSR, 1979 02/13 David W. Chapman Jr. born in Bethel, Connecticut, United States, 1981 02/14 Manolis Kiagias born in Chania, Greece, 1970 02/14 Erwin Lansing born in 's-Hertogenbosch, the Netherlands, 1975 02/14 Martin Blapp born in Olten, Switzerland, 1976 02/15 Hiren Panchasara born in Ahmedabad, Gujarat, India, 1984 02/19 Murray Stokely born in Jacksonville, Florida, United States, 1979 02/20 Anders Nordby born in Oslo, Norway, 1976 02/21 Alexey Zelkin born in Simferopol, Ukraine, 1978 02/22 Brooks Davis born in Longview, Washington, United States, 1976 02/22 Jake Burkholder born in Maynooth, Ontario, Canada, 1979 02/23 Peter Wemm born in Perth, Western Australia, Australia, 1971 02/23 Mathieu Arnold born in Champigny sur Marne, Val de Marne, France, 1978 02/24 Johan Karlsson born in Mariannelund, Sweden, 1974 02/24 Colin Percival born in Burnaby, Canada, 1981 02/26 Pietro Cerutti born in Faido, Switzerland, 1984 02/28 Daichi GOTO born in Shimizu Suntou, Shizuoka, Japan, 1980 02/28 Ruslan Makhmatkhanov born in Rostov-on-Don, USSR, 1984 03/01 Hye-Shik Chang born in Daejeon, Republic of Korea, 1980 03/02 Cy Schubert born in Edmonton, Alberta, Canada, 1956 03/03 Sergey Matveychuk born in Moscow, Russian Federation, 1973 03/03 Doug White born in Eugene, Oregon, United States, 1977 03/03 Gordon Tetlow born in Reno, Nevada, United States, 1978 03/04 Oleksandr Tymoshenko born in Chernihiv, Ukraine, 1980 03/05 Baptiste Daroussin born in Beauvais, France, 1980 03/05 Philip Paeps born in Leuven, Belgium, 1983 03/05 Ulf Lilleengen born in Hamar, Norway, 1985 03/06 Christopher Piazza born in Kamloops, British Columbia, Canada, 1981 03/07 Michael P. Pritchard born in Los Angeles, California, United States, 1964 03/07 Giorgos Keramidas born in Athens, Greece, 1976 03/10 Andreas Klemm born in Duesseldorf, Nordrhein-Westfalen, Germany, 1963 03/11 Soeren Straarup born in Andst, Denmark, 1978 03/12 Greg Lewis born in Adelaide, South Australia, Australia, 1969 03/13 Alexander Leidinger born in Neunkirchen, Saarland, Germany, 1976 03/13 Will Andrews born in Pontiac, Michigan, United States, 1982 03/14 Bernhard Froehlich born in Graz, Styria, Austria, 1985 03/15 Paolo Pisati born in Lodi, Italy, 1977 03/15 Brian Fundakowski Feldman born in Alexandria, Virginia, United States, 1983 03/17 Michael Smith born in Bankstown, New South Wales, Australia, 1971 03/17 Alexander Motin born in Simferopol, Ukraine, 1979 03/18 Koop Mast born in Dokkum, the Netherlands, 1981 03/19 Mikhail Teterin born in Kyiv, Ukraine, 1972 03/20 Joseph S. Atkinson born in Batesville, Arkansas, United States, 1977 03/20 Henrik Brix Andersen born in Aarhus, Denmark, 1978 03/20 MANTANI Nobutaka born in Hiroshima, Japan, 1978 03/20 Cameron Grant died in Hemel Hempstead, United Kingdom, 2005 03/22 Brad Davis born in Farmington, New Mexico, United States, 1983 03/23 Daniel C. Sobral born in Brasilia, Distrito Federal, Brazil, 1971 03/23 Benno Rice born in Adelaide, South Australia, Australia, 1977 03/24 Marcel Moolenaar born in Hilversum, the Netherlands, 1968 03/24 Emanuel Haupt born in Zurich, Switzerland, 1979 03/25 Andrew R. Reiter born in Springfield, Massachusetts, United States, 1980 03/27 Josef El-Rayes born in Linz, Austria, 1982 03/28 Sean C. Farley born in Indianapolis, Indiana, United States, 1970 03/29 Thierry Thomas born in Luxeuil les Bains, France, 1961 03/30 Po-Chuan Hsieh born in Taipei, Taiwan, Republic of China, 1978 03/31 First quarter status reports are due on 04/15 04/01 Matthew Jacob born in San Francisco, California, United States, 1958 04/01 Bill Fenner born in Bellefonte, Pennsylvania, United States, 1971 04/01 Peter Edwards born in Dublin, Ireland, 1973 04/03 Hellmuth Michaelis born in Kiel, Schleswig-Holstein, Germany, 1958 04/03 Tong Liu born in Beijing, People's Republic of China, 1981 04/03 Gabor Pali born in Kunhegyes, Hungary, 1982 04/04 Jason Unovitch born in Scranton, Pennsylvania, United States, 1986 04/05 Stacey Son born in Burley, Idaho, United States, 1967 04/06 Peter Jeremy born in Sydney, New South Wales, Australia, 1961 04/07 Edward Tomasz Napierala born in Wolsztyn, Poland, 1981 04/08 Jordan K. Hubbard born in Honolulu, Hawaii, United States, 1963 04/09 Ceri Davies born in Haverfordwest, Pembrokeshire, United Kingdom, 1976 04/11 Bruce A. Mah born in Fresno, California, United States, 1969 04/12 Patrick Gardella born in Columbus, Ohio, United States, 1967 04/12 Ed Schouten born in Oss, the Netherlands, 1986 04/13 Oliver Braun born in Nuremberg, Bavaria, Germany, 1972 04/14 Crist J. Clark born in Milwaukee, Wisconsin, United States, 1970 04/14 Glen J. Barber born in Wilkes-Barre, Pennsylvania, United States, 1981 04/15 David Malone born in Dublin, Ireland, 1973 04/17 Alexey Degtyarev born in Ahtubinsk, Russian Federation, 1984 04/17 Dryice Liu born in Jinan, Shandong, China, 1975 04/22 Joerg Wunsch born in Dresden, Sachsen, Germany, 1962 04/22 Jun Kuriyama born in Matsue, Shimane, Japan, 1973 04/22 Jakub Klama born in Blachownia, Silesia, Poland, 1989 04/26 Rene Ladan born in Geldrop, the Netherlands, 1980 04/29 Adam Weinberger born in Berkeley, California, United States, 1980 04/29 Eric Anholt born in Portland, Oregon, United States, 1983 05/01 Randall Stewart born in Spokane, Washington, United States, 1959 05/02 Wojciech A. Koszek born in Czestochowa, Poland, 1987 05/03 Brian Dean born in Elkins, West Virginia, United States, 1966 05/03 Patrick Kelsey born in Freehold, New Jersey, United States, 1976 05/03 Robert Nicholas Maxwell Watson born in Harrow, Middlesex, United Kingdom, 1977 05/04 Denis Peplin born in Nizhniy Novgorod, Russian Federation, 1977 05/08 Kirill Ponomarew born in Volgograd, Russian Federation, 1977 05/08 Sean Kelly born in Walnut Creek, California, United States, 1982 05/09 Daniel Eischen born in Syracuse, New York, United States, 1963 05/09 Aaron Dalton born in Boise, Idaho, United States, 1973 05/09 Jase Thew born in Abergavenny, Gwent, United Kingdom, 1974 05/10 Markus Brueffer born in Gronau, Nordrhein-Westfalen, Germany, 1977 05/11 Kurt Lidl born in Rockville, Maryland, United States, 1968 05/11 Jesus Rodriguez born in Barcelona, Spain, 1972 05/11 Roman Kurakin born in Moscow, USSR, 1979 05/11 Ulrich Spoerlein born in Schesslitz, Bayern, Germany, 1981 05/13 Pete Fritchman born in Lansdale, Pennsylvania, United States, 1983 05/14 Tatsumi Hosokawa born in Tokyo, Japan, 1968 05/14 Shigeyuku Fukushima born in Osaka, Japan, 1974 05/14 Bruce Cran born in Cambridge, United Kingdom, 1981 05/16 Johann Kois born in Wolfsberg, Austria, 1975 05/16 Marcus Alves Grando born in Florianopolis, Santa Catarina, Brazil, 1979 05/17 Thomas Abthorpe born in Port Arthur, Ontario, Canada, 1968 05/19 Philippe Charnier born in Fontainebleau, France, 1966 05/19 Ian Dowse born in Dublin, Ireland, 1975 05/19 Sofian Brabez born in Toulouse, France, 1984 05/20 Dan Moschuk died in Burlington, Ontario, Canada, 2010 05/21 Kris Kennaway born in Winnipeg, Manitoba, Canada, 1978 05/22 Clive Tong-I Lin born in Changhua, Taiwan, Republic of China, 1978 05/22 Michael Bushkov born in Rostov-on-Don, Russian Federation, 1985 05/22 Rui Paulo born in Evora, Portugal, 1986 05/22 David Naylor born in Johannesburg, South Africa, 1988 05/23 Munechika Sumikawa born in Osaka, Osaka, Japan, 1972 05/24 Duncan McLennan Barclay born in London, Middlesex, United Kingdom, 1970 05/24 Oliver Lehmann born in Karlsburg, Germany, 1981 05/25 Tom Rhodes born in Ellwood City, Pennsylvania, United States, 1981 05/25 Roman Divacky born in Brno, Czech Republic, 1983 05/26 Jim Pirzyk born in Chicago, Illinois, United States, 1968 05/26 Florian Smeets born in Schwerte, Nordrhein-Westfalen, Germany, 1982 05/27 Ollivier Robert born in Paris, France, 1967 05/29 Wilko Bulte born in Arnhem, the Netherlands, 1965 05/29 Seigo Tanimura born in Kitakyushu, Fukuoka, Japan, 1976 05/31 Ville Skytta born in Helsinki, Finland, 1974 06/02 Jean-Marc Zucconi born in Pontarlier, France, 1954 06/02 Alexander Botero-Lowry born in Austin, Texas, United States, 1986 06/03 CHOI Junho born in Seoul, Korea, 1974 06/03 Wesley Shields born in Binghamton, New York, United States, 1981 06/04 Julian Elischer born in Perth, Australia, 1959 06/04 Justin Gibbs born in San Pedro, California, United States, 1973 06/04 Jason Evans born in Greeley, Colorado, United States, 1973 06/04 Thomas Moestl born in Braunschweig, Niedersachsen, Germany, 1980 06/04 Devin Teske born in Arcadia, California, United States, 1982 06/04 Zack Kirsch born in Memphis, Tennessee, United States, 1982 06/04 Johannes Jost Meixner born in Wiesbaden, Germany, 1987 06/06 Sergei Kolobov born in Karpinsk, Russian Federation, 1972 06/06 Alan Eldridge died in Denver, Colorado, 2003 06/07 Jimmy Olgeni born in Milano, Italy, 1976 06/07 Benjamin Close born in Adelaide, Australia, 1978 06/11 Alonso Cardenas Marquez born in Arequipa, Peru, 1979 06/14 Josh Paetzel born in Minneapolis, Minnesota, United States, 1973 06/17 Tilman Linneweh born in Weinheim, Baden-Wuerttemberg, Germany, 1978 06/18 Li-Wen Hsu born in Taipei, Taiwan, Republic of China, 1984 06/18 Roman Bogorodskiy born in Saratov, Russian Federation, 1986 06/19 Charlie Root born in Portland, Oregon, United States, 1993 06/21 Ganbold Tsagaankhuu born in Ulaanbaatar, Mongolia, 1971 06/21 Niels Heinen born in Markelo, the Netherlands, 1978 06/22 Andreas Tobler born in Heiden, Switzerland, 1968 06/24 Chris Faulhaber born in Springfield, Illinois, United States, 1971 06/26 Brian Somers born in Dundrum, Dublin, Ireland, 1967 06/28 Mark Santcroos born in Rotterdam, the Netherlands, 1979 06/28 Xin Li born in Beijing, People's Republic of China, 1982 06/29 Wilfredo Sanchez Vega born in Majaguez, Puerto Rico, United States, 1972 06/29 Daniel Harris born in Lubbock, Texas, United States, 1985 06/29 Andrew Pantyukhin born in Moscow, Russian Federation, 1985 06/30 Guido van Rooij born in Best, Noord-Brabant, the Netherlands, 1965 06/30 Second quarter status reports are due on 07/15 07/01 Matthew Dillon born in San Francisco, California, United States, 1966 07/02 Mark Christopher Ovens born in Preston, Lancashire, United Kingdom, 1958 07/02 Vasil Venelinov Dimov born in Shumen, Bulgaria, 1982 07/04 Motoyuki Konno born in Musashino, Tokyo, Japan, 1969 07/04 Florent Thoumie born in Montmorency, Val d'Oise, France, 1982 07/05 Sergey Kandaurov born in Gubkin, Russian Federation, 1985 07/07 Andrew Thompson born in Lower Hutt, Wellington, New Zealand, 1979 07/07 Maxime Henrion born in Metz, France, 1981 07/07 George Reid born in Frimley, Hampshire, United Kingdom, 1983 07/10 Jung-uk Kim born in Seoul, Korea, 1971 07/10 Justin Seger born in Harvard, Massachusetts, United States, 1981 07/10 David Schultz born in Oakland, California, United States, 1982 07/11 Jesus R. Camou born in Hermosillo, Sonora, Mexico, 1983 07/15 Gary Jennejohn born in Rochester, New York, United States, 1950 07/16 Suleiman Souhlal born in Roma, Italy, 1983 07/16 Davide Italiano born in Milazzo, Italy, 1989 07/17 Michael Chin-Yuan Wu born in Taipei, Taiwan, Republic of China, 1980 07/19 Masafumi NAKANE born in Okazaki, Aichi, Japan, 1972 07/19 Simon L. Nielsen born in Copenhagen, Denmark, 1980 07/19 Gleb Smirnoff born in Kharkov, USSR, 1981 07/20 Andrey V. Elsukov born in Kotelnich, Russian Federation, 1981 07/22 James Housley born in Chicago, Illinois, United States, 1965 07/22 Jens Schweikhardt born in Waiblingen, Baden-Wuerttemberg, Germany, 1967 07/22 Lukas Ertl born in Weissenbach/Enns, Steiermark, Austria, 1976 07/23 Sergey A. Osokin born in Krasnogorsky, Stepnogorsk, Akmolinskaya region, Kazakhstan, 1972 07/23 Andrey Zonov born in Kirov, Russian Federation, 1985 07/24 Alexander Nedotsukov born in Ulyanovsk, Russian Federation, 1974 07/24 Alberto Villa born in Vercelli, Italy, 1987 07/27 Andriy Gapon born in Kyrykivka, Sumy region, Ukraine, 1976 07/28 Jim Mock born in Bethlehem, Pennsylvania, United States, 1974 07/28 Tom Hukins born in Manchester, United Kingdom, 1976 07/29 Dirk Meyer born in Kassel, Hessen, Germany, 1965 07/29 Felippe M. Motta born in Maceio, Alagoas, Brazil, 1988 08/02 Gabor Kovesdan born in Budapest, Hungary, 1987 08/03 Peter Holm born in Copenhagen, Denmark, 1955 08/05 Alfred Perlstein born in Brooklyn, New York, United States, 1978 08/06 Anton Berezin born in Dnepropetrovsk, Ukraine, 1970 08/06 John-Mark Gurney born in Detroit, Michigan, United States, 1978 08/06 Damjan Marion born in Rijeka, Croatia, 1978 08/07 Jonathan Mini born in San Mateo, California, United States, 1979 08/08 Mikolaj Golub born in Kharkov, USSR, 1977 +08/08 Juergen Lock died in Bremen, Germany, 2015 08/09 Stefan Farfeleder died in Wien, Austria, 2015 08/10 Julio Merino born in Barcelona, Spain, 1984 08/10 Peter Pentchev born in Sofia, Bulgaria, 1977 08/12 Joe Marcus Clarke born in Lakeland, Florida, United States, 1976 08/12 Max Brazhnikov born in Leningradskaya, Russian Federation, 1979 08/14 Stefan Esser born in Cologne, Nordrhein-Westfalen, Germany, 1961 08/17 Olivier Houchard born in Nancy, France, 1980 08/19 Chin-San Huang born in Yi-Lan, Taiwan, Republic of China, 1979 08/19 Pav Lucistnik born in Kutna Hora, Czech Republic, 1980 08/20 Michael Heffner born in Cleona, Pennsylvania, United States, 1981 08/24 Mark Linimon born in Houston, Texas, United States, 1955 08/24 Alexander Botero-Lowry died in San Francisco, California, United States, 2012 08/25 Beech Rintoul born in Oakland, California, United States, 1952 08/25 Jean Milanez Melo born in Divinopolis, Minas Gerais, Brazil, 1982 08/26 Dima Ruban born in Nalchik, USSR, 1970 08/26 Marc Fonvieille born in Avignon, France, 1972 08/26 Herve Quiroz born in Aix-en-Provence, France, 1977 08/27 Andrey Chernov born in Moscow, USSR, 1966 08/27 Tony Finch born in London, United Kingdom, 1974 08/27 Michael Johnson born in Morganton, North Carolina, United States, 1980 08/28 Norikatsu Shigemura born in Fujisawa, Kanagawa, Japan, 1974 08/29 Thomas Gellekum born in Moenchengladbach, Nordrhein-Westfalen, Germany, 1967 08/29 Max Laier born in Karlsruhe, Germany, 1981 09/01 Pyun YongHyeon born in Kimcheon, Korea, 1968 09/01 William Grzybowski born in Parana, Brazil, 1988 09/03 Max Khon born in Novosibirsk, USSR, 1976 09/03 Allan Jude born in Hamilton, Ontario, Canada, 1984 09/03 Cheng-Lung Sung born in Taipei, Taiwan, Republic of China, 1977 09/05 Mark Robert Vaughan Murray born in Harare, Mashonaland, Zimbabwe, 1961 09/05 Adrian Harold Chadd born in Perth, Western Australia, Australia, 1979 09/05 Rodrigo Osorio born in Montevideo, Uruguay, 1975 09/07 Tim Bishop born in Cornwall, United Kingdom, 1978 09/07 Chris Rees born in Kettering, United Kingdom, 1987 09/08 Boris Samorodov born in Krasnodar, Russian Federation, 1963 09/09 Yoshio Mita born in Hiroshima, Japan, 1972 09/10 Wesley R. Peters born in Hartford, Alabama, United States, 1961 09/12 Weongyo Jeong born in Haman, Korea, 1980 09/12 Benedict Christopher Reuschling born in Darmstadt, Germany, 1981 09/12 William C. Fumerola II born in Detroit, Michigan, United States, 1981 09/14 Matthew Seaman born in Bristol, United Kingdom, 1965 09/15 Aleksandr Rybalko born in Odessa, Ukraine, 1977 09/15 Dima Panov born in Khabarovsk, Russian Federation, 1978 09/17 Maxim Bolotin born in Rostov-on-Don, Russian Federation, 1976 09/18 Matthew Fleming born in Cleveland, Ohio, United States, 1975 09/20 Kevin Lo born in Taipei, Taiwan, Republic of China, 1972 09/21 Gleb Kurtsou born in Minsk, Belarus, 1984 09/22 Bryan Drewery born in San Diego, California, United States, 1984 09/27 Neil Blakey-Milner born in Port Elizabeth, South Africa, 1978 09/27 Renato Botelho born in Araras, Sao Paulo, Brazil, 1979 09/28 Greg Lehey born in Melbourne, Victoria, Australia, 1948 09/28 Alex Dupre born in Milano, Italy, 1980 09/29 Matthew Hunt born in Johnstown, Pennsylvania, United States, 1976 09/30 Mark Felder born in Prairie du Chien, Wisconsin, United States, 1985 09/30 Hiten M. Pandya born in Dar-es-Salaam, Tanzania, East Africa, 1986 09/30 Third quarter status reports are due on 10/15 10/02 Beat Gaetzi born in Zurich, Switzerland, 1980 10/02 Grzegorz Blach born in Starachowice, Poland, 1985 10/05 Hiroki Sato born in Yamagata, Japan, 1977 10/05 Chris Costello born in Houston, Texas, United States, 1985 10/09 Stefan Walter born in Werne, Nordrhein-Westfalen, Germany, 1978 10/12 Pawel Jakub Dawidek born in Radzyn Podlaski, Poland, 1980 10/15 Maxim Konovalov born in Khabarovsk, USSR, 1973 10/16 Remko Lodder born in Rotterdam, the Netherlands, 1983 10/17 Maho NAKATA born in Osaka, Japan, 1974 10/18 Sheldon Hearn born in Cape Town, Western Cape, South Africa, 1974 10/19 Nicholas Souchu born in Suresnes, Hauts-de-Seine, France, 1972 10/19 Nick Barkas born in Longview, Washington, United States, 1981 10/20 Joel Dahl born in Bitterna, Skaraborg, Sweden, 1983 10/20 Dmitry Marakasov born in Moscow, Russian Federation, 1984 10/21 Ben Smithurst born in Sheffield, South Yorkshire, United Kingdom, 1981 10/22 Jean-Sebastien Pedron born in Redon, Ille-et-Vilaine, France, 1980 10/23 Mario Sergio Fujikawa Ferreira born in Brasilia, Distrito Federal, Brazil, 1976 10/25 Eric Melville born in Los Gatos, California, United States, 1980 10/25 Julien Laffaye born in Toulouse, France, 1988 10/25 Ashish SHUKLA born in Kanpur, India, 1985 10/26 Philip M. Gollucci born in Silver Spring, Maryland, United States, 1979 10/27 Takanori Watanabe born in Numazu, Shizuoka, Japan, 1972 11/05 M. Warner Losh born in Kansas City, Kansas, United States, 1966 11/09 Coleman Kane born in Cincinnati, Ohio, United States, 1980 11/09 Antoine Brodin born in Bagnolet, France, 1981 11/10 Gregory Neil Shapiro born in Providence, Rhode Island, United States, 1970 11/11 Danilo E. Gondolfo born in Lobato, Parana, Brazil, 1987 11/13 John Baldwin born in Stuart, Virginia, United States, 1977 11/14 Jeremie Le Hen born in Nancy, France, 1980 11/15 Lars Engels born in Hilden, Nordrhein-Westfalen, Germany, 1980 11/15 Tijl Coosemans born in Duffel, Belgium, 1983 11/16 Jose Maria Alcaide Salinas born in Madrid, Spain, 1962 11/17 Ralf S. Engelschall born in Dachau, Bavaria, Germany, 1972 11/18 Thomas Quinot born in Paris, France, 1977 11/19 Konstantin Belousov born in Kiev, USSR, 1972 11/20 Dmitry Morozovsky born in Moscow, USSR, 1968 11/20 Gavin Atkinson born in Middlesbrough, United Kingdom, 1979 11/21 Mark Johnston born in Toronto, Ontario, Canada, 1989 11/22 Frederic Culot born in Saint-Germain-En-Laye, France, 1976 11/23 Josef Lawrence Karthauser born in Pembury, Kent, United Kingdom, 1972 11/24 Andrey Zakhvatov born in Chelyabinsk, Russian Federation, 1974 11/24 Daniel Gerzo born in Bratislava, Slovakia, 1986 11/28 Nik Clayton born in Peterborough, United Kingdom, 1973 11/28 Stanislav Sedov born in Chelyabinsk, USSR, 1985 12/01 Hajimu Umemoto born in Nara, Japan, 1961 12/01 Alexey Dokuchaev born in Magadan, USSR, 1980 12/02 Ermal Luçi born in Tirane, Albania, 1980 12/03 Diane Bruce born in Ottawa, Ontario, Canada, 1952 12/04 Mariusz Zaborski born in Skierniewice, Poland, 1990 12/05 Ivan Voras born in Slavonski Brod, Croatia, 1981 12/06 Stefan Farfeleder born in Wien, Austria, 1980 12/11 Ganael Laplanche born in Reims, France, 1980 12/15 James FitzGibbon born in Amersham, Buckinghamshire, United Kingdom, 1974 12/15 Timur I. Bakeyev born in Kazan, Republic of Tatarstan, USSR, 1974 12/18 Chris Timmons born in Ellensburg, Washington, United States, 1964 12/18 Dag-Erling Smorgrav born in Brussels, Belgium, 1977 12/18 Semen Ustimenko born in Novosibirsk, Russian Federation, 1979 12/19 Stephen Hurd born in Estevan, Saskatchewan, Canada, 1975 12/21 Rong-En Fan born in Taipei, Taiwan, Republic of China, 1982 12/22 Maxim Sobolev born in Dnepropetrovsk, Ukraine, 1976 12/23 Sean Chittenden born in Seattle, Washington, United States, 1979 12/23 Alejandro Pulver born in Buenos Aires, Argentina, 1989 12/24 Guido Falsi born in Firenze, Italy, 1978 12/25 Niclas Zeising born in Stockholm, Sweden, 1986 12/28 Soren Schmidt born in Maribo, Denmark, 1960 12/28 Ade Lovett born in London, England, 1969 12/28 Marius Strobl born in Cham, Bavaria, Germany, 1978 12/31 Edwin Groothuis born in Geldrop, the Netherlands, 1970 12/31 Fourth quarter status reports are due on 01/15 #endif /* !_calendar_freebsd_ */ Index: user/alc/PQ_LAUNDRY/usr.bin/calendar =================================================================== --- user/alc/PQ_LAUNDRY/usr.bin/calendar (revision 292448) +++ user/alc/PQ_LAUNDRY/usr.bin/calendar (revision 292449) Property changes on: user/alc/PQ_LAUNDRY/usr.bin/calendar ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/usr.bin/calendar:r291968-292448 Index: user/alc/PQ_LAUNDRY/usr.bin/netstat/ipsec.c =================================================================== --- user/alc/PQ_LAUNDRY/usr.bin/netstat/ipsec.c (revision 292448) +++ user/alc/PQ_LAUNDRY/usr.bin/netstat/ipsec.c (revision 292449) @@ -1,445 +1,455 @@ /* $KAME: ipsec.c,v 1.33 2003/07/25 09:54:32 itojun Exp $ */ /*- * Copyright (c) 2005 NTT Multimedia Communications Laboratories, Inc. * 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 AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*- * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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) 1983, 1988, 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. * 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. */ #if 0 #ifndef lint static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #ifdef IPSEC #include #include #include #include #endif #include #include #include #include #include #include #include "netstat.h" #ifdef IPSEC struct val2str { int val; const char *str; }; static struct val2str ipsec_ahnames[] = { { SADB_AALG_NONE, "none", }, { SADB_AALG_MD5HMAC, "hmac-md5", }, { SADB_AALG_SHA1HMAC, "hmac-sha1", }, { SADB_X_AALG_MD5, "md5", }, { SADB_X_AALG_SHA, "sha", }, { SADB_X_AALG_NULL, "null", }, #ifdef SADB_X_AALG_SHA2_256 { SADB_X_AALG_SHA2_256, "hmac-sha2-256", }, #endif #ifdef SADB_X_AALG_SHA2_384 { SADB_X_AALG_SHA2_384, "hmac-sha2-384", }, #endif #ifdef SADB_X_AALG_SHA2_512 { SADB_X_AALG_SHA2_512, "hmac-sha2-512", }, #endif #ifdef SADB_X_AALG_RIPEMD160HMAC { SADB_X_AALG_RIPEMD160HMAC, "hmac-ripemd160", }, #endif #ifdef SADB_X_AALG_AES_XCBC_MAC { SADB_X_AALG_AES_XCBC_MAC, "aes-xcbc-mac", }, #endif { -1, NULL }, }; static struct val2str ipsec_espnames[] = { { SADB_EALG_NONE, "none", }, { SADB_EALG_DESCBC, "des-cbc", }, { SADB_EALG_3DESCBC, "3des-cbc", }, { SADB_EALG_NULL, "null", }, { SADB_X_EALG_CAST128CBC, "cast128-cbc", }, { SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", }, #ifdef SADB_X_EALG_RIJNDAELCBC { SADB_X_EALG_RIJNDAELCBC, "rijndael-cbc", }, #endif #ifdef SADB_X_EALG_AESCTR { SADB_X_EALG_AESCTR, "aes-ctr", }, #endif #ifdef SADB_X_EALG_AESGCM16 { SADB_X_EALG_AESGCM16, "aes-gcm-16", }, #endif { -1, NULL }, }; static struct val2str ipsec_compnames[] = { { SADB_X_CALG_NONE, "none", }, { SADB_X_CALG_OUI, "oui", }, { SADB_X_CALG_DEFLATE, "deflate", }, { SADB_X_CALG_LZS, "lzs", }, { -1, NULL }, }; static void print_ipsecstats(const struct ipsecstat *ipsecstat); static void print_ipsecstats(const struct ipsecstat *ipsecstat) { xo_open_container("ipsec-statistics"); #define p(f, m) if (ipsecstat->f || sflag <= 1) \ xo_emit(m, (uintmax_t)ipsecstat->f, plural(ipsecstat->f)) p(ips_in_polvio, "\t{:dropped-policy-violation/%ju} " "{N:/inbound packet%s violated process security policy}\n"); p(ips_in_nomem, "\t{:dropped-no-memory/%ju} " "{N:/inbound packet%s failed due to insufficient memory}\n"); p(ips_in_inval, "\t{:dropped-invalid/%ju} " "{N:/invalid inbound packet%s}\n"); p(ips_out_polvio, "\t{:discarded-policy-violation/%ju} " "{N:/outbound packet%s violated process security policy}\n"); p(ips_out_nosa, "\t{:discarded-no-sa/%ju} " "{N:/outbound packet%s with no SA available}\n"); p(ips_out_nomem, "\t{:discarded-no-memory/%ju} " "{N:/outbound packet%s failed due to insufficient memory}\n"); p(ips_out_noroute, "\t{:discarded-no-route/%ju} " "{N:/outbound packet%s with no route available}\n"); p(ips_out_inval, "\t{:discarded-invalid/%ju} " "{N:/invalid outbound packet%s}\n"); p(ips_out_bundlesa, "\t{:send-bundled-sa/%ju} " "{N:/outbound packet%s with bundled SAs}\n"); p(ips_mbcoalesced, "\t{:mbufs-coalesced-during-clone/%ju} " "{N:/mbuf%s coalesced during clone}\n"); p(ips_clcoalesced, "\t{:clusters-coalesced-during-clone/%ju} " "{N:/cluster%s coalesced during clone}\n"); p(ips_clcopied, "\t{:clusters-copied-during-clone/%ju} " "{N:/cluster%s copied during clone}\n"); p(ips_mbinserted, "\t{:mbufs-inserted/%ju} " "{N:/mbuf%s inserted during makespace}\n"); #undef p xo_close_container("ipsec-statistics"); } void ipsec_stats(u_long off, const char *name, int af1 __unused, int proto __unused) { struct ipsecstat ipsecstat; - if (off == 0) - return; + if (strcmp(name, "ipsec6") == 0) { + if (fetch_stats("net.inet6.ipsec6.ipsecstats", off,&ipsecstat, + sizeof(ipsecstat), kread_counters) != 0) + return; + } else { + if (fetch_stats("net.inet.ipsec.ipsecstats", off, &ipsecstat, + sizeof(ipsecstat), kread_counters) != 0) + return; + } + xo_emit("{T:/%s}:\n", name); - kread_counters(off, (char *)&ipsecstat, sizeof(ipsecstat)); print_ipsecstats(&ipsecstat); } static void print_ahstats(const struct ahstat *ahstat); static void print_espstats(const struct espstat *espstat); static void print_ipcompstats(const struct ipcompstat *ipcompstat); /* * Dump IPSEC statistics structure. */ static void ipsec_hist_new(const uint64_t *hist, size_t histmax, const struct val2str *name, const char *title, const char *cname) { int first; size_t proto; const struct val2str *p; first = 1; for (proto = 0; proto < histmax; proto++) { if (hist[proto] <= 0) continue; if (first) { xo_open_list(cname); xo_emit("\t{T:/%s histogram}:\n", title); first = 0; } xo_open_instance(cname); for (p = name; p && p->str; p++) { if (p->val == (int)proto) break; } if (p && p->str) { xo_emit("\t\t{k:name}: {:count/%ju}\n", p->str, (uintmax_t)hist[proto]); } else { xo_emit("\t\t#{k:name/%lu}: {:count/%ju}\n", (unsigned long)proto, (uintmax_t)hist[proto]); } xo_close_instance(cname); } if (!first) xo_close_list(cname); } static void print_ahstats(const struct ahstat *ahstat) { xo_open_container("ah-statictics"); #define p(f, n, m) if (ahstat->f || sflag <= 1) \ xo_emit("\t{:" n "/%ju} {N:/" m "}\n", \ (uintmax_t)ahstat->f, plural(ahstat->f)) #define hist(f, n, t, c) \ ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t), (c)) p(ahs_hdrops, "dropped-short-header", "packet%s shorter than header shows"); p(ahs_nopf, "dropped-bad-protocol", "packet%s dropped; protocol family not supported"); p(ahs_notdb, "dropped-no-tdb", "packet%s dropped; no TDB"); p(ahs_badkcr, "dropped-bad-kcr", "packet%s dropped; bad KCR"); p(ahs_qfull, "dropped-queue-full", "packet%s dropped; queue full"); p(ahs_noxform, "dropped-no-transform", "packet%s dropped; no transform"); p(ahs_wrap, "replay-counter-wraps", "replay counter wrap%s"); p(ahs_badauth, "dropped-bad-auth", "packet%s dropped; bad authentication detected"); p(ahs_badauthl, "dropped-bad-auth-level", "packet%s dropped; bad authentication length"); p(ahs_replay, "possile-replay-detected", "possible replay packet%s detected"); p(ahs_input, "received-packets", "packet%s in"); p(ahs_output, "send-packets", "packet%s out"); p(ahs_invalid, "dropped-bad-tdb", "packet%s dropped; invalid TDB"); p(ahs_ibytes, "received-bytes", "byte%s in"); p(ahs_obytes, "send-bytes", "byte%s out"); p(ahs_toobig, "dropped-too-large", "packet%s dropped; larger than IP_MAXPACKET"); p(ahs_pdrops, "dropped-policy-violation", "packet%s blocked due to policy"); p(ahs_crypto, "crypto-failures", "crypto processing failure%s"); p(ahs_tunnel, "tunnel-failures", "tunnel sanity check failure%s"); hist(ahstat->ahs_hist, ipsec_ahnames, "AH output", "ah-output-histogram"); #undef p #undef hist xo_close_container("ah-statictics"); } void ah_stats(u_long off, const char *name, int family __unused, int proto __unused) { struct ahstat ahstat; - if (off == 0) + if (fetch_stats("net.inet.ah.stats", off, &ahstat, + sizeof(ahstat), kread_counters) != 0) return; + xo_emit("{T:/%s}:\n", name); - kread_counters(off, (char *)&ahstat, sizeof(ahstat)); print_ahstats(&ahstat); } static void print_espstats(const struct espstat *espstat) { xo_open_container("esp-statictics"); #define p(f, n, m) if (espstat->f || sflag <= 1) \ xo_emit("\t{:" n "/%ju} {N:/" m "}\n", \ (uintmax_t)espstat->f, plural(espstat->f)) #define hist(f, n, t, c) \ ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t), (c)); p(esps_hdrops, "dropped-short-header", "packet%s shorter than header shows"); p(esps_nopf, "dropped-bad-protocol", "packet%s dropped; protocol family not supported"); p(esps_notdb, "dropped-no-tdb", "packet%s dropped; no TDB"); p(esps_badkcr, "dropped-bad-kcr", "packet%s dropped; bad KCR"); p(esps_qfull, "dropped-queue-full", "packet%s dropped; queue full"); p(esps_noxform, "dropped-no-transform", "packet%s dropped; no transform"); p(esps_badilen, "dropped-bad-length", "packet%s dropped; bad ilen"); p(esps_wrap, "replay-counter-wraps", "replay counter wrap%s"); p(esps_badenc, "dropped-bad-crypto", "packet%s dropped; bad encryption detected"); p(esps_badauth, "dropped-bad-auth", "packet%s dropped; bad authentication detected"); p(esps_replay, "possible-replay-detected", "possible replay packet%s detected"); p(esps_input, "received-packets", "packet%s in"); p(esps_output, "sent-packets", "packet%s out"); p(esps_invalid, "dropped-bad-tdb", "packet%s dropped; invalid TDB"); p(esps_ibytes, "receieve-bytes", "byte%s in"); p(esps_obytes, "sent-bytes", "byte%s out"); p(esps_toobig, "dropped-too-large", "packet%s dropped; larger than IP_MAXPACKET"); p(esps_pdrops, "dropped-policy-violation", "packet%s blocked due to policy"); p(esps_crypto, "crypto-failures", "crypto processing failure%s"); p(esps_tunnel, "tunnel-failures", "tunnel sanity check failure%s"); hist(espstat->esps_hist, ipsec_espnames, "ESP output", "esp-output-histogram"); #undef p #undef hist xo_close_container("esp-statictics"); } void esp_stats(u_long off, const char *name, int family __unused, int proto __unused) { struct espstat espstat; - if (off == 0) + if (fetch_stats("net.inet.esp.stats", off, &espstat, + sizeof(espstat), kread_counters) != 0) return; + xo_emit("{T:/%s}:\n", name); - kread_counters(off, (char *)&espstat, sizeof(espstat)); print_espstats(&espstat); } static void print_ipcompstats(const struct ipcompstat *ipcompstat) { xo_open_container("ipcomp-statictics"); #define p(f, n, m) if (ipcompstat->f || sflag <= 1) \ xo_emit("\t{:" n "/%ju} {N:/" m "}\n", \ (uintmax_t)ipcompstat->f, plural(ipcompstat->f)) #define hist(f, n, t, c) \ ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t), (c)); p(ipcomps_hdrops, "dropped-short-header", "packet%s shorter than header shows"); p(ipcomps_nopf, "dropped-bad-protocol", "packet%s dropped; protocol family not supported"); p(ipcomps_notdb, "dropped-no-tdb", "packet%s dropped; no TDB"); p(ipcomps_badkcr, "dropped-bad-kcr", "packet%s dropped; bad KCR"); p(ipcomps_qfull, "dropped-queue-full", "packet%s dropped; queue full"); p(ipcomps_noxform, "dropped-no-transform", "packet%s dropped; no transform"); p(ipcomps_wrap, "replay-counter-wraps", "replay counter wrap%s"); p(ipcomps_input, "receieve-packets", "packet%s in"); p(ipcomps_output, "sent-packets", "packet%s out"); p(ipcomps_invalid, "dropped-bad-tdb", "packet%s dropped; invalid TDB"); p(ipcomps_ibytes, "receieved-bytes", "byte%s in"); p(ipcomps_obytes, "sent-bytes", "byte%s out"); p(ipcomps_toobig, "dropped-too-large", "packet%s dropped; larger than IP_MAXPACKET"); p(ipcomps_pdrops, "dropped-policy-violation", "packet%s blocked due to policy"); p(ipcomps_crypto, "crypto-failure", "crypto processing failure%s"); hist(ipcompstat->ipcomps_hist, ipsec_compnames, "COMP output", "comp-output-histogram"); p(ipcomps_threshold, "sent-uncompressed-small-packets", "packet%s sent uncompressed; size < compr. algo. threshold"); p(ipcomps_uncompr, "sent-uncompressed-useless-packets", "packet%s sent uncompressed; compression was useless"); #undef p #undef hist xo_close_container("ipcomp-statictics"); } void ipcomp_stats(u_long off, const char *name, int family __unused, int proto __unused) { struct ipcompstat ipcompstat; - if (off == 0) + if (fetch_stats("net.inet.ipcomp.stats", off, &ipcompstat, + sizeof(ipcompstat), kread_counters) != 0) return; + xo_emit("{T:/%s}:\n", name); - kread_counters(off, (char *)&ipcompstat, sizeof(ipcompstat)); print_ipcompstats(&ipcompstat); } #endif /*IPSEC*/ Index: user/alc/PQ_LAUNDRY/usr.bin/netstat/main.c =================================================================== --- user/alc/PQ_LAUNDRY/usr.bin/netstat/main.c (revision 292448) +++ user/alc/PQ_LAUNDRY/usr.bin/netstat/main.c (revision 292449) @@ -1,857 +1,857 @@ /*- * Copyright (c) 1983, 1988, 1993 * 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. * 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. */ #ifndef lint static char const copyright[] = "@(#) Copyright (c) 1983, 1988, 1993\n\ Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #if 0 #ifndef lint static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 3/1/94"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #ifdef NETGRAPH #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "netstat.h" #include "nl_defs.h" #include static struct protox { int pr_index; /* index into nlist of cb head */ int pr_sindex; /* index into nlist of stat block */ u_char pr_wanted; /* 1 if wanted, 0 otherwise */ void (*pr_cblocks)(u_long, const char *, int, int); /* control blocks printing routine */ void (*pr_stats)(u_long, const char *, int, int); /* statistics printing routine */ void (*pr_istats)(char *); /* per/if statistics printing routine */ const char *pr_name; /* well-known name */ int pr_usesysctl; /* non-zero if we use sysctl, not kvm */ int pr_protocol; } protox[] = { { N_TCBINFO, N_TCPSTAT, 1, protopr, tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, { N_UDBINFO, N_UDPSTAT, 1, protopr, udp_stats, NULL, "udp", 1, IPPROTO_UDP }, #ifdef SCTP { -1, N_SCTPSTAT, 1, sctp_protopr, sctp_stats, NULL, "sctp", 1, IPPROTO_SCTP }, #endif #ifdef SDP { -1, -1, 1, protopr, NULL, NULL, "sdp", 1, IPPROTO_TCP }, #endif { N_DIVCBINFO, -1, 1, protopr, NULL, NULL, "divert", 1, IPPROTO_DIVERT }, { N_RIPCBINFO, N_IPSTAT, 1, protopr, ip_stats, NULL, "ip", 1, IPPROTO_RAW }, { N_RIPCBINFO, N_ICMPSTAT, 1, protopr, icmp_stats, NULL, "icmp", 1, IPPROTO_ICMP }, { N_RIPCBINFO, N_IGMPSTAT, 1, protopr, igmp_stats, NULL, "igmp", 1, IPPROTO_IGMP }, #ifdef IPSEC { -1, N_IPSEC4STAT, 1, NULL, /* keep as compat */ - ipsec_stats, NULL, "ipsec", 0, 0}, + ipsec_stats, NULL, "ipsec", 1, 0}, { -1, N_AHSTAT, 1, NULL, - ah_stats, NULL, "ah", 0, 0}, + ah_stats, NULL, "ah", 1, 0}, { -1, N_ESPSTAT, 1, NULL, - esp_stats, NULL, "esp", 0, 0}, + esp_stats, NULL, "esp", 1, 0}, { -1, N_IPCOMPSTAT, 1, NULL, - ipcomp_stats, NULL, "ipcomp", 0, 0}, + ipcomp_stats, NULL, "ipcomp", 1, 0}, #endif { N_RIPCBINFO, N_PIMSTAT, 1, protopr, pim_stats, NULL, "pim", 1, IPPROTO_PIM }, { -1, N_CARPSTATS, 1, NULL, carp_stats, NULL, "carp", 1, 0 }, #ifdef PF { -1, N_PFSYNCSTATS, 1, NULL, pfsync_stats, NULL, "pfsync", 1, 0 }, #endif { -1, N_ARPSTAT, 1, NULL, arp_stats, NULL, "arp", 1, 0 }, { -1, -1, 0, NULL, NULL, NULL, NULL, 0, 0 } }; #ifdef INET6 static struct protox ip6protox[] = { { N_TCBINFO, N_TCPSTAT, 1, protopr, tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, { N_UDBINFO, N_UDPSTAT, 1, protopr, udp_stats, NULL, "udp", 1, IPPROTO_UDP }, { N_RIPCBINFO, N_IP6STAT, 1, protopr, ip6_stats, ip6_ifstats, "ip6", 1, IPPROTO_RAW }, { N_RIPCBINFO, N_ICMP6STAT, 1, protopr, icmp6_stats, icmp6_ifstats, "icmp6", 1, IPPROTO_ICMPV6 }, #ifdef SDP { -1, -1, 1, protopr, NULL, NULL, "sdp", 1, IPPROTO_TCP }, #endif #ifdef IPSEC { -1, N_IPSEC6STAT, 1, NULL, - ipsec_stats, NULL, "ipsec6", 0, 0 }, + ipsec_stats, NULL, "ipsec6", 1, 0 }, #endif #ifdef notyet { -1, N_PIM6STAT, 1, NULL, pim6_stats, NULL, "pim6", 1, 0 }, #endif { -1, N_RIP6STAT, 1, NULL, rip6_stats, NULL, "rip6", 1, 0 }, { -1, -1, 0, NULL, NULL, NULL, NULL, 0, 0 } }; #endif /*INET6*/ #ifdef IPSEC static struct protox pfkeyprotox[] = { { -1, N_PFKEYSTAT, 1, NULL, pfkey_stats, NULL, "pfkey", 0, 0 }, { -1, -1, 0, NULL, NULL, NULL, NULL, 0, 0 } }; #endif #ifdef NETGRAPH static struct protox netgraphprotox[] = { { N_NGSOCKLIST, -1, 1, netgraphprotopr, NULL, NULL, "ctrl", 0, 0 }, { N_NGSOCKLIST, -1, 1, netgraphprotopr, NULL, NULL, "data", 0, 0 }, { -1, -1, 0, NULL, NULL, NULL, NULL, 0, 0 } }; #endif static struct protox *protoprotox[] = { protox, #ifdef INET6 ip6protox, #endif #ifdef IPSEC pfkeyprotox, #endif NULL }; static void printproto(struct protox *, const char *, bool *); static void usage(void); static struct protox *name2protox(const char *); static struct protox *knownname(const char *); static int kresolve_list(struct nlist *_nl); static kvm_t *kvmd; static char *nlistf = NULL, *memf = NULL; int Aflag; /* show addresses of protocol control block */ int aflag; /* show all sockets (including servers) */ static int Bflag; /* show information about bpf consumers */ int bflag; /* show i/f total bytes in/out */ int dflag; /* show i/f dropped packets */ int gflag; /* show group (multicast) routing or stats */ int hflag; /* show counters in human readable format */ int iflag; /* show interfaces */ int Lflag; /* show size of listen queues */ int mflag; /* show memory stats */ int noutputs = 0; /* how much outputs before we exit */ int numeric_addr; /* show addresses numerically */ int numeric_port; /* show ports numerically */ static int pflag; /* show given protocol */ static int Qflag; /* show netisr information */ int rflag; /* show routing tables (or routing stats) */ int Rflag; /* show flow / RSS statistics */ int sflag; /* show protocol statistics */ int Wflag; /* wide display */ int Tflag; /* TCP Information */ int xflag; /* extra information, includes all socket buffer info */ int zflag; /* zero stats */ int interval; /* repeat interval for i/f stats */ char *interface; /* desired i/f for stats, or NULL for all i/fs */ int unit; /* unit number for above */ static int af; /* address family */ int live; /* true if we are examining a live system */ int main(int argc, char *argv[]) { struct protox *tp = NULL; /* for printing cblocks & stats */ int ch; int fib = -1; char *endptr; bool first = true; af = AF_UNSPEC; argc = xo_parse_args(argc, argv); if (argc < 0) exit(EXIT_FAILURE); while ((ch = getopt(argc, argv, "46AaBbdF:f:ghI:iLlM:mN:np:Qq:RrSTsuWw:xz")) != -1) switch(ch) { case '4': #ifdef INET af = AF_INET; #else errx(1, "IPv4 support is not compiled in"); #endif break; case '6': #ifdef INET6 af = AF_INET6; #else errx(1, "IPv6 support is not compiled in"); #endif break; case 'A': Aflag = 1; break; case 'a': aflag = 1; break; case 'B': Bflag = 1; break; case 'b': bflag = 1; break; case 'd': dflag = 1; break; case 'F': fib = strtol(optarg, &endptr, 0); if (*endptr != '\0' || (fib == 0 && (errno == EINVAL || errno == ERANGE))) xo_errx(1, "%s: invalid fib", optarg); break; case 'f': if (strcmp(optarg, "inet") == 0) af = AF_INET; #ifdef INET6 else if (strcmp(optarg, "inet6") == 0) af = AF_INET6; #endif #ifdef IPSEC else if (strcmp(optarg, "pfkey") == 0) af = PF_KEY; #endif else if (strcmp(optarg, "unix") == 0 || strcmp(optarg, "local") == 0) af = AF_UNIX; #ifdef NETGRAPH else if (strcmp(optarg, "ng") == 0 || strcmp(optarg, "netgraph") == 0) af = AF_NETGRAPH; #endif else if (strcmp(optarg, "link") == 0) af = AF_LINK; else { xo_errx(1, "%s: unknown address family", optarg); } break; case 'g': gflag = 1; break; case 'h': hflag = 1; break; case 'I': { char *cp; iflag = 1; for (cp = interface = optarg; isalpha(*cp); cp++) continue; unit = atoi(cp); break; } case 'i': iflag = 1; break; case 'L': Lflag = 1; break; case 'M': memf = optarg; break; case 'm': mflag = 1; break; case 'N': nlistf = optarg; break; case 'n': numeric_addr = numeric_port = 1; break; case 'p': if ((tp = name2protox(optarg)) == NULL) { xo_errx(1, "%s: unknown or uninstrumented " "protocol", optarg); } pflag = 1; break; case 'Q': Qflag = 1; break; case 'q': noutputs = atoi(optarg); if (noutputs != 0) noutputs++; break; case 'r': rflag = 1; break; case 'R': Rflag = 1; break; case 's': ++sflag; break; case 'S': numeric_addr = 1; break; case 'u': af = AF_UNIX; break; case 'W': case 'l': Wflag = 1; break; case 'w': interval = atoi(optarg); iflag = 1; break; case 'T': Tflag = 1; break; case 'x': xflag = 1; break; case 'z': zflag = 1; break; case '?': default: usage(); } argv += optind; argc -= optind; #define BACKWARD_COMPATIBILITY #ifdef BACKWARD_COMPATIBILITY if (*argv) { if (isdigit(**argv)) { interval = atoi(*argv); if (interval <= 0) usage(); ++argv; iflag = 1; } if (*argv) { nlistf = *argv; if (*++argv) memf = *argv; } } #endif /* * Discard setgid privileges if not the running kernel so that bad * guys can't print interesting stuff from kernel memory. */ live = (nlistf == NULL && memf == NULL); if (!live) { if (setgid(getgid()) != 0) xo_err(-1, "setgid"); } if (xflag && Tflag) xo_errx(1, "-x and -T are incompatible, pick one."); if (Bflag) { if (!live) usage(); bpf_stats(interface); xo_finish(); exit(0); } if (mflag) { if (!live) { if (kread(0, NULL, 0) == 0) mbpr(kvmd, nl[N_SFSTAT].n_value); } else mbpr(NULL, 0); xo_finish(); exit(0); } if (Qflag) { if (!live) { if (kread(0, NULL, 0) == 0) netisr_stats(); } else netisr_stats(); xo_finish(); exit(0); } #if 0 /* * Keep file descriptors open to avoid overhead * of open/close on each call to get* routines. */ sethostent(1); setnetent(1); #else /* * This does not make sense any more with DNS being default over * the files. Doing a setXXXXent(1) causes a tcp connection to be * used for the queries, which is slower. */ #endif if (iflag && !sflag) { xo_open_container("statistics"); intpr(NULL, af); xo_close_container("statistics"); xo_finish(); exit(0); } if (rflag) { xo_open_container("statistics"); if (sflag) { rt_stats(); flowtable_stats(); } else routepr(fib, af); xo_close_container("statistics"); xo_finish(); exit(0); } if (gflag) { xo_open_container("statistics"); if (sflag) { if (af == AF_INET || af == AF_UNSPEC) mrt_stats(); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) mrt6_stats(); #endif } else { if (af == AF_INET || af == AF_UNSPEC) mroutepr(); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) mroute6pr(); #endif } xo_close_container("statistics"); xo_finish(); exit(0); } /* Load all necessary kvm symbols */ kresolve_list(nl); if (tp) { xo_open_container("statistics"); printproto(tp, tp->pr_name, &first); if (!first) xo_close_list("socket"); xo_close_container("statistics"); xo_finish(); exit(0); } xo_open_container("statistics"); if (af == AF_INET || af == AF_UNSPEC) for (tp = protox; tp->pr_name; tp++) printproto(tp, tp->pr_name, &first); #ifdef INET6 if (af == AF_INET6 || af == AF_UNSPEC) for (tp = ip6protox; tp->pr_name; tp++) printproto(tp, tp->pr_name, &first); #endif /*INET6*/ #ifdef IPSEC if (af == PF_KEY || af == AF_UNSPEC) for (tp = pfkeyprotox; tp->pr_name; tp++) printproto(tp, tp->pr_name, &first); #endif /*IPSEC*/ #ifdef NETGRAPH if (af == AF_NETGRAPH || af == AF_UNSPEC) for (tp = netgraphprotox; tp->pr_name; tp++) printproto(tp, tp->pr_name, &first); #endif /* NETGRAPH */ if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag) unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value, nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value, nl[N_UNP_SPHEAD].n_value, &first); if (!first) xo_close_list("socket"); xo_close_container("statistics"); xo_finish(); exit(0); } int fetch_stats(const char *sysctlname, u_long off, void *stats, size_t len, int (*kreadfn)(u_long, void *, size_t)) { int error; if (live) { memset(stats, 0, len); if (zflag) error = sysctlbyname(sysctlname, NULL, NULL, stats, len); else error = sysctlbyname(sysctlname, stats, &len, NULL, 0); if (error == -1 && errno != ENOENT) xo_warn("sysctl %s", sysctlname); } else { if (off == 0) return (1); error = kreadfn(off, stats, len); } return (error); } /* * Print out protocol statistics or control blocks (per sflag). * If the interface was not specifically requested, and the symbol * is not in the namelist, ignore this one. */ static void printproto(struct protox *tp, const char *name, bool *first) { void (*pr)(u_long, const char *, int, int); u_long off; bool doingdblocks = false; if (sflag) { if (iflag) { if (tp->pr_istats) intpr(tp->pr_istats, af); else if (pflag) xo_message("%s: no per-interface stats routine", tp->pr_name); return; } else { pr = tp->pr_stats; if (!pr) { if (pflag) xo_message("%s: no stats routine", tp->pr_name); return; } if (tp->pr_usesysctl && live) off = 0; else if (tp->pr_sindex < 0) { if (pflag) xo_message("%s: stats routine doesn't " "work on cores", tp->pr_name); return; } else off = nl[tp->pr_sindex].n_value; } } else { doingdblocks = true; pr = tp->pr_cblocks; if (!pr) { if (pflag) xo_message("%s: no PCB routine", tp->pr_name); return; } if (tp->pr_usesysctl && live) off = 0; else if (tp->pr_index < 0) { if (pflag) xo_message("%s: PCB routine doesn't work on " "cores", tp->pr_name); return; } else off = nl[tp->pr_index].n_value; } if (pr != NULL && (off || (live && tp->pr_usesysctl) || af != AF_UNSPEC)) { if (doingdblocks && *first) { xo_open_list("socket"); *first = false; } (*pr)(off, name, af, tp->pr_protocol); } } static int kvmd_init(void) { char errbuf[_POSIX2_LINE_MAX]; if (kvmd != NULL) return (0); kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); if (setgid(getgid()) != 0) xo_err(-1, "setgid"); if (kvmd == NULL) { xo_warnx("kvm not available: %s", errbuf); return (-1); } return (0); } /* * Resolve symbol list, return 0 on success. */ static int kresolve_list(struct nlist *_nl) { if ((kvmd == NULL) && (kvmd_init() != 0)) return (-1); if (_nl[0].n_type != 0) return (0); if (kvm_nlist(kvmd, _nl) < 0) { if (nlistf) xo_errx(1, "%s: kvm_nlist: %s", nlistf, kvm_geterr(kvmd)); else xo_errx(1, "kvm_nlist: %s", kvm_geterr(kvmd)); } return (0); } /* * Wrapper of kvm_dpcpu_setcpu(). */ void kset_dpcpu(u_int cpuid) { if ((kvmd == NULL) && (kvmd_init() != 0)) xo_errx(-1, "%s: kvm is not available", __func__); if (kvm_dpcpu_setcpu(kvmd, cpuid) < 0) xo_errx(-1, "%s: kvm_dpcpu_setcpu(%u): %s", __func__, cpuid, kvm_geterr(kvmd)); return; } /* * Read kernel memory, return 0 on success. */ int kread(u_long addr, void *buf, size_t size) { if (kvmd_init() < 0) return (-1); if (!buf) return (0); if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) { xo_warnx("%s", kvm_geterr(kvmd)); return (-1); } return (0); } /* * Read single counter(9). */ uint64_t kread_counter(u_long addr) { if (kvmd_init() < 0) return (-1); return (kvm_counter_u64_fetch(kvmd, addr)); } /* * Read an array of N counters in kernel memory into array of N uint64_t's. */ int kread_counters(u_long addr, void *buf, size_t size) { uint64_t *c; u_long *counters; size_t i, n; if (kvmd_init() < 0) return (-1); if (size % sizeof(uint64_t) != 0) { xo_warnx("kread_counters: invalid counter set size"); return (-1); } n = size / sizeof(uint64_t); if ((counters = malloc(n * sizeof(u_long))) == NULL) xo_err(-1, "malloc"); if (kread(addr, counters, n * sizeof(u_long)) < 0) { free(counters); return (-1); } c = buf; for (i = 0; i < n; i++) c[i] = kvm_counter_u64_fetch(kvmd, counters[i]); free(counters); return (0); } const char * plural(uintmax_t n) { return (n != 1 ? "s" : ""); } const char * plurales(uintmax_t n) { return (n != 1 ? "es" : ""); } const char * pluralies(uintmax_t n) { return (n != 1 ? "ies" : "y"); } /* * Find the protox for the given "well-known" name. */ static struct protox * knownname(const char *name) { struct protox **tpp, *tp; for (tpp = protoprotox; *tpp; tpp++) for (tp = *tpp; tp->pr_name; tp++) if (strcmp(tp->pr_name, name) == 0) return (tp); return (NULL); } /* * Find the protox corresponding to name. */ static struct protox * name2protox(const char *name) { struct protox *tp; char **alias; /* alias from p->aliases */ struct protoent *p; /* * Try to find the name in the list of "well-known" names. If that * fails, check if name is an alias for an Internet protocol. */ if ((tp = knownname(name)) != NULL) return (tp); setprotoent(1); /* make protocol lookup cheaper */ while ((p = getprotoent()) != NULL) { /* assert: name not same as p->name */ for (alias = p->p_aliases; *alias; alias++) if (strcmp(name, *alias) == 0) { endprotoent(); return (knownname(p->p_name)); } } endprotoent(); return (NULL); } static void usage(void) { (void)xo_error("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", "usage: netstat [-46AaLnRSTWx] [-f protocol_family | -p protocol]\n" " [-M core] [-N system]", " netstat -i | -I interface [-46abdhnW] [-f address_family]\n" " [-M core] [-N system]", " netstat -w wait [-I interface] [-46d] [-M core] [-N system]\n" " [-q howmany]", " netstat -s [-46sz] [-f protocol_family | -p protocol]\n" " [-M core] [-N system]", " netstat -i | -I interface -s [-46s]\n" " [-f protocol_family | -p protocol] [-M core] [-N system]", " netstat -m [-M core] [-N system]", " netstat -B [-z] [-I interface]", " netstat -r [-46AnW] [-F fibnum] [-f address_family]\n" " [-M core] [-N system]", " netstat -rs [-s] [-M core] [-N system]", " netstat -g [-46W] [-f address_family] [-M core] [-N system]", " netstat -gs [-46s] [-f address_family] [-M core] [-N system]", " netstat -Q"); xo_finish(); exit(1); } Index: user/alc/PQ_LAUNDRY/usr.sbin/boot0cfg/boot0cfg.c =================================================================== --- user/alc/PQ_LAUNDRY/usr.sbin/boot0cfg/boot0cfg.c (revision 292448) +++ user/alc/PQ_LAUNDRY/usr.sbin/boot0cfg/boot0cfg.c (revision 292449) @@ -1,605 +1,607 @@ /* * Copyright (c) 2008 Luigi Rizzo * Copyright (c) 1999 Robert Nordier * 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 AND CONTRIBUTORS``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #define MBRSIZE 512 /* master boot record size */ #define OFF_VERSION 0x1b0 /* offset: version number, only boot0version */ #define OFF_SERIAL 0x1b8 /* offset: volume serial number */ #define OFF_PTBL 0x1be /* offset: partition table */ #define OFF_MAGIC 0x1fe /* offset: magic number */ /* * Offsets to the parameters of the 512-byte boot block. * For historical reasons they are set as macros */ struct opt_offsets { int opt; int drive; int flags; int ticks; }; static struct opt_offsets b0_ofs[] = { { 0x0, 0x0, 0x0, 0x0 }, /* no boot block */ { 0x1b9, 0x1ba, 0x1bb, 0x1bc }, /* original block */ { 0x1b5, 0x1b6, 0x1b7, 0x1bc }, /* NT_SERIAL block */ }; static int b0_ver; /* boot block version set by boot0bs */ #define OFF_OPT (b0_ofs[b0_ver].opt) /* default boot option */ #define OFF_DRIVE (b0_ofs[b0_ver].drive) /* setdrv drive */ #define OFF_FLAGS (b0_ofs[b0_ver].flags) /* option flags */ #define OFF_TICKS (b0_ofs[b0_ver].ticks) /* clock ticks */ #define cv2(p) ((p)[0] | (p)[1] << 010) #define mk2(p, x) \ (p)[0] = (u_int8_t)(x), \ (p)[1] = (u_int8_t)((x) >> 010) static const struct { const char *tok; int def; } opttbl[] = { {"packet", 0}, {"update", 1}, {"setdrv", 0} }; static const int nopt = sizeof(opttbl) / sizeof(opttbl[0]); static const char fmt0[] = "# flag start chs type" " end chs offset size\n"; static const char fmt1[] = "%d 0x%02x %4u:%3u:%2u 0x%02x" " %4u:%3u:%2u %10u %10u\n"; static int geom_class_available(const char *); static int read_mbr(const char *, u_int8_t **, int); static void write_mbr(const char *, int, u_int8_t *, int); static void display_mbr(u_int8_t *); static int boot0version(const u_int8_t *); static int boot0bs(const u_int8_t *); static void stropt(const char *, int *, int *); static int argtoi(const char *, int, int, int); static int set_bell(u_int8_t *, int, int); static void usage(void); static unsigned vol_id[5]; /* 4 plus 1 for flag */ static int v_flag; /* * Boot manager installation/configuration utility. */ int main(int argc, char *argv[]) { u_int8_t *mbr, *boot0; int boot0_size, mbr_size; const char *bpath, *fpath; char *disk; int B_flag, o_flag; int d_arg, m_arg, s_arg, t_arg; int o_and, o_or, o_e = -1; int up, c; bpath = "/boot/boot0"; fpath = NULL; B_flag = v_flag = o_flag = 0; d_arg = m_arg = s_arg = t_arg = -1; o_and = 0xff; o_or = 0; while ((c = getopt(argc, argv, "Bvb:d:e:f:i:m:o:s:t:")) != -1) switch (c) { case 'B': B_flag = 1; break; case 'v': v_flag = 1; break; case 'b': bpath = optarg; break; case 'd': d_arg = argtoi(optarg, 0, 0xff, 'd'); break; case 'e': if (optarg[0] == '0' && optarg[1] == 'x') sscanf(optarg, "0x%02x", &o_e); else o_e = optarg[0]; break; case 'f': fpath = optarg; break; case 'i': if (sscanf(optarg, "%02x%02x-%02x%02x", vol_id, vol_id+1, vol_id+2, vol_id+3) == 4) vol_id[4] = 1; else errx(1, "bad argument %s", optarg); break; case 'm': m_arg = argtoi(optarg, 0, 0xf, 'm'); break; case 'o': stropt(optarg, &o_and, &o_or); o_flag = 1; break; case 's': if (strcasecmp(optarg, "pxe") == 0) s_arg = 6; else s_arg = argtoi(optarg, 1, 6, 's'); break; case 't': t_arg = argtoi(optarg, 1, 0xffff, 't'); break; default: usage(); } argc -= optind; argv += optind; if (argc != 1) usage(); disk = g_device_path(*argv); if (disk == NULL) errx(1, "Unable to get providername for %s\n", *argv); up = B_flag || d_arg != -1 || m_arg != -1 || o_flag || s_arg != -1 || t_arg != -1; /* open the disk and read in the existing mbr. Either here or * when reading the block from disk, we do check for the version * and abort if a suitable block is not found. */ mbr_size = read_mbr(disk, &mbr, !B_flag); /* save the existing MBR if we are asked to do so */ if (fpath) write_mbr(fpath, O_CREAT | O_TRUNC, mbr, mbr_size); /* * If we are installing the boot loader, read it from disk and copy the * slice table over from the existing MBR. If not, then point boot0 * back at the MBR we just read in. After this, boot0 is the data to * write back to disk if we are going to do a write. */ if (B_flag) { boot0_size = read_mbr(bpath, &boot0, 1); memcpy(boot0 + OFF_PTBL, mbr + OFF_PTBL, sizeof(struct dos_partition) * NDOSPART); if (b0_ver == 2) /* volume serial number support */ memcpy(boot0 + OFF_SERIAL, mbr + OFF_SERIAL, 4); } else { boot0 = mbr; boot0_size = mbr_size; } /* set the drive */ if (d_arg != -1) boot0[OFF_DRIVE] = d_arg; /* set various flags */ if (m_arg != -1) { boot0[OFF_FLAGS] &= 0xf0; boot0[OFF_FLAGS] |= m_arg; } if (o_flag) { boot0[OFF_FLAGS] &= o_and; boot0[OFF_FLAGS] |= o_or; } /* set the default boot selection */ if (s_arg != -1) boot0[OFF_OPT] = s_arg - 1; /* set the timeout */ if (t_arg != -1) mk2(boot0 + OFF_TICKS, t_arg); /* set the bell char */ if (o_e != -1 && set_bell(boot0, o_e, 0) != -1) up = 1; if (vol_id[4]) { if (b0_ver != 2) errx(1, "incompatible boot block, cannot set volume ID"); boot0[OFF_SERIAL] = vol_id[0]; boot0[OFF_SERIAL+1] = vol_id[1]; boot0[OFF_SERIAL+2] = vol_id[2]; boot0[OFF_SERIAL+3] = vol_id[3]; up = 1; /* force update */ } /* write the MBR back to disk */ if (up) write_mbr(disk, 0, boot0, boot0_size); /* display the MBR */ if (v_flag) display_mbr(boot0); /* clean up */ if (mbr != boot0) free(boot0); free(mbr); free(disk); return 0; } /* get or set the 'bell' character to be used in case of errors. * Lookup for a certain code sequence, return -1 if not found. */ static int set_bell(u_int8_t *mbr, int new_bell, int report) { /* lookup sequence: 0x100 means skip, 0x200 means done */ static unsigned seq[] = { 0xb0, 0x100, 0xe8, 0x100, 0x100, 0x30, 0xe4, 0x200 }; int ofs, i, c; for (ofs = 0x60; ofs < 0x180; ofs++) { /* search range */ if (mbr[ofs] != seq[0]) /* search initial pattern */ continue; for (i=0;; i++) { if (seq[i] == 0x200) { /* found */ c = mbr[ofs+1]; if (!report) mbr[ofs+1] = c = new_bell; else printf(" bell=%c (0x%x)", (c >= ' ' && c < 0x7f) ? c : ' ', c); return c; } if (seq[i] != 0x100 && seq[i] != mbr[ofs+i]) break; } } warn("bell not found"); return -1; } /* * Read in the MBR of the disk. If it is boot0, then use the version to * read in all of it if necessary. Use pointers to return a malloc'd * buffer containing the MBR and then return its size. */ static int read_mbr(const char *disk, u_int8_t **mbr, int check_version) { u_int8_t buf[MBRSIZE]; int mbr_size, fd; int ver; ssize_t n; if ((fd = open(disk, O_RDONLY)) == -1) err(1, "open %s", disk); if ((n = read(fd, buf, MBRSIZE)) == -1) err(1, "read %s", disk); if (n != MBRSIZE) errx(1, "%s: short read", disk); if (cv2(buf + OFF_MAGIC) != 0xaa55) errx(1, "%s: bad magic", disk); if (! (ver = boot0bs(buf))) { if (check_version) errx(1, "%s: unknown or incompatible boot code", disk); } else if (boot0version(buf) == 0x101) { mbr_size = 1024; if ((*mbr = malloc(mbr_size)) == NULL) errx(1, "%s: unable to allocate read buffer", disk); if (lseek(fd, 0, SEEK_SET) == -1 || (n = read(fd, *mbr, mbr_size)) == -1) err(1, "%s", disk); if (n != mbr_size) errx(1, "%s: short read", disk); close(fd); return (mbr_size); } *mbr = malloc(sizeof(buf)); + if (*mbr == NULL) + errx(1, "%s: unable to allocate MBR buffer", disk); memcpy(*mbr, buf, sizeof(buf)); close(fd); return sizeof(buf); } static int geom_class_available(const char *name) { struct gclass *class; struct gmesh mesh; int error; error = geom_gettree(&mesh); if (error != 0) errc(1, error, "Cannot get GEOM tree"); LIST_FOREACH(class, &mesh.lg_class, lg_class) { if (strcmp(class->lg_name, name) == 0) { geom_deletetree(&mesh); return (1); } } geom_deletetree(&mesh); return (0); } /* * Write out the mbr to the specified file. */ static void write_mbr(const char *fname, int flags, u_int8_t *mbr, int mbr_size) { struct gctl_req *grq; const char *errmsg; char *pname; ssize_t n; int fd; fd = open(fname, O_WRONLY | flags, 0666); if (fd != -1) { n = write(fd, mbr, mbr_size); close(fd); if (n != mbr_size) errx(1, "%s: short write", fname); return; } /* * If we're called to write to a backup file, don't try to * write through GEOM. */ if (flags != 0) err(1, "can't open file %s to write backup", fname); /* Try open it read only. */ fd = open(fname, O_RDONLY); if (fd == -1) { warn("error opening %s", fname); return; } pname = g_providername(fd); if (pname == NULL) { warn("error getting providername for %s", fname); return; } /* First check that GEOM_PART is available */ if (geom_class_available("PART") != 0) { grq = gctl_get_handle(); gctl_ro_param(grq, "class", -1, "PART"); gctl_ro_param(grq, "arg0", -1, pname); gctl_ro_param(grq, "verb", -1, "bootcode"); gctl_ro_param(grq, "bootcode", mbr_size, mbr); gctl_ro_param(grq, "flags", -1, "C"); errmsg = gctl_issue(grq); if (errmsg != NULL && errmsg[0] != '\0') errx(1, "GEOM_PART: write bootcode to %s failed: %s", fname, errmsg); gctl_free(grq); } else if (geom_class_available("MBR") != 0) { grq = gctl_get_handle(); gctl_ro_param(grq, "verb", -1, "write MBR"); gctl_ro_param(grq, "class", -1, "MBR"); gctl_ro_param(grq, "geom", -1, pname); gctl_ro_param(grq, "data", mbr_size, mbr); errmsg = gctl_issue(grq); if (errmsg != NULL) err(1, "GEOM_MBR: write MBR to %s failed", fname); gctl_free(grq); } else errx(1, "can't write MBR to %s", fname); free(pname); } /* * Outputs an informative dump of the data in the MBR to stdout. */ static void display_mbr(u_int8_t *mbr) { struct dos_partition *part; int i, version; part = (struct dos_partition *)(mbr + DOSPARTOFF); printf(fmt0); for (i = 0; i < NDOSPART; i++) if (part[i].dp_typ) printf(fmt1, 1 + i, part[i].dp_flag, part[i].dp_scyl + ((part[i].dp_ssect & 0xc0) << 2), part[i].dp_shd, part[i].dp_ssect & 0x3f, part[i].dp_typ, part[i].dp_ecyl + ((part[i].dp_esect & 0xc0) << 2), part[i].dp_ehd, part[i].dp_esect & 0x3f, part[i].dp_start, part[i].dp_size); printf("\n"); version = boot0version(mbr); printf("version=%d.%d drive=0x%x mask=0x%x ticks=%u", version >> 8, version & 0xff, mbr[OFF_DRIVE], mbr[OFF_FLAGS] & 0xf, cv2(mbr + OFF_TICKS)); set_bell(mbr, 0, 1); printf("\noptions="); for (i = 0; i < nopt; i++) { if (i) printf(","); if (!(mbr[OFF_FLAGS] & 1 << (7 - i)) ^ opttbl[i].def) printf("no"); printf("%s", opttbl[i].tok); } printf("\n"); if (b0_ver == 2) printf("volume serial ID %02x%02x-%02x%02x\n", mbr[OFF_SERIAL], mbr[OFF_SERIAL+1], mbr[OFF_SERIAL+2], mbr[OFF_SERIAL+3]); printf("default_selection=F%d (", mbr[OFF_OPT] + 1); if (mbr[OFF_OPT] < 4) printf("Slice %d", mbr[OFF_OPT] + 1); else if (mbr[OFF_OPT] == 4) printf("Drive 1"); else printf("PXE"); printf(")\n"); } /* * Return the boot0 version with the minor revision in the low byte, and * the major revision in the next higher byte. */ static int boot0version(const u_int8_t *bs) { /* Check for old version, and return 0x100 if found. */ int v = boot0bs(bs); if (v != 0) return v << 8; /* We have a newer boot0, so extract the version number and return it. */ return *(const int *)(bs + OFF_VERSION) & 0xffff; } /* descriptor of a pattern to match. * Start from the first entry trying to match the chunk of bytes, * if you hit an entry with len=0 terminate the search and report * off as the version. Otherwise skip to the next block after len=0 * An entry with len=0, off=0 is the end marker. */ struct byte_pattern { unsigned off; unsigned len; u_int8_t *key; }; /* * Decide if we have valid boot0 boot code by looking for * characteristic byte sequences at fixed offsets. */ static int boot0bs(const u_int8_t *bs) { /* the initial code sequence */ static u_int8_t id0[] = {0xfc, 0x31, 0xc0, 0x8e, 0xc0, 0x8e, 0xd8, 0x8e, 0xd0, 0xbc, 0x00, 0x7c }; /* the drive id */ static u_int8_t id1[] = {'D', 'r', 'i', 'v', 'e', ' '}; static struct byte_pattern patterns[] = { {0x0, sizeof(id0), id0}, {0x1b2, sizeof(id1), id1}, {1, 0, NULL}, {0x0, sizeof(id0), id0}, /* version with NT support */ {0x1ae, sizeof(id1), id1}, {2, 0, NULL}, {0, 0, NULL}, }; struct byte_pattern *p = patterns; for (; p->off || p->len; p++) { if (p->len == 0) break; if (!memcmp(bs + p->off, p->key, p->len)) /* match */ continue; while (p->len) /* skip to next block */ p++; } b0_ver = p->off; /* XXX ugly side effect */ return p->off; } /* * Adjust "and" and "or" masks for a -o option argument. */ static void stropt(const char *arg, int *xa, int *xo) { const char *q; char *s, *s1; int inv, i, x; if (!(s = strdup(arg))) err(1, NULL); for (s1 = s; (q = strtok(s1, ",")); s1 = NULL) { if ((inv = !strncmp(q, "no", 2))) q += 2; for (i = 0; i < nopt; i++) if (!strcmp(q, opttbl[i].tok)) break; if (i == nopt) errx(1, "%s: Unknown -o option", q); if (opttbl[i].def) inv ^= 1; x = 1 << (7 - i); if (inv) *xa &= ~x; else *xo |= x; } free(s); } /* * Convert and check an option argument. */ static int argtoi(const char *arg, int lo, int hi, int opt) { char *s; long x; errno = 0; x = strtol(arg, &s, 0); if (errno || !*arg || *s || x < lo || x > hi) errx(1, "%s: Bad argument to -%c option", arg, opt); return x; } /* * Display usage information. */ static void usage(void) { fprintf(stderr, "%s\n%s\n", "usage: boot0cfg [-Bv] [-b boot0] [-d drive] [-f file] [-m mask]", " [-o options] [-s slice] [-t ticks] disk"); exit(1); } Index: user/alc/PQ_LAUNDRY/usr.sbin/ypserv/Makefile.yp =================================================================== --- user/alc/PQ_LAUNDRY/usr.sbin/ypserv/Makefile.yp (revision 292448) +++ user/alc/PQ_LAUNDRY/usr.sbin/ypserv/Makefile.yp (revision 292449) @@ -1,691 +1,695 @@ # # Makefile for the NIS databases # # $FreeBSD$ # # This Makefile should only be run on the NIS master server of a domain. # All updated maps will be pushed to all NIS slave servers listed in the # /var/yp/ypservers file. Please make sure that the hostnames of all # NIS servers in your domain are listed in /var/yp/ypservers. # # This Makefile can be modified to support more NIS maps if desired. # # If this machine is an NIS master, reset this variable (NOPUSH=) # in Makefile.local so that changes to the NIS maps can be propagated to # the slave servers. (By default we assume that we are only serving a # small domain with only one server.) # NOPUSH = "True" # If this machine does not wish to generate a linux-style shadow map # from the master.passwd file, reset this variable (SHADOW=) in # Makefile.local. SHADOW = "True" # If you want to use a FreeBSD NIS server to serve non-FreeBSD clients # (i.e. clients who expect the password field in the passwd maps to be # valid) then set this variable (UNSECURE="True") in Makefile.local. # This will cause $YPDIR/passwd to be generated with valid password # fields. This is insecure: FreeBSD normally only serves the # master.passwd and shadow maps (which have real encrypted passwords # in them) to the superuser on other FreeBSD machines, but non-FreeBSD # clients (e.g. SunOS, Solaris (without NIS+), IRIX, HP-UX, etc...) # will only work properly in 'unsecure' mode. # #UNSECURE = "True" # The following line encodes the YP_INTERDOMAIN key into the hosts.byname # and hosts.byaddr maps so that ypserv(8) will do DNS lookups to resolve # hosts not in the current domain. Resetting this variable in # Makefile.local (B=) will disable the DNS lookups. B=-b # Normally, the master.passwd.* and shadow.* maps are guarded against access # from non-privileged users. By resetting S in Makefile.local (S=), the # YP_SECURE key will be removed from these maps, allowing anyone to access # them. S=-s # These are commands which this Makefile needs to properly rebuild the # NIS databases. Don't change these unless you have a good reason. Also # be sure not to place an @ in front of /usr/bin/awk: it isn't necessary # and it'll break everything in sight. # AWK = /usr/bin/awk RM = @/bin/rm -f MV = @/bin/mv -f RMV = /bin/mv -f MKDB = /usr/sbin/yp_mkdb DBLOAD = $(MKDB) -m `hostname` MKNETID = /usr/libexec/mknetid NEWALIASES = /usr/bin/newaliases YPPUSH = /usr/sbin/yppush .if !defined(UPDATE_DOMAIN) DOMAIN = `/bin/domainname` .else DOMAIN = $(UPDATE_DOMAIN) .endif REVNETGROUP = /usr/libexec/revnetgroup TMP = `echo $@.$$$$` # It is advisable to create a separate directory to contain the # source files used to generate your NIS maps. If you intend to # support multiple domains, something like /src/dir/$DOMAIN # would work well. YPSRCDIR = /etc .if !defined(YP_DIR) YPDIR = /var/yp .else YPDIR = $(YP_DIR) .endif YPMAPDIR = $(YPDIR)/$(DOMAIN) # These are the files from which the NIS databases are built. You may edit # these to taste in the event that you wish to keep your NIS source files # separate from your NIS server's actual configuration files. Note that the # NIS passwd and master.passwd files are stored in /var/yp: the server's # real password database is not used by default. However, you may use # the real /etc/passwd and /etc/master.passwd files by: # # # - invoking yppasswdd with `-t /etc/master.passwd' (yppasswdd will do a # 'pwd_mkdb' as needed if /etc/master.passwd is thus specified). # - Specifying the location of the master.passwd file using the # MASTER_PASSWD variable, i.e.: # # # make MASTER_PASSWD=/path/to/some/other/master.passwd # # - (optionally): editing this Makefile to change the default location. # # To add a user, edit $(YPDIR)/master.passwd and type 'make'. The raw # passwd file will be generated from the master.passwd file automagically. # ETHERS = $(YPSRCDIR)/ethers # ethernet addresses (for rarpd) EUI64 = $(YPSRCDIR)/eui64 # eui64 addresses (for firewire) BOOTPARAMS= $(YPSRCDIR)/bootparams # for booting Sun boxes (bootparamd) HOSTS = $(YPSRCDIR)/hosts IPNODES = $(YPDIR)/ipnodes NETWORKS = $(YPSRCDIR)/networks PROTOCOLS = $(YPSRCDIR)/protocols RPC = $(YPSRCDIR)/rpc SERVICES = $(YPSRCDIR)/services SHELLS = $(YPSRCDIR)/shells GROUP = $(YPSRCDIR)/group ALIASES = $(YPSRCDIR)/mail/aliases NETGROUP = $(YPDIR)/netgroup PASSWD = $(YPDIR)/passwd .if !defined(MASTER_PASSWD) MASTER = $(YPDIR)/master.passwd .else MASTER = $(MASTER_PASSWD) .endif YPSERVERS = $(YPDIR)/ypservers # List of all NIS servers for a domain PUBLICKEY = $(YPSRCDIR)/publickey NETID = $(YPSRCDIR)/netid AMDHOST = $(YPSRCDIR)/amd.map target: @if [ ! -d $(DOMAIN) ]; then mkdir $(DOMAIN); fi; \ cd $(DOMAIN) ; echo "NIS Map update started on `date` for domain $(DOMAIN)" ; \ make -f ../Makefile all; echo "NIS Map update completed." # Read overrides. Note, the current directory will be /var/yp/ # when 'all' is built. .if exists(${YPDIR}/Makefile.local) .include "${YPDIR}/Makefile.local" .endif # List of maps that are always built. # If you want to omit some of them, feel free to comment # them out from this list. TARGETS= servers hosts networks protocols rpc services shells group +TARGETS+= ipnodes #TARGETS+= aliases # Sanity checks: filter out targets we can't build # Note that we don't build the ethers, eui64, or boorparams maps by default # since /etc/ethers, /etc/eui64 and /etc/bootparams are not likely to be present # on all systems. .if exists($(ETHERS)) TARGETS+= ethers .else ETHERS= /dev/null .endif .if exists($(EUI64)) TARGETS+= eui64 .else EUI64= /dev/null .endif .if exists($(BOOTPARAMS)) TARGETS+= bootparams .else BOOTPARAMS= /dev/null .endif .if exists($(NETGROUP)) TARGETS+= netgrp .else NETGROUP= /dev/null .endif .if exists($(MASTER)) TARGETS+= passwd master.passwd netid .if ${SHADOW} == "\"True\"" TARGETS+= shadow .endif .else MASTER= /dev/null TARGETS+= nopass .endif .if exists($(PUBLICKEY)) TARGETS+= publickey .else PUBLICKEY= /dev/null .endif .if exists($(AMDHOST)) TARGETS+= amd.map .else AMDHOST= /dev/null .endif -.if exists($(IPNODES)) -TARGETS+= ipnodes -.else -IPNODES= /dev/null +.if !exists($(IPNODES)) +IPNODES= $(HOSTS) .endif all: $(TARGETS) ethers: ethers.byname ethers.byaddr eui64: eui64.byname eui64.byid bootparam: bootparams hosts: hosts.byname hosts.byaddr ipnodes: ipnodes.byname ipnodes.byaddr networks: networks.byaddr networks.byname protocols: protocols.bynumber protocols.byname rpc: rpc.byname rpc.bynumber services: services.byname passwd: passwd.byname passwd.byuid shadow: shadow.byname shadow.byuid group: group.byname group.bygid netgrp: netgroup netid: netid.byname servers: ypservers publickey: publickey.byname aliases: mail.aliases master.passwd: master.passwd.byname master.passwd.byuid # # This is a special target used only when doing in-place updates with # rpc.yppasswdd. In this case, the maps will be updated by the rpc.yppasswdd # server and won't need to be remade. They will have to be pushed to the # slaves however. Calling this target implicitly insures that this will # happen. # pushpw: @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) master.passwd.byname ; fi @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) master.passwd.byuid ; fi .if ${SHADOW} == "\"True\"" @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) shadow.byname ; fi @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) shadow.byuid ; fi .endif @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) passwd.byname ; fi @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) passwd.byuid ; fi pushmap: @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $(PUSHMAP) ; fi nopass: @echo "" @echo " ********WARNING********" @echo " Couldn't find the master.passwd source file. This file" @echo " is needed to generate the master.passwd and passwd maps." @echo " The default location is /var/yp/master.passwd. You should" @echo " edit /var/yp/Makefile and set the MASTER variable to point" @echo " to the source file you wish to use for building the passwd" @echo " maps, or else invoke make(1) in the following manner:" @echo "" @echo " make MASTER_PASSWD=/path/to/master.passwd" @echo "" mail.aliases: $(ALIASES) @echo "Updating $@..." @$(NEWALIASES) -oA$(ALIASES) @$(MKDB) -u $(ALIASES).db \ | $(DBLOAD) -i $(ALIASES) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi ypservers: $(YPSERVERS) @echo "Updating $@..." @$(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*") print $$0"\t"$$0 }' \ $(YPSERVERS) \ | $(DBLOAD) -i $(YPSERVERS) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi ethers.byname: $(ETHERS) @echo "Updating $@..." .if ${ETHERS} == "/dev/null" @echo "Ethers source file not found -- skipping" .else @$(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$2"\t"$$0 }' $(ETHERS) | $(DBLOAD) -i $(ETHERS) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi .endif ethers.byaddr: $(ETHERS) @echo "Updating $@..." .if ${ETHERS} == "/dev/null" @echo "Ethers source file not found -- skipping" .else @$(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$1"\t"$$0 }' $(ETHERS) | $(DBLOAD) -i $(ETHERS) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi .endif eui64.byname: $(EUI64) @echo "Updating $@..." .if ${EUI64} == "/dev/null" @echo "EUI64 source file not found -- skipping" .else @$(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$2"\t"$$0 }' $(EUI64) | $(DBLOAD) -i $(EUI64) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi .endif eui64.byid: $(EUI64) @echo "Updating $@..." .if ${EUI64} == "/dev/null" @echo "EUI64 source file not found -- skipping" .else @$(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$1"\t"$$0 }' $(EUI64) | $(DBLOAD) -i $(EUI64) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi .endif bootparams: $(BOOTPARAMS) @echo "Updating $@..." .if ${BOOTPARAMS} == "/dev/null" @echo "Bootparams source file not found -- skipping" .else @$(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$0 }' $(BOOTPARAMS) | $(DBLOAD) -i $(BOOTPARAMS) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi .endif netgroup: $(NETGROUP) netgroup.byhost netgroup.byuser @echo "Updating $@..." .if ${NETGROUP} == "/dev/null" @echo "Netgroup source file not found -- skipping" .else @$(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$0 }' $(NETGROUP) | $(DBLOAD) -i $(NETGROUP) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi .endif netgroup.byhost: $(NETGROUP) @echo "Updating $@..." .if ${NETGROUP} == "/dev/null" @echo "Netgroup source file not found -- skipping" .else @$(REVNETGROUP) -h -f $(NETGROUP) | \ $(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$0 }' | $(DBLOAD) -i $(NETGROUP) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi .endif netgroup.byuser: $(NETGROUP) @echo "Updating $@..." .if ${NETGROUP} == "/dev/null" @echo "Netgroup source file not found -- skipping" .else @$(REVNETGROUP) -u -f $(NETGROUP) | \ $(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$0 }' | $(DBLOAD) -i $(NETGROUP) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi .endif +# Solaris 8 does the following: +# - /etc/hosts and hosts.{byname,byaddr} are IPv4 only. +# - /etc/inet/ipnodes and ipnodes.{byname,byaddr} are used for protocol +# independent name-to-address mapping. +# +# For local name resolution, we made /etc/hosts protocol independent. +# For NIS name resolution, we obey Solaris 8 practice. +# - We keep hosts.{byname,byaddr} IPv4 only, to be friendly with Solaris 8 +# clients. +# - ipnodes.{byname,byaddr} is used for protocol independent mapping. +# We generate all the mappings from /etc/hosts unless /var/yp/ipnodes +# exists, for compatibility with FreeBSD local name resolution. +# hosts.byname: $(HOSTS) @echo "Updating $@..." - @$(AWK) '/^[0-9]/ { for (n=2; n<=NF && $$n !~ "^#.*"; n++) \ + @$(AWK) '/^[0-9.]+[\t ]/ { for (n=2; n<=NF && $$n !~ "^#.*"; n++) \ print $$n"\t"$$0 }' $(HOSTS) | $(DBLOAD) ${B} -i $(HOSTS) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi hosts.byaddr: $(HOSTS) @echo "Updating $@..." - @$(AWK) '$$1 !~ "^#.*" { print $$1"\t"$$0 }' $(HOSTS) \ + @$(AWK) '/^[0-9.]+[\t ]/ { print $$1"\t"$$0 }' $(HOSTS) \ | $(DBLOAD) ${B} -i $(HOSTS) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi ipnodes.byname: $(IPNODES) @echo "Updating $@..." -.if ${IPNODES} == "/dev/null" - @echo "Ipnodes source file not found -- skipping" -.else @$(AWK) '/^[0-9a-fA-F:]/ { for (n=2; n<=NF && $$n !~ "^#.*"; n++) \ print $$n"\t"$$0 }' $(IPNODES) | $(DBLOAD) ${B} -i $(IPNODES) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi -.endif ipnodes.byaddr: $(IPNODES) @echo "Updating $@..." -.if ${IPNODES} == "/dev/null" - @echo "Ipnodes source file not found -- skipping" -.else @$(AWK) '$$1 !~ "^#.*" { print $$1"\t"$$0 }' $(IPNODES) \ | $(DBLOAD) ${B} -i $(IPNODES) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi -.endif networks.byname: $(NETWORKS) @echo "Updating $@..." @$(AWK) \ '$$1 !~ "^#.*" { print $$1"\t"$$0; \ for (n=3; n<=NF && $$n !~ "^#.*"; n++) \ print $$n"\t"$$0 \ }' $(NETWORKS) \ | $(DBLOAD) -i $(NETWORKS) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi networks.byaddr: $(NETWORKS) @echo "Updating $@..." @$(AWK) '$$1 !~ "^#.*" { print $$2"\t"$$0 }' $(NETWORKS) \ | $(DBLOAD) -i $(NETWORKS) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi protocols.byname: $(PROTOCOLS) @echo "Updating $@..." @$(AWK) \ '$$1 !~ "^#.*" { print $$1"\t"$$0; \ for (n=3; n<=NF && $$n !~ "^#.*"; n++) \ print $$n"\t"$$0 \ }' $(PROTOCOLS) | $(DBLOAD) -i $(PROTOCOLS) \ -o $(YPMAPDIR)/$@ - $(TMP); $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi protocols.bynumber: $(PROTOCOLS) @echo "Updating $@..." @$(AWK) '$$1 !~ "^#.*" { print $$2"\t"$$0 }' $(PROTOCOLS) \ | $(DBLOAD) -i $(PROTOCOLS) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi rpc.byname: $(RPC) @echo "Updating $@..." @$(AWK) \ '$$1 !~ "^#.*" { print $$1"\t"$$0; \ for (n=3; n<=NF && $$n !~ "^#.*"; n++) \ print $$n"\t"$$0 \ }' $(RPC) | $(DBLOAD) -i $(RPC) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi rpc.bynumber: $(RPC) @echo "Updating $@..." @$(AWK) '$$1 !~ "^#.*" { print $$2"\t"$$0 }' $(RPC) \ | $(DBLOAD) -i $(RPC) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi services.byname: $(SERVICES) @echo "Updating $@..." @$(AWK) \ '$$1 !~ "^#.*" { for (n=1; n<=NF && $$n !~ "^#.*"; n++) { \ if (split($$2, t, "/")) { \ printf("%s/%s", $$n, t[2]) }; \ print "\t"$$0; \ if (n == 1) n = 2; \ } ; print $$2"\t"$$0 ; \ }' $(SERVICES) \ | $(DBLOAD) -i $(SERVICES) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi shells: $(SHELLS) @echo "Updating $@..." @$(AWK) '{ if ($$1 != "" && $$1 !~ "^#.*") print $$0"\t"$$0 }' \ $(SHELLS) \ | $(DBLOAD) -i $(SHELLS) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi publickey.byname: $(PUBLICKEY) @echo "Updating $@..." .if ${PUBLICKEY} == "/dev/null" @echo "Publickey source file not found -- skipping" .else @$(AWK) '$$1 !~ "^#.*" { print $$1"\t"$$2 }' $(PUBLICKEY) \ | $(DBLOAD) -i $(PUBLICKEY) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi .endif $(PASSWD): $(MASTER) @echo "Creating new $@ file from $(MASTER)..." @if [ ! $(UNSECURE) ]; then \ $(AWK) -F: '{if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$1":*:"$$3":"$$4":"$$8":"$$9":"$$10}' $(MASTER) \ > $(PASSWD) ; \ else \ $(AWK) -F: '{if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$1":"$$2":"$$3":"$$4":"$$8":"$$9":"$$10}' $(MASTER) \ > $(PASSWD) ; fi passwd.byname: $(PASSWD) @echo "Updating $@..." @$(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$1"\t"$$0 }' $(PASSWD) \ | $(DBLOAD) -f -i $(PASSWD) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi passwd.byuid: $(PASSWD) @echo "Updating $@..." @$(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$3"\t"$$0 }' $(PASSWD) \ | $(DBLOAD) -f -i $(PASSWD) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi group.byname: $(GROUP) @echo "Updating $@..." @$(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$1"\t"$$0 }' $(GROUP) \ | $(DBLOAD) -f -i $(GROUP) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi group.bygid: $(GROUP) @echo "Updating $@..." @$(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$3"\t"$$0 }' $(GROUP) \ | $(DBLOAD) -f -i $(GROUP) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi netid.byname: $(GROUP) $(PASSWD) $(HOSTS) @echo "Updating $@..." @$(MKNETID) -q -p $(PASSWD) -g $(GROUP) -h $(HOSTS) -n $(NETID) \ -d $(DOMAIN) | $(DBLOAD) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi master.passwd.byname: $(MASTER) @echo "Updating $@..." .if ${MASTER} == "/dev/null" @echo "Master.passwd source file not found -- skipping" .else @$(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$1"\t"$$0 }' $(MASTER) \ | $(DBLOAD) ${S} -f -i $(MASTER) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi .endif master.passwd.byuid: $(MASTER) @echo "Updating $@..." .if ${MASTER} == "/dev/null" @echo "Master.passwd source file not found -- skipping" .else @$(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$3"\t"$$0 }' $(MASTER) \ | $(DBLOAD) ${S} -f -i $(MASTER) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi .endif shadow.byname: $(MASTER) @echo "Updating $@..." .if ${MASTER} == "/dev/null" @echo "Master.passwd source file not found -- skipping" .else @$(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$1"\t"$$1":"$$2":12000:0:99999:7:::" }' $(MASTER) \ | sed 's/\( [^:]*:\)\*:/\1!:/' \ | $(DBLOAD) ${S} -f -i $(PASSWD) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi .endif shadow.byuid: $(MASTER) @echo "Updating $@..." .if ${MASTER} == "/dev/null" @echo "Master.passwd source file not found -- skipping" .else @$(AWK) -F: '{ if ($$1 != "" && $$1 !~ "^#.*" && $$1 != "+") \ print $$3"\t"$$1":"$$2":12000:0:99999:7:::" }' $(MASTER) \ | sed 's/\( [^:]*:\)\*:/\1!:/' \ | $(DBLOAD) ${S} -f -i $(PASSWD) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi .endif amd.map: $(AMDHOST) @echo "Updating $@..." @$(AWK) '$$1 !~ "^#.*" { \ for (i = 1; i <= NF; i++) \ if (i == NF) { \ if (substr($$i, length($$i), 1) == "\\") \ printf("%s", substr($$i, 1, length($$i) - 1)); \ else \ printf("%s\n", $$i); \ } \ else \ printf("%s ", $$i); \ }' $(AMDHOST) | \ $(DBLOAD) -i $(AMDHOST) -o $(YPMAPDIR)/$@ - $(TMP); \ $(RMV) $(TMP) $@ @$(DBLOAD) -c @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi Index: user/alc/PQ_LAUNDRY =================================================================== --- user/alc/PQ_LAUNDRY (revision 292448) +++ user/alc/PQ_LAUNDRY (revision 292449) Property changes on: user/alc/PQ_LAUNDRY ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r292390-292448