diff --git a/.gitignore b/.gitignore index 7964e136..f73526b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,59 +1,57 @@ *.o *.a *.la *.lo *.pc *.tar.* *.sha256* stamp-h1 Makefile.in Makefile .deps .libs .version .dirstamp # build-aux/release.mk related litter /.tarball-version /tag-* aclocal.m4 autoconf autoheader autom4te.cache automake compile config.* configure* debian/changelog debian/kronosnetd.postinst debian/patches depcomp install-sh libtoolize ltmain.sh m4/libtool.m4 m4/lt~obsolete.m4 m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 missing libtool autoscan.log init/kronosnetd init/kronosnetd.service kronosnetd/kronosnetd kronosnetd/knet-keygen kronosnetd/kronosnetd.logrotate kronosnet.spec -libknet/compress_canary -libknet/crypto_canary *.swp *_test *_bench test-driver *.trs *.log Doxyfile doxyfile.stamp xml/ diff --git a/Makefile.am b/Makefile.am index 2ab43647..858a3186 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,184 +1,184 @@ # # Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. # # Author: Fabio M. Di Nitto # # This software licensed under GPL-2.0+, LGPL-2.0+ # MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure depcomp \ config.guess config.sub missing install-sh \ ltmain.sh compile config.h.in config.h.in~ \ autoscan.log configure.scan test-driver \ m4/libtool.m4 m4/lt~obsolete.m4 m4/ltoptions.m4 \ m4/ltsugar.m4 m4/ltversion.m4 include $(top_srcdir)/build-aux/check.mk AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 SPEC = $(PACKAGE_NAME).spec TARGZFILE = $(PACKAGE_NAME)-$(VERSION).tar.gz EXTRA_DIST = build-aux autogen.sh .version \ NOTES_TO_PACKAGE_MAINTAINERS \ $(SPEC).in SUBDIRS = init libtap libknet kronosnetd if BUILD_POC SUBDIRS += poc-code endif dist_doc_DATA = \ COPYING.applications \ COPYING.libraries \ COPYRIGHT \ README.licence \ README all-local: $(SPEC) clean-local: rm -f $(SPEC) distclean-local: rm -f $(PACKAGE_NAME)-*.tar.* $(PACKAGE_NAME)-*.sha256* tag-* ## make rpm/srpm section. $(SPEC): $(SPEC).in .version config.status rm -f $@-t $@ date="`LC_ALL=C date "+%a %b %d %Y"`" && \ if [ -f $(abs_srcdir)/.tarball-version ]; then \ gitver="`cat $(abs_srcdir)/.tarball-version`" && \ rpmver=$$gitver && \ alphatag="" && \ dirty="" && \ numcomm="0"; \ else \ gitver="`GIT_DIR=$(abs_srcdir)/.git git describe --abbrev=4 --match='v*' HEAD 2>/dev/null`" && \ rpmver=`echo $$gitver | sed -e "s/^v//" -e "s/-.*//g"` && \ alphatag=`echo $$gitver | sed -e "s/.*-//" -e "s/^g//"` && \ vtag=`echo $$gitver | sed -e "s/-.*//g"` && \ numcomm=`GIT_DIR=$(abs_srcdir)/.git git rev-list $$vtag..HEAD | wc -l` && \ cd $(abs_srcdir) && \ git update-index --refresh > /dev/null 2>&1 || true && \ dirty=`git diff-index --name-only HEAD 2>/dev/null` && cd - 2>/dev/null; \ fi && \ if [ -n "$$dirty" ]; then dirty="dirty"; else dirty=""; fi && \ if [ "$$numcomm" = "0" ]; then \ sed \ -e "s#@version@#$$rpmver#g" \ -e "s#%glo.*alpha.*##g" \ -e "s#%glo.*numcomm.*##g" \ -e "s#@dirty@#$$dirty#g" \ -e "s#@date@#$$date#g" \ $(abs_srcdir)/$@.in > $@-t; \ else \ sed \ -e "s#@version@#$$rpmver#g" \ -e "s#@alphatag@#$$alphatag#g" \ -e "s#@numcomm@#$$numcomm#g" \ -e "s#@dirty@#$$dirty#g" \ -e "s#@date@#$$date#g" \ $(abs_srcdir)/$@.in > $@-t; \ fi; \ if [ -z "$$dirty" ]; then sed -i -e "s#%glo.*dirty.*##g" $@-t; fi if BUILDSCTP sed -i -e "s#@sctp@#bcond_without#g" $@-t else sed -i -e "s#@sctp@#bcond_with#g" $@-t endif -if BUILDCRYPTONSS +if BUILD_CRYPTO_NSS sed -i -e "s#@nss@#bcond_without#g" $@-t else sed -i -e "s#@nss@#bcond_with#g" $@-t endif -if BUILDCRYPTOOPENSSL +if BUILD_CRYPTO_OPENSSL sed -i -e "s#@openssl@#bcond_without#g" $@-t else sed -i -e "s#@openssl@#bcond_with#g" $@-t endif -if BUILDCOMPZLIB +if BUILD_COMPRESS_ZLIB sed -i -e "s#@zlib@#bcond_without#g" $@-t else sed -i -e "s#@zlib@#bcond_with#g" $@-t endif -if BUILDCOMPLZ4 +if BUILD_COMPRESS_LZ4 sed -i -e "s#@lz4@#bcond_without#g" $@-t else sed -i -e "s#@lz4@#bcond_with#g" $@-t endif -if BUILDCOMPLZO2 +if BUILD_COMPRESS_LZO2 sed -i -e "s#@lzo2@#bcond_without#g" $@-t else sed -i -e "s#@lzo2@#bcond_with#g" $@-t endif -if BUILDCOMPLZMA +if BUILD_COMPRESS_LZMA sed -i -e "s#@lzma@#bcond_without#g" $@-t else sed -i -e "s#@lzma@#bcond_with#g" $@-t endif -if BUILDCOMPBZIP2 +if BUILD_COMPRESS_BZIP2 sed -i -e "s#@bzip2@#bcond_without#g" $@-t else sed -i -e "s#@bzip2@#bcond_with#g" $@-t endif if BUILD_KRONOSNETD sed -i -e "s#@kronosnetd@#bcond_without#g" $@-t else sed -i -e "s#@kronosnetd@#bcond_with#g" $@-t endif if BUILD_LIBTAP sed -i -e "s#@libtap@#bcond_without#g" $@-t else sed -i -e "s#@libtap@#bcond_with#g" $@-t endif if BUILD_RUNAUTOGEN sed -i -e "s#@runautogen@#bcond_without#g" $@-t else sed -i -e "s#@runautogen@#bcond_with#g" $@-t endif sed -i -e "s#@defaultadmgroup@#$(DEFAULTADMGROUP)#g" $@-t chmod a-w $@-t mv $@-t $@ rm -f $@-t* $(TARGZFILE): $(MAKE) dist RPMBUILDOPTS = --define "_sourcedir $(abs_builddir)" \ --define "_specdir $(abs_builddir)" \ --define "_builddir $(abs_builddir)" \ --define "_srcrpmdir $(abs_builddir)" \ --define "_rpmdir $(abs_builddir)" srpm: clean $(MAKE) $(SPEC) $(TARGZFILE) rpmbuild $(RPMBUILDOPTS) --nodeps -bs $(SPEC) rpm: clean $(MAKE) $(SPEC) $(TARGZFILE) rpmbuild $(RPMBUILDOPTS) -ba $(SPEC) # release/versioning BUILT_SOURCES = .version .version: echo $(VERSION) > $@-t && mv $@-t $@ dist-hook: gen-ChangeLog echo $(VERSION) > $(distdir)/.tarball-version gen_start_date = 2000-01-01 .PHONY: gen-ChangeLog gen-ChangeLog: if test -d $(abs_sourcedir)/.git; then \ LC_ALL=C $(top_srcdir)/build-aux/gitlog-to-changelog \ --since=$(gen_start_date) > $(distdir)/cl-t; \ rm -f $(distdir)/ChangeLog; \ mv $(distdir)/cl-t $(distdir)/ChangeLog; \ fi diff --git a/build-aux/knet_valgrind_memcheck.supp b/build-aux/knet_valgrind_memcheck.supp index f0c7343a..de0d2188 100644 --- a/build-aux/knet_valgrind_memcheck.supp +++ b/build-aux/knet_valgrind_memcheck.supp @@ -1,543 +1,543 @@ { lzma internal stuff Memcheck:Cond fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 fun:lzma_stream_header_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:lzma_crc32 fun:lzma_stream_header_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 fun:lzma_crc32 fun:lzma_stream_header_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 fun:lzma_block_header_encode obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:is_overlap fun:memcpy@@GLIBC_2.14 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread } { lzma internal stuff Memcheck:Cond fun:memcpy@@GLIBC_2.14 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread } { lzma internal stuff Memcheck:Value8 fun:memcpy@@GLIBC_2.14 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread } { lzma internal stuff Memcheck:Value8 fun:lzma_vli_encode fun:lzma_filter_flags_encode fun:lzma_block_header_encode obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_filter_flags_encode fun:lzma_block_header_encode obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:memset fun:lzma_block_header_encode obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 fun:memset fun:lzma_block_header_encode obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:lzma_block_unpadded_size fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:lzma_index_append fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:lzma_vli_size fun:lzma_index_append fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:lzma_index_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_index_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_index_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:lzma_vli_encode obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_index_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 fun:lzma_vli_encode obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_index_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:lzma_crc32 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_index_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 fun:lzma_crc32 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_index_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 fun:lzma_stream_footer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 fun:lzma_crc32 fun:lzma_stream_footer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:lzma_crc32 fun:lzma_stream_footer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread } { lzma internal stuff (Debian Unstable) Memcheck:Cond obj:/lib/x86_64-linux-gnu/liblzma.so.5.2.2 obj:/lib/x86_64-linux-gnu/liblzma.so.5.2.2 obj:/lib/x86_64-linux-gnu/liblzma.so.5.2.2 obj:/lib/x86_64-linux-gnu/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread } { lzma internal stuff (Ubuntu 17.10 i386) Memcheck:Cond obj:/lib/i386-linux-gnu/liblzma.so.5.2.2 obj:/lib/i386-linux-gnu/liblzma.so.5.2.2 obj:/lib/i386-linux-gnu/liblzma.so.5.2.2 obj:/lib/i386-linux-gnu/liblzma.so.5.2.2 obj:/lib/i386-linux-gnu/liblzma.so.5.2.2 obj:/lib/i386-linux-gnu/liblzma.so.5.2.2 fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread } { lzma internal stuff (Ubuntu 17.10 i386) Memcheck:Cond obj:/lib/i386-linux-gnu/liblzma.so.5.2.2 obj:/lib/i386-linux-gnu/liblzma.so.5.2.2 obj:/lib/i386-linux-gnu/liblzma.so.5.2.2 obj:/lib/i386-linux-gnu/liblzma.so.5.2.2 obj:/lib/i386-linux-gnu/liblzma.so.5.2.2 obj:/lib/i386-linux-gnu/liblzma.so.5.2.2 fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread } { nss internal stuff (FreeBSD 11.1) Memcheck:Addr8 obj:/libexec/ld-elf.so.1 obj:/libexec/ld-elf.so.1 obj:/libexec/ld-elf.so.1 obj:/libexec/ld-elf.so.1 obj:/libexec/ld-elf.so.1 obj:/libexec/ld-elf.so.1 fun:PR_LoadLibraryWithFlags obj:/usr/local/lib/nss/libnssutil3.so fun:PORT_LoadLibraryFromOrigin obj:/usr/local/lib/nss/libnss3.so fun:PR_CallOnce obj:/usr/local/lib/nss/libnss3.so } { nss internal stuff (FreeBSD 11.1) Memcheck:Addr8 obj:/libexec/ld-elf.so.1 obj:/libexec/ld-elf.so.1 obj:/libexec/ld-elf.so.1 obj:/libexec/ld-elf.so.1 fun:PR_LoadLibraryWithFlags obj:/usr/local/lib/nss/libnssutil3.so fun:PORT_LoadLibraryFromOrigin obj:/usr/local/lib/nss/libnss3.so fun:PR_CallOnce obj:/usr/local/lib/nss/libnss3.so fun:SECMOD_LoadModule obj:/usr/local/lib/nss/libnss3.so } { nss internal stuff (FreeBSD 11.1) Memcheck:Addr8 obj:/libexec/ld-elf.so.1 obj:/libexec/ld-elf.so.1 obj:/libexec/ld-elf.so.1 obj:/libexec/ld-elf.so.1 obj:/usr/local/lib/libcrypto.so.10 fun:DSO_load fun:DSO_dsobyaddr obj:/usr/local/lib/libcrypto.so.10 fun:pthread_once fun:CRYPTO_THREAD_run_once fun:OPENSSL_init_crypto - fun:opensslcrypto_load_lib + fun:opensslcrypto_init } diff --git a/configure.ac b/configure.ac index 4d050c82..cc5b769f 100644 --- a/configure.ac +++ b/configure.ac @@ -1,521 +1,458 @@ # # Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. # # Authors: Fabio M. Di Nitto # Federico Simoncelli # # This software licensed under GPL-2.0+, LGPL-2.0+ # # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. # AC_PREREQ([2.63]) AC_INIT([kronosnet], m4_esyscmd([build-aux/git-version-gen .tarball-version]), [devel@lists.kronosnet.org]) AC_USE_SYSTEM_EXTENSIONS AM_INIT_AUTOMAKE([1.13 dist-bzip2 dist-xz color-tests -Wno-portability subdir-objects]) LT_PREREQ([2.2.6]) LT_INIT AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([kronosnetd/main.c]) AC_CONFIG_HEADERS([config.h]) AC_CANONICAL_HOST AC_PROG_LIBTOOL AC_LANG([C]) systemddir=${prefix}/lib/systemd/system if test "$prefix" = "NONE"; then prefix="/usr" if test "$localstatedir" = "\${prefix}/var"; then localstatedir="/var" fi if test "$sysconfdir" = "\${prefix}/etc"; then sysconfdir="/etc" fi if test "$systemddir" = "NONE/lib/systemd/system"; then systemddir=/lib/systemd/system fi if test "$libdir" = "\${exec_prefix}/lib"; then if test -e /usr/lib64; then libdir="/usr/lib64" else libdir="/usr/lib" fi fi fi AC_PROG_AWK AC_PROG_GREP AC_PROG_SED AC_PROG_CPP AC_PROG_CC AC_PROG_CC_C99 if test "x$ac_cv_prog_cc_c99" = "xno"; then AC_MSG_ERROR(["C99 support is required"]) fi AC_PROG_LN_S AC_PROG_INSTALL AC_PROG_MAKE_SET PKG_PROG_PKG_CONFIG AC_CHECK_PROGS([DOXYGEN], [doxygen]) AC_CHECK_PROGS([DOXY2MAN], [doxy2man]) manpageupdates=1 if test "x$DOXYGEN" = "x" || test "x$DOXY2MAN" = "x"; then manpageupdates=0; fi AM_CONDITIONAL([MANPAGEUPDATES], [test $manpageupdates -gt 0]) AC_CHECK_PROGS([VALGRIND_EXEC], [valgrind]) AM_CONDITIONAL([HAS_VALGRIND], [test x$VALGRIND_EXEC != "x"]) +# KNET_OPTION_DEFINES(stem,type,detection code) +# stem: enters name of option, Automake conditional and preprocessor define +# type: compress or crypto, determines where the default comes from +AC_DEFUN([KNET_OPTION_DEFINES],[ +AC_ARG_ENABLE([$2-$1],[AS_HELP_STRING([--disable-$2-$1],[disable libknet $1 support])],, + [enable_$2_$1="$enable_$2_all"]) +AM_CONDITIONAL([BUILD_]m4_toupper([$2_$1]),[test "x$enable_$2_$1" = xyes]) +if test "x$enable_$2_$1" = xyes; then + $3 +fi +AC_DEFINE_UNQUOTED([WITH_]m4_toupper([$2_$1]), [`test "x$enable_$2_$1" != xyes; echo $?`], $1 $2 [built in]) +]) + AC_ARG_ENABLE([libknet-sctp], - [ --disable-libknet-sctp : disable libknet SCTP support ],, + [AS_HELP_STRING([--disable-libknet-sctp],[disable libknet SCTP support])],, [ enable_libknet_sctp="yes" ]) AM_CONDITIONAL([BUILDSCTP], [test x$enable_libknet_sctp = xyes]) AC_ARG_ENABLE([crypto-all], - [ --disable-crypto-all : disable libknet all crypto modules support ],, + [AS_HELP_STRING([--disable-crypto-all],[disable libknet all crypto modules support])],, [ enable_crypto_all="yes" ]) -AC_ARG_ENABLE([crypto-nss], - [ --disable-crypto-nss : disable libknet nss support ],, - [ enable_crypto_nss="$enable_crypto_all" ]) -AM_CONDITIONAL([BUILDCRYPTONSS], [test x$enable_crypto_nss = xyes]) - -AC_ARG_ENABLE([crypto-openssl], - [ --disable-crypto-openssl : disable libknet openssl support ],, - [ enable_crypto_openssl="$enable_crypto_all" ]) -AM_CONDITIONAL([BUILDCRYPTOOPENSSL], [test x$enable_crypto_openssl = xyes]) +KNET_OPTION_DEFINES([nss],[crypto],[PKG_CHECK_MODULES([nss], [nss])]) +KNET_OPTION_DEFINES([openssl],[crypto],[ + PKG_CHECK_MODULES([openssl],[libcrypto < 1.1], + [AC_DEFINE_UNQUOTED([BUILDCRYPTOOPENSSL10], [1], [openssl 1.0 crypto])], + [PKG_CHECK_MODULES([openssl],[libcrypto >= 1.1], + [AC_DEFINE_UNQUOTED([BUILDCRYPTOOPENSSL11], [1], [openssl 1.1 crypto])])]) +]) AC_ARG_ENABLE([compress-all], - [ --disable-compress-all : disable libknet all compress modules support ],, + [AS_HELP_STRING([--disable-compress-all],[disable libknet all compress modules support])],, [ enable_compress_all="yes" ]) -AC_ARG_ENABLE([compress-zlib], - [ --disable-compress-zlib : disable libknet zlib support ],, - [ enable_compress_zlib="$enable_compress_all" ]) -AM_CONDITIONAL([BUILDCOMPZLIB], [test x$enable_compress_zlib = xyes]) - -AC_ARG_ENABLE([compress-lz4], - [ --disable-compress-lz4 : disable libknet lz4 support ],, - [ enable_compress_lz4="$enable_compress_all" ]) -AM_CONDITIONAL([BUILDCOMPLZ4], [test x$enable_compress_lz4 = xyes]) - -AC_ARG_ENABLE([compress-lzo2], - [ --disable-compress-lzo2 : disable libknet lzo2 support ],, - [ enable_compress_lzo2="$enable_compress_all" ]) -AM_CONDITIONAL([BUILDCOMPLZO2], [test x$enable_compress_lzo2 = xyes]) - -AC_ARG_ENABLE([compress-lzma], - [ --disable-compress-lzma : disable libknet lzma support ],, - [ enable_compress_lzma="$enable_compress_all" ]) -AM_CONDITIONAL([BUILDCOMPLZMA], [test x$enable_compress_lzma = xyes]) - -AC_ARG_ENABLE([compress-bzip2], - [ --disable-compress-bzip2 : disable libknet bzip2 support ],, - [ enable_compress_bzip2="$enable_compress_all" ]) -AM_CONDITIONAL([BUILDCOMPBZIP2], [test x$enable_compress_bzip2 = xyes]) +KNET_OPTION_DEFINES([zlib],[compress],[PKG_CHECK_MODULES([zlib], [zlib])]) +KNET_OPTION_DEFINES([lz4],[compress],[PKG_CHECK_MODULES([liblz4], [liblz4])]) +KNET_OPTION_DEFINES([lzo2],[compress],[ + PKG_CHECK_MODULES([lzo2], [lzo2],, + [AC_CHECK_HEADERS([lzo/lzo1x.h], + [AC_CHECK_LIB([lzo2], [lzo1x_decompress_safe], + [AC_SUBST([lzo2_LIBS], [-llzo2])])], + [AC_MSG_ERROR(["missing required lzo/lzo1x.h header"])])]) +]) +KNET_OPTION_DEFINES([lzma],[compress],[PKG_CHECK_MODULES([liblzma], [liblzma])]) +KNET_OPTION_DEFINES([bzip2],[compress],[ + PKG_CHECK_MODULES([bzip2], [bzip2],, + [AC_CHECK_HEADERS([bzlib.h], + [AC_CHECK_LIB([bz2], [BZ2_bzBuffToBuffCompress], + [AC_SUBST([bzip2_LIBS], [-lbz2])])], + [AC_MSG_ERROR(["missing required bzlib.h"])])]) +]) AC_ARG_ENABLE([poc], - [ --enable-poc : enable building poc code ],, + [AS_HELP_STRING([--enable-poc],[enable building poc code])],, [ enable_poc="no" ]) AM_CONDITIONAL([BUILD_POC], [test x$enable_poc = xyes]) AC_ARG_ENABLE([kronosnetd], - [ --enable-kronosnetd : Kronosnetd support ],, + [AS_HELP_STRING([--enable-kronosnetd],[Kronosnetd support])],, [ enable_kronosnetd="no" ]) AM_CONDITIONAL([BUILD_KRONOSNETD], [test x$enable_kronosnetd = xyes]) AC_ARG_ENABLE([runautogen], - [ --enable-runautogen : run autogen.sh ],, + [AS_HELP_STRING([--enable-runautogen],[run autogen.sh])],, [ enable_runautogen="no" ]) AM_CONDITIONAL([BUILD_RUNAUTOGEN], [test x$enable_runautogen = xyes]) AC_ARG_ENABLE([libtap], - [ --enable-libtap : libtap support ],, + [AS_HELP_STRING([--enable-libtap],[libtap support])],, [ enable_libtap="no" ]) if test "x$enable_kronosnetd" = xyes; then enable_libtap=yes fi AM_CONDITIONAL([BUILD_LIBTAP], [test x$enable_libtap = xyes]) ## local helper functions # this function checks if CC support options passed as # args. Global CFLAGS are ignored during this test. cc_supports_flag() { saveCPPFLAGS="$CPPFLAGS" CPPFLAGS="$@" if echo $CC | grep -q clang; then CPPFLAGS="-Werror $CPPFLAGS" fi AC_MSG_CHECKING([whether $CC supports "$@"]) AC_PREPROC_IFELSE([AC_LANG_PROGRAM([])], [RC=0; AC_MSG_RESULT([yes])], [RC=1; AC_MSG_RESULT([no])]) CPPFLAGS="$saveCPPFLAGS" return $RC } # Checks for C features AC_C_INLINE # Checks for libraries. AX_PTHREAD(,[AC_MSG_ERROR([POSIX threads support is required])]) AC_CHECK_LIB([m], [ceil], [AC_SUBST([m_LIBS], [-lm])], [AC_MSG_ERROR([kronosnet requires m library])]) saved_LIBS="$LIBS" LIBS= AC_SEARCH_LIBS([clock_gettime], [rt], , [AC_MSG_ERROR([clock_gettime not found])]) AC_SUBST([rt_LIBS], [$LIBS]) LIBS= AC_SEARCH_LIBS([dlopen], [dl dld], , [AC_MSG_ERROR([dlopen not found])]) AC_SUBST([dl_LIBS], [$LIBS]) LIBS="$saved_LIBS" # OS detection AC_MSG_CHECKING([for os in ${host_os}]) case "$host_os" in *linux*) AC_DEFINE_UNQUOTED([KNET_LINUX], [1], [Compiling for Linux platform]) AC_MSG_RESULT([Linux]) ;; *bsd*) AC_DEFINE_UNQUOTED([KNET_BSD], [1], [Compiling for BSD platform]) AC_MSG_RESULT([BSD]) if test "x$enable_libtap" = xyes; then AC_MSG_ERROR([libtap is not currently supported on BSD platforms]) fi ;; *) AC_MSG_ERROR([Unsupported OS? hmmmm]) ;; esac -AC_DEFUN([KNET_PKG_SONAME],[ -AC_MSG_CHECKING([for soname of $1]) -$CC -shared -nostdlib -o dummy.so -Wl,--no-as-needed $$1_LIBS -# Choosing the first SONAME is a best guess here: -knet_pkg_soname=`$OBJDUMP -p dummy.so | $SED -n '/^Dynamic Section:$/,/^[^ ]/{s/ *NEEDED *//p;}' | head -n1` -rm dummy.so -AC_DEFINE_UNQUOTED([$2],["$knet_pkg_soname"],[SONAME of the $1 library]) -AS_IF([test "x$knet_pkg_soname" = x], - [AC_MSG_FAILURE([failed to extract SONAME])], - [AC_MSG_RESULT([$knet_pkg_soname])]) -]) - -# crypto libraries checks -if test "x$enable_crypto_nss" = xyes; then - PKG_CHECK_MODULES([nss],[nss]) - AC_DEFINE_UNQUOTED([BUILDCRYPTONSS], [1], [Enable nss crypto]) - KNET_PKG_SONAME([nss],[LIBNSS3]) -fi - -if test "x$enable_crypto_openssl" = xyes; then - PKG_CHECK_MODULES([openssl],[libcrypto < 1.1], - [AC_DEFINE_UNQUOTED([BUILDCRYPTOOPENSSL10], [1], [openssl 1.0 crypto])], - [PKG_CHECK_MODULES([openssl],[libcrypto >= 1.1], - [AC_DEFINE_UNQUOTED([BUILDCRYPTOOPENSSL11], [1], [openssl 1.1 crypto])])]) - AC_DEFINE_UNQUOTED([BUILDCRYPTOOPENSSL], [1], [Enable openssl crypto]) - KNET_PKG_SONAME([openssl],[LIBOPENSSL]) -fi - -# compress libraries checks -if test "x$enable_compress_zlib" = xyes; then - PKG_CHECK_MODULES([zlib], [zlib]) - AC_DEFINE_UNQUOTED([BUILDCOMPZLIB], [1], [Enable zlib compression]) - KNET_PKG_SONAME([zlib],[LIBZ_1]) -fi -if test "x$enable_compress_lz4" = xyes; then - PKG_CHECK_MODULES([liblz4], [liblz4]) - AC_DEFINE_UNQUOTED([BUILDCOMPLZ4], [1], [Enable lz4 compress]) - KNET_PKG_SONAME([liblz4],[LIBLZ4_1]) -fi -if test "x$enable_compress_lzo2" = xyes; then - PKG_CHECK_MODULES([lzo2], [lzo2],, - [AC_CHECK_HEADERS([lzo/lzo1x.h], - [AC_CHECK_LIB([lzo2], [lzo1x_decompress_safe], - [AC_SUBST([lzo2_LIBS], [-llzo2])])], - [AC_MSG_ERROR(["missing required lzo/lzo1x.h header"])])]) - AC_DEFINE_UNQUOTED([BUILDCOMPLZO2], [1], [Enable lzo2 compress]) - KNET_PKG_SONAME([lzo2],[LIBLZO2_2]) -fi -if test "x$enable_compress_lzma" = xyes; then - PKG_CHECK_MODULES([liblzma], [liblzma]) - AC_DEFINE_UNQUOTED([BUILDCOMPLZMA], [1], [Enable lzma compress]) - KNET_PKG_SONAME([liblzma],[LIBLZMA_5]) -fi -if test "x$enable_compress_bzip2" = xyes; then - PKG_CHECK_MODULES([bzip2], [bzip2],, - [AC_CHECK_HEADERS([bzlib.h], - [AC_CHECK_LIB([bz2], [BZ2_bzBuffToBuffCompress], - [AC_SUBST([bzip2_LIBS], [-lbz2])])], - [AC_MSG_ERROR(["missing required bzlib.h"])])]) - AC_DEFINE_UNQUOTED([BUILDCOMPBZIP2], [1], [Enable bzip2 compress]) - KNET_PKG_SONAME([bzip2],[LIBBZ2_1]) -fi - # Checks for header files. AC_CHECK_HEADERS([fcntl.h]) AC_CHECK_HEADERS([stdlib.h]) AC_CHECK_HEADERS([string.h]) AC_CHECK_HEADERS([strings.h]) AC_CHECK_HEADERS([sys/ioctl.h]) AC_CHECK_HEADERS([syslog.h]) AC_CHECK_HEADERS([unistd.h]) AC_CHECK_HEADERS([netinet/in.h]) AC_CHECK_HEADERS([sys/socket.h]) AC_CHECK_HEADERS([arpa/inet.h]) AC_CHECK_HEADERS([netdb.h]) AC_CHECK_HEADERS([limits.h]) AC_CHECK_HEADERS([stdint.h]) AC_CHECK_HEADERS([sys/epoll.h]) if test "x$enable_libknet_sctp" = xyes; then AC_CHECK_HEADERS([netinet/sctp.h],, [AC_MSG_ERROR(["missing required SCTP headers"])]) fi # Checks for typedefs, structures, and compiler characteristics. AC_C_INLINE AC_TYPE_SIZE_T AC_TYPE_PID_T AC_TYPE_SSIZE_T AC_TYPE_UINT8_T AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_INT32_T # Checks for library functions. AC_FUNC_ALLOCA AC_FUNC_FORK AC_FUNC_MALLOC AC_FUNC_REALLOC AC_CHECK_FUNCS([kevent]) # if neither sys/epoll.h nor kevent are present, we should fail. if test "x$ac_cv_header_sys_epoll_h" = xno && test "x$ac_cv_func_kevent" = xno; then AC_MSG_ERROR([Both epoll and kevent unavailable on this OS]) fi if test "x$ac_cv_header_sys_epoll_h" = xyes && test "x$ac_cv_func_kevent" = xyes; then AC_MSG_ERROR([Both epoll and kevent available on this OS, please contact the maintainers to fix the code]) fi # checks (for kronosnetd) if test "x$enable_kronosnetd" = xyes; then AC_CHECK_HEADERS([security/pam_appl.h], [AC_CHECK_LIB([pam], [pam_start], [AC_SUBST([pam_LIBS], [-lpam])], [AC_MSG_ERROR([Unable to find LinuxPAM devel files])])]) AC_CHECK_HEADERS([security/pam_misc.h], [AC_CHECK_LIB([pam_misc], [misc_conv], [AC_SUBST([pam_misc_LIBS], [-lpam_misc])], [AC_MSG_ERROR([Unable to find LinuxPAM MISC devel files])])]) PKG_CHECK_MODULES([libqb], [libqb]) AC_CHECK_LIB([qb], [qb_log_thread_priority_set], [have_qb_log_thread_priority_set="yes"], [have_qb_log_thread_priority_set="no"]) if test "x${have_qb_log_thread_priority_set}" = xyes; then AC_DEFINE_UNQUOTED([HAVE_QB_LOG_THREAD_PRIORITY_SET], [1], [have qb_log_thread_priority_set]) fi fi # local options AC_ARG_ENABLE([debug], - [ --enable-debug enable debug build. ], - [ default="no" ]) + [AS_HELP_STRING([--enable-debug],[enable debug build])]) AC_ARG_WITH([initdefaultdir], - [ --with-initdefaultdir : path to /etc/sysconfig/.. or /etc/default dir. ], + [AS_HELP_STRING([--with-initdefaultdir=DIR],[path to /etc/sysconfig or /etc/default dir])], [ INITDEFAULTDIR="$withval" ], [ INITDEFAULTDIR="$sysconfdir/default" ]) AC_ARG_WITH([initddir], - [ --with-initddir=DIR : path to init script directory. ], + [AS_HELP_STRING([--with-initddir=DIR],[path to init script directory])], [ INITDDIR="$withval" ], [ INITDDIR="$sysconfdir/init.d" ]) AC_ARG_WITH([systemddir], - [ --with-systemddir=DIR : path to systemd unit files directory. ], + [AS_HELP_STRING([--with-systemddir=DIR],[path to systemd unit files directory])], [ SYSTEMDDIR="$withval" ], [ SYSTEMDDIR="$systemddir" ]) AC_ARG_WITH([syslogfacility], - [ --with-syslogfacility=FACILITY - default syslog facility. ], + [AS_HELP_STRING([--with-syslogfacility=FACILITY],[default syslog facility])], [ SYSLOGFACILITY="$withval" ], [ SYSLOGFACILITY="LOG_DAEMON" ]) AC_ARG_WITH([sysloglevel], - [ --with-sysloglevel=LEVEL - default syslog level. ], + [AS_HELP_STRING([--with-sysloglevel=LEVEL],[default syslog level])], [ SYSLOGLEVEL="$withval" ], [ SYSLOGLEVEL="LOG_INFO" ]) AC_ARG_WITH([defaultadmgroup], - [ --with-defaultadmgroup=GROUP - define PAM group. Users part of this group will be - allowed to configure kronosnet. Others will only - receive read-only rights. ], + [AS_HELP_STRING([--with-defaultadmgroup=GROUP], + [define PAM group. Users part of this group will be allowed to configure + kronosnet. Others will only receive read-only rights.])], [ DEFAULTADMGROUP="$withval" ], [ DEFAULTADMGROUP="kronosnetadm" ]) ## random vars LOGDIR=${localstatedir}/log/ RUNDIR=${localstatedir}/run/ DEFAULT_CONFIG_DIR=${sysconfdir}/kronosnet ## do subst AM_CONDITIONAL([DEBUG], [test "x${enable_debug}" = xyes]) AC_SUBST([DEFAULT_CONFIG_DIR]) AC_SUBST([INITDEFAULTDIR]) AC_SUBST([INITDDIR]) AC_SUBST([SYSTEMDDIR]) AC_SUBST([LOGDIR]) AC_SUBST([DEFAULTADMGROUP]) AC_DEFINE_UNQUOTED([DEFAULT_CONFIG_DIR], ["$(eval echo ${DEFAULT_CONFIG_DIR})"], [Default config directory]) AC_DEFINE_UNQUOTED([DEFAULT_CONFIG_FILE], ["$(eval echo ${DEFAULT_CONFIG_DIR}/kronosnetd.conf)"], [Default config file]) AC_DEFINE_UNQUOTED([LOGDIR], ["$(eval echo ${LOGDIR})"], [Default logging directory]) AC_DEFINE_UNQUOTED([DEFAULT_LOG_FILE], ["$(eval echo ${LOGDIR}/kronosnetd.log)"], [Default log file]) AC_DEFINE_UNQUOTED([RUNDIR], ["$(eval echo ${RUNDIR})"], [Default run directory]) AC_DEFINE_UNQUOTED([SYSLOGFACILITY], [$(eval echo ${SYSLOGFACILITY})], [Default syslog facility]) AC_DEFINE_UNQUOTED([SYSLOGLEVEL], [$(eval echo ${SYSLOGLEVEL})], [Default syslog level]) AC_DEFINE_UNQUOTED([DEFAULTADMGROUP], ["$(eval echo ${DEFAULTADMGROUP})"], [Default admin group]) ## *FLAGS handling ENV_CFLAGS="$CFLAGS" ENV_CPPFLAGS="$CPPFLAGS" ENV_LDFLAGS="$LDFLAGS" # debug build stuff if test "x${enable_debug}" = xyes; then AC_DEFINE_UNQUOTED([DEBUG], [1], [Compiling Debugging code]) OPT_CFLAGS="-O0" else OPT_CFLAGS="-O3" fi # gdb flags if test "x${GCC}" = xyes; then GDB_FLAGS="-ggdb3" else GDB_FLAGS="-g" fi # extra warnings EXTRA_WARNINGS="" WARNLIST=" all extra unused shadow missing-prototypes missing-declarations suggest-attribute=noreturn suggest-attribute=format strict-prototypes declaration-after-statement pointer-arith write-strings cast-align bad-function-cast missing-format-attribute float-equal format=2 format-signedness format-security format-nonliteral no-long-long unsigned-char gnu89-inline no-strict-aliasing error address cpp overflow parentheses sequence-point switch shift-overflow=2 overlength-strings retundent-decls init-self uninitialized unused-but-set-variable unused-function unused-result unused-value unused-variable unknown-pragmas no-unused-parameter " for j in $WARNLIST; do if cc_supports_flag -W$j; then EXTRA_WARNINGS="$EXTRA_WARNINGS -W$j"; fi done CFLAGS="$ENV_CFLAGS $lt_prog_compiler_pic $OPT_CFLAGS $GDB_FLAGS \ $EXTRA_WARNINGS $WERROR_CFLAGS" CPPFLAGS="$ENV_CPPFLAGS" LDFLAGS="$ENV_LDFLAGS $lt_prog_compiler_pic" AC_CONFIG_FILES([ Makefile init/Makefile libtap/Makefile libtap/libtap.pc kronosnetd/Makefile kronosnetd/kronosnetd.logrotate libknet/Makefile libknet/libknet.pc libknet/tests/Makefile libknet/man/Doxyfile libknet/man/Makefile poc-code/Makefile poc-code/iov-hash/Makefile poc-code/access-list/Makefile ]) AC_OUTPUT diff --git a/kronosnet.spec.in b/kronosnet.spec.in index e753d330..1af157e2 100644 --- a/kronosnet.spec.in +++ b/kronosnet.spec.in @@ -1,363 +1,512 @@ ############################################################################### ############################################################################### ## ## Copyright (C) 2012-2017 Red Hat, Inc. All rights reserved. ## ## This copyrighted material is made available to anyone wishing to use, ## modify, copy, or redistribute it subject to the terms and conditions ## of the GNU General Public License v.2 or higher ## ############################################################################### ############################################################################### # keep around ready for later user %global alphatag @alphatag@ %global numcomm @numcomm@ %global dirty @dirty@ # set defaults from ./configure invokation %@sctp@ sctp %@nss@ nss %@openssl@ openssl %@zlib@ zlib %@lz4@ lz4 %@lzo2@ lzo2 %@lzma@ lzma %@bzip2@ bzip2 %@kronosnetd@ kronosnetd %@libtap@ libtap %@runautogen@ runautogen %if %{with sctp} %global buildsctp 1 %endif %if %{with nss} %global buildcryptonss 1 %endif %if %{with openssl} %global buildcryptoopenssl 1 %endif %if %{with zlib} %global buildcompresszlib 1 %endif %if %{with lz4} %global buildcompresslz4 1 %endif %if %{with lzo2} %global buildcompresslzo2 1 %endif %if %{with lzma} %global buildcompresslzma 1 %endif %if %{with bzip2} %global buildcompressbzip2 1 %endif %if %{with libtap} %global buildlibtap 1 %endif %if %{with kronosnetd} %global buildlibtap 1 %global buildkronosnetd 1 %endif %if %{with runautogen} %global buildautogen 1 %endif # main (empty) package # http://www.rpm.org/max-rpm/s1-rpm-subpack-spec-file-changes.html Name: kronosnet Summary: Multipoint-to-Multipoint VPN daemon Version: @version@ Release: 1%{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}%{?dist} License: GPLv2+ and LGPLv2+ Group: System Environment/Base URL: https://github.com/fabbione/kronosnet/ Source0: https://github.com/fabbione/kronosnet/archive/%{name}-%{version}%{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}}.tar.gz ## Setup/build bits BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) # Build dependencies BuildRequires: gcc %if %{defined buildsctp} BuildRequires: lksctp-tools-devel %endif %if %{defined buildcryptonss} BuildRequires: /usr/include/nss3/nss.h /usr/include/nspr4/nspr.h %endif %if %{defined buildcryptoopenssl} BuildRequires: /usr/include/openssl/conf.h %endif %if %{defined buildcompresszlib} BuildRequires: zlib-devel %endif %if %{defined buildcompresslz4} BuildRequires: /usr/include/lz4hc.h %endif %if %{defined buildcompresslzo2} BuildRequires: lzo-devel %endif %if %{defined buildcompresslzma} BuildRequires: xz-devel %endif %if %{defined buildcompressbzip2} BuildRequires: /usr/include/bzlib.h %endif %if %{defined buildkronosnetd} BuildRequires: libqb-devel pam-devel %endif %if %{defined buildautogen} BuildRequires: autoconf BuildRequires: automake BuildRequires: libtool %endif %prep %setup -q -n %{name}-%{version}%{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}} %build %if %{with runautogen} ./autogen.sh %endif %{configure} \ %if %{defined buildsctp} --enable-libknet-sctp \ %else --disable-libknet-sctp \ %endif %if %{defined buildcryptonss} --enable-crypto-nss \ %else --disable-crypto-nss \ %endif %if %{defined buildcryptoopenssl} --enable-crypto-openssl \ %else --disable-crypto-openssl \ %endif %if %{defined buildcompresszlib} --enable-compress-zlib \ %else --disable-compress-zlib \ %endif %if %{defined buildcompresslz4} --enable-compress-lz4 \ %else --disable-compress-lz4 \ %endif %if %{defined buildcompresslzo2} --enable-compress-lzo2 \ %else --disable-compress-lzo2 \ %endif %if %{defined buildcompresslzma} --enable-compress-lzma \ %else --disable-compress-lzma \ %endif %if %{defined buildcompressbzip2} --enable-compress-bzip2 \ %else --disable-compress-bzip2 \ %endif %if %{defined buildkronosnetd} --enable-kronosnetd \ %endif %if %{defined buildlibtap} --enable-libtap \ %endif --with-initdefaultdir=%{_sysconfdir}/sysconfig/ \ %if %{defined _unitdir} --with-systemddir=%{_unitdir} %else --with-initddir=%{_sysconfdir}/rc.d/init.d/ %endif make %{_smp_mflags} %install rm -rf %{buildroot} make install DESTDIR=%{buildroot} # tree cleanup # remove static libraries find %{buildroot} -name "*.a" -exec rm {} \; # remove libtools leftovers find %{buildroot} -name "*.la" -exec rm {} \; # handle systemd vs init script %if %{defined _unitdir} # remove init scripts rm -rf %{buildroot}/etc/init.d %else # remove systemd specific bits find %{buildroot} -name "*.service" -exec rm {} \; %endif # remove docs rm -rf %{buildroot}/usr/share/doc/kronosnet %clean rm -rf %{buildroot} # main empty package %description kronosnet source %if %{defined buildkronosnetd} ## Runtime and subpackages section %package -n kronosnetd Group: System Environment/Base Summary: Multipoint-to-Multipoint VPN daemon %if %{defined _unitdir} # Needed for systemd unit Requires(post): systemd-sysv Requires(post): systemd-units Requires(preun): systemd-units Requires(postun): systemd-units %else Requires(post): chkconfig Requires(preun): chkconfig, initscripts %endif Requires(post): shadow-utils Requires(preun): shadow-utils Requires: pam, /etc/pam.d/passwd %description -n kronosnetd The kronosnet daemon is a bridge between kronosnet switching engine and kernel network tap devices, to create and administer a distributed LAN over multipoint-to-multipoint VPNs. The daemon does a poor attempt to provide a configure UI similar to other known network devices/tools (Cisco, quagga). Beside looking horrific, it allows runtime changes and reconfiguration of the kronosnet(s) without daemon reload or service disruption. %post -n kronosnetd %if %{defined _unitdir} %if 0%{?systemd_post:1} %systemd_post kronosnetd.service %else /bin/systemctl daemon-reload >/dev/null 2>&1 || : %endif %else /sbin/chkconfig --add kronosnetd %endif /usr/sbin/groupadd --force --system @defaultadmgroup@ %preun -n kronosnetd %if %{defined _unitdir} %if 0%{?systemd_preun:1} %systemd_preun kronosnetd.service %else if [ "$1" -eq 0 ]; then /bin/systemctl --no-reload disable kronosnetd.service /bin/systemctl stop kronosnetd.service >/dev/null 2>&1 fi %endif %else if [ "$1" = 0 ]; then /sbin/service kronosnetd stop >/dev/null 2>&1 /sbin/chkconfig --del kronosnetd fi %endif %files -n kronosnetd %defattr(-,root,root,-) %doc COPYING.* COPYRIGHT %dir %{_sysconfdir}/kronosnet %dir %{_sysconfdir}/kronosnet/* %config(noreplace) %{_sysconfdir}/sysconfig/kronosnetd %config(noreplace) %{_sysconfdir}/pam.d/kronosnetd %config(noreplace) %{_sysconfdir}/logrotate.d/kronosnetd %if %{defined _unitdir} %{_unitdir}/kronosnetd.service %else %config(noreplace) %{_sysconfdir}/rc.d/init.d/kronosnetd %endif %{_sbindir}/* %{_mandir}/man8/* %endif %if %{defined buildlibtap} %package -n libtap1 Group: System Environment/Libraries Summary: Simple userland wrapper around kernel tap devices %description -n libtap1 This is an over-engineered commodity library to manage a pool of tap devices and provides the basic pre-up.d/up.d/down.d/post-down.d infrastructure. %files -n libtap1 %defattr(-,root,root,-) %doc COPYING.* COPYRIGHT %{_libdir}/libtap.so.* %post -n libtap1 -p /sbin/ldconfig %postun -n libtap1 -p /sbin/ldconfig %package -n libtap1-devel Group: Development/Libraries Summary: Simple userland wrapper around kernel tap devices (developer files) Requires: libtap1 = %{version}-%{release} Requires: pkgconfig %description -n libtap1-devel This is an over-engineered commodity library to manage a pool of tap devices and provides the basic pre-up.d/up.d/down.d/post-down.d infrastructure. %files -n libtap1-devel %defattr(-,root,root,-) %doc COPYING.* COPYRIGHT %{_libdir}/libtap.so %{_includedir}/libtap.h %{_libdir}/pkgconfig/libtap.pc %endif %package -n libknet1 Group: System Environment/Libraries Summary: Kronosnet core switching implementation %description -n libknet1 The whole kronosnet core is implemented in this library. Please refer to the not-yet-existing documentation for further information. %files -n libknet1 %defattr(-,root,root,-) %doc COPYING.* COPYRIGHT %{_libdir}/libknet.so.* +%dir %{_libdir}/kronosnet %post -n libknet1 -p /sbin/ldconfig %postun -n libknet1 -p /sbin/ldconfig %package -n libknet1-devel Group: Development/Libraries Summary: Kronosnet core switching implementation (developer files) Requires: libknet1 = %{version}-%{release} Requires: pkgconfig %description -n libknet1-devel The whole kronosnet core is implemented in this library. Please refer to the not-yet-existing documentation for further information. %files -n libknet1-devel %defattr(-,root,root,-) %doc COPYING.* COPYRIGHT %{_libdir}/libknet.so %{_includedir}/libknet.h %{_libdir}/pkgconfig/libknet.pc %{_mandir}/man3/*.3.gz +%if %{defined buildcryptonss} +%package -n libknet1-crypto-nss-plugin +Group: System Environment/Libraries +Summary: libknet1 nss support +Requires: libknet1 = %{version}-%{release} + +%description -n libknet1-crypto-nss-plugin + NSS crypto support for libknet1. + +%files -n libknet1-crypto-nss-plugin +%defattr(-,root,root,-) +%{_libdir}/kronosnet/crypto_nss.so +%endif + +%if %{defined buildcryptoopenssl} +%package -n libknet1-crypto-openssl-plugin +Group: System Environment/Libraries +Summary: libknet1 openssl support +Requires: libknet1 = %{version}-%{release} + +%description -n libknet1-crypto-openssl-plugin + OpenSSL crypto support for libknet1. + +%files -n libknet1-crypto-openssl-plugin +%defattr(-,root,root,-) +%{_libdir}/kronosnet/crypto_openssl.so +%endif + +%if %{defined buildcompresszlib} +%package -n libknet1-compress-zlib-plugin +Group: System Environment/Libraries +Summary: libknet1 zlib support +Requires: libknet1 = %{version}-%{release} + +%description -n libknet1-compress-zlib-plugin + zlib compression support for libknet1. + +%files -n libknet1-compress-zlib-plugin +%defattr(-,root,root,-) +%{_libdir}/kronosnet/compress_zlib.so +%endif +%if %{defined buildcompresslz4} +%package -n libknet1-compress-lz4-plugin +Group: System Environment/Libraries +Summary: libknet1 lz4 and lz4hc support +Requires: libknet1 = %{version}-%{release} + +%description -n libknet1-compress-lz4-plugin + lz4 and lz4hc compression support for libknet1. + +%files -n libknet1-compress-lz4-plugin +%defattr(-,root,root,-) +%{_libdir}/kronosnet/compress_lz4.so +%{_libdir}/kronosnet/compress_lz4hc.so +%endif + +%if %{defined buildcompresslzo2} +%package -n libknet1-compress-lzo2-plugin +Group: System Environment/Libraries +Summary: libknet1 lzo2 support +Requires: libknet1 = %{version}-%{release} + +%description -n libknet1-compress-lzo2-plugin + lzo2 compression support for libknet1. + +%files -n libknet1-compress-lzo2-plugin +%defattr(-,root,root,-) +%{_libdir}/kronosnet/compress_lzo2.so +%endif + +%if %{defined buildcompresslzma} +%package -n libknet1-compress-lzma-plugin +Group: System Environment/Libraries +Summary: libknet1 lzma support +Requires: libknet1 = %{version}-%{release} + +%description -n libknet1-compress-lzma-plugin + lzma compression support for libknet1. + +%files -n libknet1-compress-lzma-plugin +%defattr(-,root,root,-) +%{_libdir}/kronosnet/compress_lzma.so +%endif + +%if %{defined buildcompressbzip2} +%package -n libknet1-compress-bzip2-plugin +Group: System Environment/Libraries +Summary: libknet1 bzip2 support +Requires: libknet1 = %{version}-%{release} + +%description -n libknet1-compress-bzip2-plugin + bzip2 compression support for libknet1. + +%files -n libknet1-compress-bzip2-plugin +%defattr(-,root,root,-) +%{_libdir}/kronosnet/compress_bzip2.so +%endif + +%package -n libknet1-crypto-plugins-all +Group: System Environment/Libraries +Summary: libknet1 crypto plugins meta package +%if %{defined buildcryptonss} +Requires: libknet1-crypto-nss-plugin +%endif +%if %{defined buildcryptoopenssl} +Requires: libknet1-crypto-openssl-plugin +%endif + +%description -n libknet1-crypto-plugins-all + meta package to install all of libknet1 crypto plugins + +%files -n libknet1-crypto-plugins-all + +%package -n libknet1-compress-plugins-all +Group: System Environment/Libraries +Summary: libknet1 compress plugins meta package +%if %{defined buildcompresszlib} +Requires: libknet1-compress-zlib-plugin +%endif +%if %{defined buildcompresslz4} +Requires: libknet1-compress-lz4-plugin +%endif +%if %{defined buildcompresslzo2} +Requires: libknet1-compress-lzo2-plugin +%endif +%if %{defined buildcompresslzma} +Requires: libknet1-compress-lzma-plugin +%endif +%if %{defined buildcompressbzip2} +Requires: libknet1-compress-bzip2-plugin +%endif + +%description -n libknet1-compress-plugins-all + meta package to install all of libknet1 compress plugins + +%files -n libknet1-compress-plugins-all + +%package -n libknet1-plugins-all +Group: System Environment/Libraries +Summary: libknet1 plugins meta package +Requires: libknet1-compress-plugins-all +Requires: libknet1-crypto-plugins-all + +%description -n libknet1-plugins-all + meta package to install all of libknet1 plugins + +%files -n libknet1-plugins-all + %changelog * @date@ Autotools generated version - @version@-1-@numcomm@.@alphatag@.@dirty@ - These aren't the droids you're looking for. diff --git a/libknet/Makefile.am b/libknet/Makefile.am index 5b412a7c..e18277a8 100644 --- a/libknet/Makefile.am +++ b/libknet/Makefile.am @@ -1,136 +1,162 @@ # # Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. # # Authors: Fabio M. Di Nitto # Federico Simoncelli # # This software licensed under GPL-2.0+, LGPL-2.0+ # MAINTAINERCLEANFILES = Makefile.in include $(top_srcdir)/build-aux/check.mk SYMFILE = libknet_exported_syms EXTRA_DIST = $(SYMFILE) SUBDIRS = . tests man libversion = 1:0:0 # override global LIBS that pulls in lots of craft we don't need here LIBS = sources = \ common.c \ compat.c \ compress.c \ - compress_zlib.c \ - compress_lz4.c \ - compress_lzo2.c \ - compress_lzma.c \ - compress_bzip2.c \ crypto.c \ - crypto_nss.c \ - crypto_openssl.c \ handle.c \ host.c \ links.c \ logging.c \ netutils.c \ threads_common.c \ threads_dsthandler.c \ threads_heartbeat.c \ threads_pmtud.c \ threads_rx.c \ threads_tx.c \ transports.c \ transport_common.c \ transport_loopback.c \ transport_udp.c \ transport_sctp.c include_HEADERS = libknet.h pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libknet.pc noinst_HEADERS = \ common.h \ compat.h \ compress.h \ - compress_bzip2.h \ - compress_bzip2_remap.h \ - compress_lz4.h \ - compress_lz4_remap.h \ - compress_lzma.h \ - compress_lzma_remap.h \ - compress_lzo2.h \ - compress_lzo2_remap.h \ - compress_zlib.h \ - compress_zlib_remap.h \ + compress_model.h \ crypto.h \ - crypto_nss.h \ - crypto_nss_remap.h \ - crypto_openssl.h \ - crypto_openssl_remap.h \ + crypto_model.h \ host.h \ internals.h \ links.h \ logging.h \ netutils.h \ onwire.h \ - remap.h \ threads_common.h \ threads_dsthandler.h \ threads_heartbeat.h \ threads_pmtud.h \ threads_rx.h \ threads_tx.h \ transports.h \ transport_common.h \ transport_loopback.h \ transport_udp.h \ transport_sctp.h lib_LTLIBRARIES = libknet.la libknet_la_SOURCES = $(sources) -libknet_la_CFLAGS = $(PTHREAD_CFLAGS) \ - $(nss_CFLAGS) $(openssl_CFLAGS) \ - $(zlib_CFLAGS) $(liblz4_CFLAGS) $(lzo2_CFLAGS) $(liblzma_CFLAGS) $(bzip2_CFLAGS) +libknet_la_CFLAGS = $(PTHREAD_CFLAGS) EXTRA_libknet_la_DEPENDENCIES = $(SYMFILE) libknet_la_LDFLAGS = -Wl,--version-script=$(srcdir)/$(SYMFILE) \ --export-dynamic \ + -Wl,-rpath=$(pkglibdir) \ -version-number $(libversion) libknet_la_LIBADD = $(PTHREAD_LIBS) $(dl_LIBS) $(rt_LIBS) $(m_LIBS) -noinst_PROGRAMS = crypto_canary compress_canary -crypto_canary_SOURCES = crypto_canary.c -crypto_canary_CFLAGS = $(nss_CFLAGS) $(openssl_CFLAGS) -crypto_canary_LDADD = $(nss_LIBS) $(openssl_LIBS) -compress_canary_SOURCES = compress_canary.c -compress_canary_CFLAGS = $(zlib_CFLAGS) $(liblz4_CFLAGS) $(lzo2_CFLAGS) $(liblzma_CFLAGS) $(bzip2_CFLAGS) -compress_canary_LDADD = $(zlib_LIBS) $(liblz4_LIBS) $(lzo2_LIBS) $(liblzma_LIBS) $(bzip2_LIBS) +# Prepare empty value for appending +pkglib_LTLIBRARIES = + +if BUILD_COMPRESS_ZLIB +pkglib_LTLIBRARIES += compress_zlib.la +compress_zlib_la_LDFLAGS = -module -avoid-version +compress_zlib_la_CFLAGS = $(zlib_CFLAGS) +compress_zlib_la_LIBADD = $(zlib_LIBS) +endif + +if BUILD_COMPRESS_LZ4 +pkglib_LTLIBRARIES += compress_lz4.la compress_lz4hc.la +compress_lz4_la_LDFLAGS = -module -avoid-version +compress_lz4_la_CFLAGS = $(liblz4_CFLAGS) +compress_lz4_la_LIBADD = $(liblz4_LIBS) +compress_lz4hc_la_LDFLAGS = -module -avoid-version +compress_lz4hc_la_CFLAGS = $(liblz4_CFLAGS) +compress_lz4hc_la_LIBADD = $(liblz4_LIBS) +endif + +if BUILD_COMPRESS_LZO2 +pkglib_LTLIBRARIES += compress_lzo2.la +compress_lzo2_la_LDFLAGS = -module -avoid-version +compress_lzo2_la_CFLAGS = $(lzo2_CFLAGS) +compress_lzo2_la_LIBADD = $(lzo2_LIBS) +endif + +if BUILD_COMPRESS_LZMA +pkglib_LTLIBRARIES += compress_lzma.la +compress_lzma_la_LDFLAGS = -module -avoid-version +compress_lzma_la_CFLAGS = $(liblzma_CFLAGS) +compress_lzma_la_LIBADD = $(liblzma_LIBS) +endif + +if BUILD_COMPRESS_BZIP2 +pkglib_LTLIBRARIES += compress_bzip2.la +compress_bzip2_la_LDFLAGS = -module -avoid-version +compress_bzip2_la_CFLAGS = $(bzip2_CFLAGS) +compress_bzip2_la_LIBADD = $(bzip2_LIBS) +endif + +if BUILD_CRYPTO_NSS +pkglib_LTLIBRARIES += crypto_nss.la +crypto_nss_la_LDFLAGS = -module -avoid-version +crypto_nss_la_CFLAGS = $(nss_CFLAGS) +crypto_nss_la_LIBADD = $(nss_LIBS) +endif + +if BUILD_CRYPTO_OPENSSL +pkglib_LTLIBRARIES += crypto_openssl.la +crypto_openssl_la_LDFLAGS = -module -avoid-version +crypto_openssl_la_CFLAGS = $(openssl_CFLAGS) +crypto_openssl_la_LIBADD = $(openssl_LIBS) +endif dist_man_MANS = man update-man-pages: doxyfile.stamp doxyfile.stamp: Doxyfile if MANPAGEUPDATES $(DOXYGEN) Doxyfile $(DOXY2MAN) -o $(abs_srcdir)/man -s 3 --short-pkg @PACKAGE_NAME@ --pkg "Kronosnet Programmer's Manual" $(builddir)/xml/libknet_8h.xml else @echo this system does not have doxy2man or doxygen installed. Unable to update man pages automatically. endif touch doxyfile.stamp clean-local: rm -rf doxyfile.stamp xml diff --git a/libknet/common.c b/libknet/common.c index 4d104722..9195bfba 100644 --- a/libknet/common.c +++ b/libknet/common.c @@ -1,130 +1,155 @@ /* * Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "logging.h" #include "common.h" int _fdset_cloexec(int fd) { int fdflags; fdflags = fcntl(fd, F_GETFD, 0); if (fdflags < 0) return -1; fdflags |= FD_CLOEXEC; if (fcntl(fd, F_SETFD, fdflags) < 0) return -1; return 0; } int _fdset_nonblock(int fd) { int fdflags; fdflags = fcntl(fd, F_GETFL, 0); if (fdflags < 0) return -1; fdflags |= O_NONBLOCK; if (fcntl(fd, F_SETFL, fdflags) < 0) return -1; return 0; } -void *open_lib(knet_handle_t knet_h, const char *libname, int extra_flags) +static void *open_lib(knet_handle_t knet_h, const char *libname, int extra_flags) { void *ret = NULL; char *error = NULL; char dir[MAXPATHLEN], path[MAXPATHLEN], link[MAXPATHLEN]; struct stat sb; /* * clear any pending error */ dlerror(); ret = dlopen(libname, RTLD_NOW | RTLD_GLOBAL | extra_flags); error = dlerror(); if (error != NULL) { log_err(knet_h, KNET_SUB_COMMON, "unable to dlopen %s: %s", libname, error); errno = EAGAIN; return NULL; } memset(dir, 0, sizeof(dir)); memset(link, 0, sizeof(link)); memset(path, 0, sizeof(path)); if (dlinfo(ret, RTLD_DI_ORIGIN, &dir) < 0) { /* * should we dlclose and return error? */ log_warn(knet_h, KNET_SUB_COMMON, "unable to dlinfo %s: %s", libname, error); } else { snprintf(path, sizeof(path), "%s/%s", dir, libname); log_info(knet_h, KNET_SUB_COMMON, "%s has been loaded from %s", libname, path); /* * try to resolve the library and check if it is a symlink and to where. * we can't prevent symlink attacks but at least we can log where the library * has been loaded from */ if (lstat(path, &sb) < 0) { log_debug(knet_h, KNET_SUB_COMMON, "Unable to stat %s: %s", path, strerror(errno)); goto out; } if (S_ISLNK(sb.st_mode)) { if (readlink(path, link, sizeof(link)) < 0) { log_debug(knet_h, KNET_SUB_COMMON, "Unable to readlink %s: %s", path, strerror(errno)); goto out; } /* * symlink is relative to the directory */ if (link[0] != '/') { snprintf(path, sizeof(path), "%s/%s", dir, link); log_info(knet_h, KNET_SUB_COMMON, "%s/%s is a symlink to %s", dir, libname, path); } else { log_info(knet_h, KNET_SUB_COMMON, "%s/%s is a symlink to %s", dir, libname, link); } } } out: return ret; } -void *remap_symbol(knet_handle_t knet_h, uint8_t subsystem, - void *lib_handle, const char *symbol_name) +void *load_module(knet_handle_t knet_h, const char *type, const char *name) { - void *symbol = dlsym (lib_handle, symbol_name); - if (!symbol) { - log_err (knet_h, subsystem, "unable to map %s: %s", symbol_name, dlerror ()); + void *module, *ops; + log_msg_t **log_msg_sym; + char soname[MAXPATHLEN], opsname[MAXPATHLEN]; + + snprintf (soname, sizeof soname, "%s_%s.so", type, name); + + module = open_lib(knet_h, soname, 0); + if (!module) { + return NULL; + } + + log_msg_sym = dlsym (module, "log_msg"); + if (!log_msg_sym) { + log_err (knet_h, KNET_SUB_COMMON, "unable to map symbol 'log_msg' in module %s: %s", + soname, dlerror ()); + errno = EINVAL; + return NULL; } - return symbol; + *log_msg_sym = log_msg; + + snprintf (opsname, sizeof opsname, "%s_model", type); + + ops = dlsym (module, opsname); + if (!ops) { + log_err (knet_h, KNET_SUB_COMMON, "unable to map symbol 'model' in module %s: %s", + soname, dlerror ()); + errno = EINVAL; + return NULL; + } + + return ops; } diff --git a/libknet/common.h b/libknet/common.h index f92f5941..0d1db235 100644 --- a/libknet/common.h +++ b/libknet/common.h @@ -1,21 +1,19 @@ /* * Copyright (C) 2012-2017 Red Hat, Inc. All rights reserved. * * Authors: Fabio M. Di Nitto * Federico Simoncelli * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "internals.h" #ifndef __KNET_COMMON_H__ #define __KNET_COMMON_H__ int _fdset_cloexec(int fd); int _fdset_nonblock(int fd); -void *open_lib(knet_handle_t knet_h, const char *libname, int extra_flags); -void *remap_symbol(knet_handle_t knet_h, uint8_t subsystem, - void *lib_handle, const char *symbol_name); +void *load_module(knet_handle_t knet_h, const char *type, const char *name); #endif diff --git a/libknet/compress.c b/libknet/compress.c index e2b4f7ba..f9ac5655 100644 --- a/libknet/compress.c +++ b/libknet/compress.c @@ -1,467 +1,430 @@ /* * Copyright (C) 2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include #include #include #include #include "internals.h" #include "compress.h" +#include "compress_model.h" #include "logging.h" #include "threads_common.h" - -#ifdef BUILDCOMPZLIB -#include "compress_zlib.h" -#endif -#ifdef BUILDCOMPLZ4 -#include "compress_lz4.h" -#endif -#ifdef BUILDCOMPLZO2 -#include "compress_lzo2.h" -#endif -#ifdef BUILDCOMPLZMA -#include "compress_lzma.h" -#endif -#ifdef BUILDCOMPBZIP2 -#include "compress_bzip2.h" -#endif +#include "common.h" /* * internal module switch data */ /* * DO NOT CHANGE MODEL_ID HERE OR ONWIRE COMPATIBILITY * WILL BREAK! * - * always add before the last NULL/NULL/NULL. + * Always add new items before the last NULL. */ -#define empty_module 0, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL }, - compress_model_t compress_modules_cmds[] = { - { "none", 0, empty_module - { "zlib", 1, -#ifdef BUILDCOMPZLIB - 1, zlib_load_lib, 0, NULL, NULL, NULL, zlib_val_level, zlib_compress, zlib_decompress }, -#else -empty_module -#endif - { "lz4", 2, -#ifdef BUILDCOMPLZ4 - 1, lz4_load_lib, 0, NULL, NULL, NULL, lz4_val_level, lz4_compress, lz4_decompress }, -#else -empty_module -#endif - { "lz4hc", 3, -#ifdef BUILDCOMPLZ4 - 1, lz4_load_lib, 0, NULL, NULL, NULL, lz4hc_val_level, lz4hc_compress, lz4_decompress }, -#else -empty_module -#endif - { "lzo2", 4, -#ifdef BUILDCOMPLZO2 - 1, lzo2_load_lib, 0, lzo2_is_init, lzo2_init, lzo2_fini, lzo2_val_level, lzo2_compress, lzo2_decompress }, -#else -empty_module -#endif - { "lzma", 5, -#ifdef BUILDCOMPLZMA - 1, lzma_load_lib, 0, NULL, NULL, NULL, lzma_val_level, lzma_compress, lzma_decompress }, -#else -empty_module -#endif - { "bzip2", 6, -#ifdef BUILDCOMPBZIP2 - 1, bzip2_load_lib, 0, NULL, NULL, NULL, bzip2_val_level, bzip2_compress, bzip2_decompress }, -#else -empty_module -#endif - { NULL, 255, empty_module + { "none" , 0, 0, 0, NULL }, + { "zlib" , 1, WITH_COMPRESS_ZLIB , 0, NULL }, + { "lz4" , 2, WITH_COMPRESS_LZ4 , 0, NULL }, + { "lz4hc", 3, WITH_COMPRESS_LZ4 , 0, NULL }, + { "lzo2" , 4, WITH_COMPRESS_LZO2 , 0, NULL }, + { "lzma" , 5, WITH_COMPRESS_LZMA , 0, NULL }, + { "bzip2", 6, WITH_COMPRESS_BZIP2, 0, NULL }, + { NULL, 255, 0, 0, NULL } }; static int max_model = 0; static struct timespec last_load_failure; static int compress_get_model(const char *model) { int idx = 0; while (compress_modules_cmds[idx].model_name != NULL) { if (!strcmp(compress_modules_cmds[idx].model_name, model)) { return compress_modules_cmds[idx].model_id; } idx++; } return -1; } static int compress_get_max_model(void) { int idx = 0; while (compress_modules_cmds[idx].model_name != NULL) { idx++; } return idx - 1; } static int compress_is_valid_model(int compress_model) { int idx = 0; while (compress_modules_cmds[idx].model_name != NULL) { if ((compress_model == compress_modules_cmds[idx].model_id) && (compress_modules_cmds[idx].built_in == 1)) { return 0; } idx++; } return -1; } static int val_level( knet_handle_t knet_h, int compress_model, int compress_level) { - return compress_modules_cmds[compress_model].val_level(knet_h, compress_level); + return compress_modules_cmds[compress_model].ops->val_level(knet_h, compress_level); } /* * compress_check_lib_is_init needs to be invoked in a locked context! */ static int compress_check_lib_is_init(knet_handle_t knet_h, int cmp_model) { /* * lack of a .is_init function means that the module does not require * init per handle so we use a fake reference in the compress_int_data * to identify that we already increased the libref for this handle */ if (compress_modules_cmds[cmp_model].loaded == 1) { - if (compress_modules_cmds[cmp_model].is_init == NULL) { + if (compress_modules_cmds[cmp_model].ops->is_init == NULL) { if (knet_h->compress_int_data[cmp_model] != NULL) { return 1; } } else { - if (compress_modules_cmds[cmp_model].is_init(knet_h, cmp_model) == 1) { + if (compress_modules_cmds[cmp_model].ops->is_init(knet_h, cmp_model) == 1) { return 1; } } } return 0; } /* * compress_load_lib should _always_ be invoked in write lock context */ static int compress_load_lib(knet_handle_t knet_h, int cmp_model, int rate_limit) { struct timespec clock_now; unsigned long long timediff; /* * checking again for paranoia and because * compress_check_lib_is_init is usually invoked in read context * and we need to switch from read to write locking in between. * another thread might have init the library in the meantime */ if (compress_check_lib_is_init(knet_h, cmp_model)) { return 0; } /* * due to the fact that decompress can load libraries * on demand, depending on the compress model selected * on other nodes, it is possible for an attacker * to send crafted packets to attempt to load libraries * at random in a DoS fashion. * If there is an error loading a library, then we want * to rate_limit a retry to reload the library every X * seconds to avoid a lock DoS that could greatly slow * down libknet. */ if (rate_limit) { if ((last_load_failure.tv_sec != 0) || (last_load_failure.tv_nsec != 0)) { clock_gettime(CLOCK_MONOTONIC, &clock_now); timespec_diff(last_load_failure, clock_now, &timediff); if (timediff < 10000000000) { errno = EAGAIN; return -1; } } } if (compress_modules_cmds[cmp_model].loaded == 0) { - if (compress_modules_cmds[cmp_model].load_lib(knet_h) < 0) { + compress_modules_cmds[cmp_model].ops = load_module (knet_h, "compress", compress_modules_cmds[cmp_model].model_name); + if (!compress_modules_cmds[cmp_model].ops) { clock_gettime(CLOCK_MONOTONIC, &last_load_failure); return -1; } + if (compress_modules_cmds[cmp_model].ops->abi_ver != KNET_COMPRESS_MODEL_ABI) { + log_err(knet_h, KNET_SUB_COMPRESS, + "ABI mismatch loading module %s. knet ver: %d, module ver: %d", + compress_modules_cmds[cmp_model].model_name, KNET_COMPRESS_MODEL_ABI, + compress_modules_cmds[cmp_model].ops->abi_ver); + errno = EINVAL; + return -1; + } compress_modules_cmds[cmp_model].loaded = 1; } - if (compress_modules_cmds[cmp_model].init != NULL) { - if (compress_modules_cmds[cmp_model].init(knet_h, cmp_model) < 0) { + if (compress_modules_cmds[cmp_model].ops->init != NULL) { + if (compress_modules_cmds[cmp_model].ops->init(knet_h, cmp_model) < 0) { return -1; } } else { knet_h->compress_int_data[cmp_model] = (void *)&"1"; } return 0; } int compress_init( knet_handle_t knet_h) { max_model = compress_get_max_model(); if (max_model > KNET_MAX_COMPRESS_METHODS) { log_err(knet_h, KNET_SUB_COMPRESS, "Too many compress methods defined in compress.c."); errno = EINVAL; return -1; } memset(&last_load_failure, 0, sizeof(struct timespec)); return 0; } int compress_cfg( knet_handle_t knet_h, struct knet_handle_compress_cfg *knet_handle_compress_cfg) { int savederrno = 0, err = 0; int cmp_model; cmp_model = compress_get_model(knet_handle_compress_cfg->compress_model); if (cmp_model < 0) { log_err(knet_h, KNET_SUB_COMPRESS, "compress model %s not supported", knet_handle_compress_cfg->compress_model); errno = EINVAL; return -1; } log_debug(knet_h, KNET_SUB_COMPRESS, "Initizializing compress module [%s/%d/%u]", knet_handle_compress_cfg->compress_model, knet_handle_compress_cfg->compress_level, knet_handle_compress_cfg->compress_threshold); if (cmp_model > 0) { if (compress_modules_cmds[cmp_model].built_in == 0) { log_err(knet_h, KNET_SUB_COMPRESS, "compress model %s support has not been built in. Please contact your vendor or fix the build", knet_handle_compress_cfg->compress_model); errno = EINVAL; return -1; } if (knet_handle_compress_cfg->compress_threshold > KNET_MAX_PACKET_SIZE) { log_err(knet_h, KNET_SUB_COMPRESS, "compress threshold cannot be higher than KNET_MAX_PACKET_SIZE (%d).", KNET_MAX_PACKET_SIZE); errno = EINVAL; return -1; } if (knet_handle_compress_cfg->compress_threshold == 0) { knet_h->compress_threshold = KNET_COMPRESS_THRESHOLD; log_debug(knet_h, KNET_SUB_COMPRESS, "resetting compression threshold to default (%d)", KNET_COMPRESS_THRESHOLD); } else { knet_h->compress_threshold = knet_handle_compress_cfg->compress_threshold; } savederrno = pthread_rwlock_rdlock(&shlib_rwlock); if (savederrno) { log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get read lock: %s", strerror(savederrno)); errno = savederrno; return -1; } if (!compress_check_lib_is_init(knet_h, cmp_model)) { /* * need to switch to write lock, load the lib, and return with a write lock * this is not racy because compress_load_lib is written idempotent. */ pthread_rwlock_unlock(&shlib_rwlock); savederrno = pthread_rwlock_wrlock(&shlib_rwlock); if (savederrno) { log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get write lock: %s", strerror(savederrno)); errno = savederrno; return -1; } if (compress_load_lib(knet_h, cmp_model, 0) < 0) { savederrno = errno; log_err(knet_h, KNET_SUB_COMPRESS, "Unable to load library: %s", strerror(savederrno)); err = -1; goto out_unlock; } } if (val_level(knet_h, cmp_model, knet_handle_compress_cfg->compress_level) < 0) { log_err(knet_h, KNET_SUB_COMPRESS, "compress level %d not supported for model %s", knet_handle_compress_cfg->compress_level, knet_handle_compress_cfg->compress_model); savederrno = EINVAL; err = -1; goto out_unlock; } out_unlock: pthread_rwlock_unlock(&shlib_rwlock); } if (!err) { knet_h->compress_model = cmp_model; knet_h->compress_level = knet_handle_compress_cfg->compress_level; } else { knet_h->compress_model = 0; } errno = savederrno; return err; } void compress_fini( knet_handle_t knet_h, int all) { int savederrno = 0; int idx = 0; savederrno = pthread_rwlock_wrlock(&shlib_rwlock); if (savederrno) { log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get write lock: %s", strerror(savederrno)); return; } while (compress_modules_cmds[idx].model_name != NULL) { if ((compress_modules_cmds[idx].built_in == 1) && (compress_modules_cmds[idx].loaded == 1) && (compress_modules_cmds[idx].model_id > 0) && (knet_h->compress_int_data[idx] != NULL) && (idx < KNET_MAX_COMPRESS_METHODS)) { if ((all) || (compress_modules_cmds[idx].model_id == knet_h->compress_model)) { - if (compress_modules_cmds[idx].fini != NULL) { - compress_modules_cmds[idx].fini(knet_h, idx); + if (compress_modules_cmds[idx].ops->fini != NULL) { + compress_modules_cmds[idx].ops->fini(knet_h, idx); } else { knet_h->compress_int_data[idx] = NULL; } } } idx++; } pthread_rwlock_unlock(&shlib_rwlock); return; } /* * compress does not require compress_check_lib_is_init * because it's protected by compress_cfg */ int compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { - return compress_modules_cmds[knet_h->compress_model].compress(knet_h, buf_in, buf_in_len, buf_out, buf_out_len); + return compress_modules_cmds[knet_h->compress_model].ops->compress(knet_h, buf_in, buf_in_len, buf_out, buf_out_len); } int decompress( knet_handle_t knet_h, int compress_model, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int savederrno = 0, err = 0; if (compress_model > max_model) { log_err(knet_h, KNET_SUB_COMPRESS, "Received packet with unknown compress model %d", compress_model); errno = EINVAL; return -1; } if (compress_is_valid_model(compress_model) < 0) { log_err(knet_h, KNET_SUB_COMPRESS, "Received packet compressed with %s but support is not built in this version of libknet. Please contact your distribution vendor or fix the build.", compress_modules_cmds[compress_model].model_name); errno = EINVAL; return -1; } savederrno = pthread_rwlock_rdlock(&shlib_rwlock); if (savederrno) { log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get read lock: %s", strerror(savederrno)); errno = savederrno; return -1; } if (!compress_check_lib_is_init(knet_h, compress_model)) { /* * need to switch to write lock, load the lib, and return with a write lock * this is not racy because compress_load_lib is written idempotent. */ pthread_rwlock_unlock(&shlib_rwlock); savederrno = pthread_rwlock_wrlock(&shlib_rwlock); if (savederrno) { log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get write lock: %s", strerror(savederrno)); errno = savederrno; return -1; } if (compress_load_lib(knet_h, compress_model, 1) < 0) { savederrno = errno; err = -1; log_err(knet_h, KNET_SUB_COMPRESS, "Unable to load library: %s", strerror(savederrno)); goto out_unlock; } } - err = compress_modules_cmds[compress_model].decompress(knet_h, buf_in, buf_in_len, buf_out, buf_out_len); + err = compress_modules_cmds[compress_model].ops->decompress(knet_h, buf_in, buf_in_len, buf_out, buf_out_len); savederrno = errno; out_unlock: pthread_rwlock_unlock(&shlib_rwlock); errno = savederrno; return err; } int knet_get_compress_list(struct knet_compress_info *compress_list, size_t *compress_list_entries) { int err = 0; int idx = 0; int outidx = 0; if (!compress_list_entries) { errno = EINVAL; return -1; } while (compress_modules_cmds[idx].model_name != NULL) { if (compress_modules_cmds[idx].built_in) { if (compress_list) { compress_list[outidx].name = compress_modules_cmds[idx].model_name; } outidx++; } idx++; } *compress_list_entries = outidx; return err; } diff --git a/libknet/compress.h b/libknet/compress.h index 717698d8..f2d0def9 100644 --- a/libknet/compress.h +++ b/libknet/compress.h @@ -1,118 +1,40 @@ /* * Copyright (C) 2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #ifndef __KNET_COMPRESS_H__ #define __KNET_COMPRESS_H__ #include "internals.h" -typedef struct { - const char *model_name; - uint8_t model_id; /* sequencial unique identifier */ - uint8_t built_in; /* set at configure/build time to 1 if available */ - - /* - * shared lib load functions - * - * both are called in shlib_rwlock write context and should - * update the loaded status below. - */ - int (*load_lib) (knet_handle_t knet_h); - - /* - * library is loaded - */ - uint8_t loaded; - - /* - * runtime bits - */ - - /* - * some libs need special init and handling of buffers etc. - * is_init is called in shlib_rwlock read only context to see if - * the module has been initialized within this knet_handle. - * Providing is_init is optional. A module that does not export - * an is_init and if the associated shared library is already loaded - * is treated as "does not require init". - */ - int (*is_init) (knet_handle_t knet_h, int method_idx); - - /* - * init is called when the library requires special init handling, - * such as memory allocation and such. - * init is invoked in shlib_rwlock write only context when - * the module exports this function. - * It is optional to provide an init function if the module - * does not require any init. - */ - int (*init) (knet_handle_t knet_h, int method_idx); - - /* - * fini is invoked only on knet_handle_free in a write only context. - * It is optional to provide this function if the module - * does not require any finalization - */ - void (*fini) (knet_handle_t knet_h, int method_idx); - - /* - * runtime config validation and compress/decompress - */ - - /* - * required functions - * - * val_level is called upon compress configuration changes - * to make sure that the requested compress_level is valid - * within the context of a given module. - */ - int (*val_level)(knet_handle_t knet_h, - int compress_level); - - /* - * hopefully those 2 don't require any explanation.... - */ - int (*compress) (knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - int (*decompress)(knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); -} compress_model_t; - int compress_cfg( knet_handle_t knet_h, struct knet_handle_compress_cfg *knet_handle_compress_cfg); int compress_init( knet_handle_t knet_h); void compress_fini( knet_handle_t knet_h, int all); int compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int decompress( knet_handle_t knet_h, int compress_model, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); #endif diff --git a/libknet/compress_bzip2.c b/libknet/compress_bzip2.c index 38add11d..759cf4a6 100644 --- a/libknet/compress_bzip2.c +++ b/libknet/compress_bzip2.c @@ -1,165 +1,126 @@ /* * Copyright (C) 2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ +#define KNET_MODULE #include "config.h" -#include -#include #include -#include -#ifdef BUILDCOMPBZIP2 #include -#include "internals.h" -#include "compress_bzip2.h" #include "logging.h" -#include "common.h" +#include "compress_model.h" -/* - * global vars for dlopen - */ -static void *bzip2_lib; - -#include "compress_bzip2_remap.h" - -static int bzip2_remap_symbols(knet_handle_t knet_h) -{ -#define REMAP_WITH(name) remap_symbol (knet_h, KNET_SUB_BZIP2COMP, bzip2_lib, name) -#include "compress_bzip2_remap.h" - return 0; - - fail: -#define REMAP_FAIL -#include "compress_bzip2_remap.h" - errno = EINVAL; - return -1; -} - -int bzip2_load_lib( - knet_handle_t knet_h) -{ - int err = 0, savederrno = 0; - - if (!bzip2_lib) { - bzip2_lib = open_lib(knet_h, LIBBZ2_1, 0); - if (!bzip2_lib) { - savederrno = errno; - err = -1; - goto out; - } - } - - if (bzip2_remap_symbols(knet_h) < 0) { - savederrno = errno; - err = -1; - } -out: - errno = savederrno; - return err; -} - -int bzip2_val_level( +static int bzip2_val_level( knet_handle_t knet_h, int compress_level) { if ((compress_level < 1) || (compress_level > 9)) { log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 unsupported compression level %d (accepted values from 1 to 9)", compress_level); errno = EINVAL; return -1; } return 0; } -int bzip2_compress( +static int bzip2_compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int err = 0; int savederrno = 0; unsigned int destLen = KNET_DATABUFSIZE_COMPRESS; - err = (*_int_BZ2_bzBuffToBuffCompress)((char *)buf_out, &destLen, - (char *)buf_in, buf_in_len, - knet_h->compress_level, - 0, 0); + err = BZ2_bzBuffToBuffCompress((char *)buf_out, &destLen, + (char *)buf_in, buf_in_len, + knet_h->compress_level, + 0, 0); switch(err) { case BZ_OK: *buf_out_len = destLen; break; case BZ_MEM_ERROR: log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 compress has not enough memory"); savederrno = ENOMEM; err = -1; break; case BZ_OUTBUFF_FULL: log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 unable to compress source in destination buffer"); savederrno = E2BIG; err = -1; break; default: log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 compress unknown error %d", err); savederrno = EINVAL; err = -1; break; } errno = savederrno; return err; } -int bzip2_decompress( +static int bzip2_decompress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int err = 0; int savederrno = 0; unsigned int destLen = KNET_DATABUFSIZE_COMPRESS; - err = (*_int_BZ2_bzBuffToBuffDecompress)((char *)buf_out, &destLen, - (char *)buf_in, buf_in_len, - 0, 0); + err = BZ2_bzBuffToBuffDecompress((char *)buf_out, &destLen, + (char *)buf_in, buf_in_len, + 0, 0); switch(err) { case BZ_OK: *buf_out_len = destLen; break; case BZ_MEM_ERROR: log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 decompress has not enough memory"); savederrno = ENOMEM; err = -1; break; case BZ_OUTBUFF_FULL: log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 unable to decompress source in destination buffer"); savederrno = E2BIG; err = -1; break; case BZ_DATA_ERROR: case BZ_DATA_ERROR_MAGIC: case BZ_UNEXPECTED_EOF: log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 decompress detected input data corruption"); savederrno = EINVAL; err = -1; break; default: log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 decompress unknown error %d", err); savederrno = EINVAL; err = -1; break; } errno = savederrno; return err; } -#endif + +compress_ops_t compress_model = { + KNET_COMPRESS_MODEL_ABI, + NULL, + NULL, + NULL, + bzip2_val_level, + bzip2_compress, + bzip2_decompress +}; diff --git a/libknet/compress_bzip2.h b/libknet/compress_bzip2.h deleted file mode 100644 index cd112810..00000000 --- a/libknet/compress_bzip2.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2017 Red Hat, Inc. All rights reserved. - * - * Author: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+, LGPL-2.0+ - */ - -#ifndef __KNET_COMPRESS_BZIP2_H__ -#define __KNET_COMPRESS_BZIP2_H__ - -#include "internals.h" - -int bzip2_load_lib( - knet_handle_t knet_h); - -int bzip2_val_level( - knet_handle_t knet_h, - int compress_level); - -int bzip2_compress( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - -int bzip2_decompress( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - -#endif diff --git a/libknet/compress_bzip2_remap.h b/libknet/compress_bzip2_remap.h deleted file mode 100644 index 917e7ee1..00000000 --- a/libknet/compress_bzip2_remap.h +++ /dev/null @@ -1,11 +0,0 @@ -#include "remap.h" - -REMAP_PROTO(int,BZ2_bzBuffToBuffCompress, - (char* dest, unsigned int* destLen, - char* source, unsigned int sourceLen, - int blockSize100k, int verbosity, - int workFactor)) -REMAP_PROTO(int,BZ2_bzBuffToBuffDecompress, - (char* dest, unsigned int* destLen, - char* source, unsigned int sourceLen, - int samll, int verbosity)) diff --git a/libknet/compress_canary.c b/libknet/compress_canary.c deleted file mode 100644 index fe010fa2..00000000 --- a/libknet/compress_canary.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Transform the binary into dependencies like: - * dpkg-shlibdeps -pcompress -dSuggests -xlibc6 -elibknet/compress_canary - */ - -#include "config.h" - -#define CANARY - -#include "compress_bzip2_remap.h" -#include "compress_lz4_remap.h" -#include "compress_lzma_remap.h" -#include "compress_lzo2_remap.h" -#include "compress_zlib_remap.h" - -#define CANARY_CALL - -int main (void) -{ - return -#ifdef BUILDCOMPBZIP2 -#include "compress_bzip2_remap.h" -#endif -#ifdef BUILDCOMPLZ4 -#include "compress_lz4_remap.h" -#endif -#ifdef BUILDCOMPLZMA -#include "compress_lzma_remap.h" -#endif -#ifdef BUILDCOMPLZO2 -#include "compress_lzo2_remap.h" -#endif -#ifdef BUILDCOMPZLIB -#include "compress_zlib_remap.h" -#endif - 0; -} diff --git a/libknet/compress_lz4.c b/libknet/compress_lz4.c index aa00fc02..7364ffed 100644 --- a/libknet/compress_lz4.c +++ b/libknet/compress_lz4.c @@ -1,205 +1,102 @@ /* * Copyright (C) 2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ +#define KNET_MODULE #include "config.h" -#include -#include #include -#include -#ifdef BUILDCOMPLZ4 #include -#include "internals.h" -#include "compress_lz4.h" #include "logging.h" -#include "common.h" +#include "compress_model.h" -/* - * global vars for dlopen - */ -static void *lz4_lib; - -#include "compress_lz4_remap.h" - -static int lz4_remap_symbols(knet_handle_t knet_h) -{ -#define REMAP_WITH(name) remap_symbol (knet_h, KNET_SUB_LZ4COMP, lz4_lib, name) -#include "compress_lz4_remap.h" - return 0; - - fail: -#define REMAP_FAIL -#include "compress_lz4_remap.h" - errno = EINVAL; - return -1; -} - -int lz4_load_lib( - knet_handle_t knet_h) -{ - int err = 0, savederrno = 0; - - if (!lz4_lib) { - lz4_lib = open_lib(knet_h, LIBLZ4_1, 0); - if (!lz4_lib) { - savederrno = EAGAIN; - err = -1; - goto out; - } - } - - if (lz4_remap_symbols(knet_h) < 0) { - savederrno = errno; - err = -1; - } -out: - errno = savederrno; - return err; -} - -int lz4_val_level( +static int lz4_val_level( knet_handle_t knet_h, int compress_level) { if (compress_level <= 0) { - log_info(knet_h, KNET_SUB_LZ4COMP, "lz4 acceleration level 0 (or negatives) are automatically remapped to 1 by %s", LIBLZ4_1); + log_info(knet_h, KNET_SUB_LZ4COMP, "lz4 acceleration level 0 (or negatives) are automatically remapped to 1"); } return 0; } -int lz4_compress( +static int lz4_compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int lzerr = 0, err = 0; int savederrno = 0; - lzerr = (*_int_LZ4_compress_fast)((const char *)buf_in, (char *)buf_out, buf_in_len, KNET_DATABUFSIZE_COMPRESS, knet_h->compress_level); + lzerr = LZ4_compress_fast((const char *)buf_in, (char *)buf_out, buf_in_len, KNET_DATABUFSIZE_COMPRESS, knet_h->compress_level); /* * data compressed */ if (lzerr > 0) { *buf_out_len = lzerr; } /* * unable to compress */ if (lzerr == 0) { *buf_out_len = buf_in_len; } /* * lz4 internal error */ if (lzerr < 0) { log_err(knet_h, KNET_SUB_LZ4COMP, "lz4 compression error: %d", lzerr); savederrno = EINVAL; err = -1; } errno = savederrno; return err; } -#ifdef LZ4HC_CLEVEL_MAX -#define KNET_LZ4HC_MAX LZ4HC_CLEVEL_MAX -#endif -#ifdef LZ4HC_MAX_CLEVEL -#define KNET_LZ4HC_MAX LZ4HC_MAX_CLEVEL -#endif -#ifndef KNET_LZ4HC_MAX -#define KNET_LZ4HC_MAX 0 -#error Please check lz4hc.h for missing LZ4HC_CLEVEL_MAX or LZ4HC_MAX_CLEVEL variants -#endif - -int lz4hc_val_level( - knet_handle_t knet_h, - int compress_level) -{ - if (compress_level < 1) { - log_err(knet_h, KNET_SUB_LZ4HCCOMP, "lz4hc supports only 1+ values for compression level"); - errno = EINVAL; - return -1; - } - - if (compress_level < 4) { - log_info(knet_h, KNET_SUB_LZ4HCCOMP, "lz4hc recommends 4+ compression level for better results"); - } - - if (compress_level > KNET_LZ4HC_MAX) { - log_warn(knet_h, KNET_SUB_LZ4HCCOMP, "lz4hc installed on this system supports up to compression level %d. Higher values behaves as %d", KNET_LZ4HC_MAX, KNET_LZ4HC_MAX); - } - - return 0; -} - -int lz4hc_compress( +static int lz4_decompress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int lzerr = 0, err = 0; int savederrno = 0; - lzerr = (*_int_LZ4_compress_HC)((const char *)buf_in, (char *)buf_out, buf_in_len, KNET_DATABUFSIZE_COMPRESS, knet_h->compress_level); - - /* - * data compressed - */ - if (lzerr > 0) { - *buf_out_len = lzerr; - } - - /* - * unable to compress - */ - if (lzerr <= 0) { - log_err(knet_h, KNET_SUB_LZ4HCCOMP, "lz4hc compression error: %d", lzerr); - savederrno = EINVAL; - err = -1; - } - - errno = savederrno; - return err; -} - -int lz4_decompress( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len) -{ - int lzerr = 0, err = 0; - int savederrno = 0; - - lzerr = (*_int_LZ4_decompress_safe)((const char *)buf_in, (char *)buf_out, buf_in_len, KNET_DATABUFSIZE); + lzerr = LZ4_decompress_safe((const char *)buf_in, (char *)buf_out, buf_in_len, KNET_DATABUFSIZE); if (lzerr < 0) { log_err(knet_h, KNET_SUB_LZ4COMP, "lz4 decompression error: %d", lzerr); savederrno = EINVAL; err = -1; } if (lzerr > 0) { *buf_out_len = lzerr; } errno = savederrno; return err; } -#endif + +compress_ops_t compress_model = { + KNET_COMPRESS_MODEL_ABI, + NULL, + NULL, + NULL, + lz4_val_level, + lz4_compress, + lz4_decompress +}; diff --git a/libknet/compress_lz4.h b/libknet/compress_lz4.h deleted file mode 100644 index 093136e0..00000000 --- a/libknet/compress_lz4.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2017 Red Hat, Inc. All rights reserved. - * - * Author: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+, LGPL-2.0+ - */ - -#ifndef __KNET_COMPRESS_LZ4_H__ -#define __KNET_COMPRESS_LZ4_H__ - -#include "internals.h" - -int lz4_load_lib( - knet_handle_t knet_h); - -int lz4_val_level( - knet_handle_t knet_h, - int compress_level); - -int lz4_compress( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - -int lz4hc_val_level( - knet_handle_t knet_h, - int compress_level); - -int lz4hc_compress( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - -int lz4_decompress( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - -#endif diff --git a/libknet/compress_lz4_remap.h b/libknet/compress_lz4_remap.h deleted file mode 100644 index 039cc9ad..00000000 --- a/libknet/compress_lz4_remap.h +++ /dev/null @@ -1,13 +0,0 @@ -#include "remap.h" - -REMAP_PROTO(int,LZ4_compress_HC, - (const char* src, char* dst, - int srcSize, int dstCapacity, - int compressionLevel)) -REMAP_PROTO(int,LZ4_compress_fast, - (const char* source, char* dest, - int sourceSize, int maxDestSize, - int acceleration)) -REMAP_PROTO(int,LZ4_decompress_safe, - (const char* source, char* dest, - int compressedSize, int maxDecompressedSize)) diff --git a/libknet/compress_lz4hc.c b/libknet/compress_lz4hc.c new file mode 100644 index 00000000..af14fd9e --- /dev/null +++ b/libknet/compress_lz4hc.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2017 Red Hat, Inc. All rights reserved. + * + * Author: Fabio M. Di Nitto + * + * This software licensed under GPL-2.0+, LGPL-2.0+ + */ +#define KNET_MODULE + +#include "config.h" + +#include +#include + +#include "logging.h" +#include "compress_model.h" + +#ifdef LZ4HC_CLEVEL_MAX +#define KNET_LZ4HC_MAX LZ4HC_CLEVEL_MAX +#endif +#ifdef LZ4HC_MAX_CLEVEL +#define KNET_LZ4HC_MAX LZ4HC_MAX_CLEVEL +#endif +#ifndef KNET_LZ4HC_MAX +#define KNET_LZ4HC_MAX 0 +#error Please check lz4hc.h for missing LZ4HC_CLEVEL_MAX or LZ4HC_MAX_CLEVEL variants +#endif + +static int lz4hc_val_level( + knet_handle_t knet_h, + int compress_level) +{ + if (compress_level < 1) { + log_err(knet_h, KNET_SUB_LZ4HCCOMP, "lz4hc supports only 1+ values for compression level"); + errno = EINVAL; + return -1; + } + + if (compress_level < 4) { + log_info(knet_h, KNET_SUB_LZ4HCCOMP, "lz4hc recommends 4+ compression level for better results"); + } + + if (compress_level > KNET_LZ4HC_MAX) { + log_warn(knet_h, KNET_SUB_LZ4HCCOMP, "lz4hc installed on this system supports up to compression level %d. Higher values behaves as %d", KNET_LZ4HC_MAX, KNET_LZ4HC_MAX); + } + + return 0; +} + +static int lz4hc_compress( + knet_handle_t knet_h, + const unsigned char *buf_in, + const ssize_t buf_in_len, + unsigned char *buf_out, + ssize_t *buf_out_len) +{ + int lzerr = 0, err = 0; + int savederrno = 0; + + lzerr = LZ4_compress_HC((const char *)buf_in, (char *)buf_out, buf_in_len, KNET_DATABUFSIZE_COMPRESS, knet_h->compress_level); + + /* + * data compressed + */ + if (lzerr > 0) { + *buf_out_len = lzerr; + } + + /* + * unable to compress + */ + if (lzerr <= 0) { + log_err(knet_h, KNET_SUB_LZ4HCCOMP, "lz4hc compression error: %d", lzerr); + savederrno = EINVAL; + err = -1; + } + + errno = savederrno; + return err; +} + +/* This is a straight copy from compress_lz4.c */ +static int lz4_decompress( + knet_handle_t knet_h, + const unsigned char *buf_in, + const ssize_t buf_in_len, + unsigned char *buf_out, + ssize_t *buf_out_len) +{ + int lzerr = 0, err = 0; + int savederrno = 0; + + lzerr = LZ4_decompress_safe((const char *)buf_in, (char *)buf_out, buf_in_len, KNET_DATABUFSIZE); + + if (lzerr < 0) { + log_err(knet_h, KNET_SUB_LZ4COMP, "lz4 decompression error: %d", lzerr); + savederrno = EINVAL; + err = -1; + } + + if (lzerr > 0) { + *buf_out_len = lzerr; + } + + errno = savederrno; + return err; +} + +compress_ops_t compress_model = { + KNET_COMPRESS_MODEL_ABI, + NULL, + NULL, + NULL, + lz4hc_val_level, + lz4hc_compress, + lz4_decompress +}; diff --git a/libknet/compress_lzma.c b/libknet/compress_lzma.c index 3ace3d07..ff15f4a9 100644 --- a/libknet/compress_lzma.c +++ b/libknet/compress_lzma.c @@ -1,177 +1,138 @@ /* * Copyright (C) 2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ +#define KNET_MODULE #include "config.h" -#include -#include #include -#include -#ifdef BUILDCOMPLZMA #include -#include "internals.h" -#include "compress_lzma.h" #include "logging.h" -#include "common.h" +#include "compress_model.h" -/* - * global vars for dlopen - */ -static void *lzma_lib; - -#include "compress_lzma_remap.h" - -static int lzma_remap_symbols(knet_handle_t knet_h) -{ -#define REMAP_WITH(name) remap_symbol (knet_h, KNET_SUB_LZMACOMP, lzma_lib, name) -#include "compress_lzma_remap.h" - return 0; - - fail: -#define REMAP_FAIL -#include "compress_lzma_remap.h" - errno = EINVAL; - return -1; -} - -int lzma_load_lib( - knet_handle_t knet_h) -{ - int err = 0, savederrno = 0; - - if (!lzma_lib) { - lzma_lib = open_lib(knet_h, LIBLZMA_5, 0); - if (!lzma_lib) { - savederrno = EAGAIN; - err = -1; - goto out; - } - } - - if (lzma_remap_symbols(knet_h) < 0) { - savederrno = errno; - err = -1; - } -out: - errno = savederrno; - return err; -} - -int lzma_val_level( +static int lzma_val_level( knet_handle_t knet_h, int compress_level) { if ((compress_level < 0) || (compress_level > 9)) { log_err(knet_h, KNET_SUB_LZMACOMP, "lzma unsupported compression preset %d (accepted values from 0 to 9)", compress_level); errno = EINVAL; return -1; } return 0; } -int lzma_compress( +static int lzma_compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int err = 0; int savederrno = 0; size_t out_pos = 0; lzma_ret ret = 0; - ret = (*_int_lzma_easy_buffer_encode)(knet_h->compress_level, LZMA_CHECK_NONE, NULL, - (const uint8_t *)buf_in, buf_in_len, - (uint8_t *)buf_out, &out_pos, KNET_DATABUFSIZE_COMPRESS); + ret = lzma_easy_buffer_encode(knet_h->compress_level, LZMA_CHECK_NONE, NULL, + (const uint8_t *)buf_in, buf_in_len, + (uint8_t *)buf_out, &out_pos, KNET_DATABUFSIZE_COMPRESS); switch(ret) { case LZMA_OK: *buf_out_len = out_pos; break; case LZMA_MEM_ERROR: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma compress memory allocation failed"); savederrno = ENOMEM; err = -1; break; case LZMA_MEMLIMIT_ERROR: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma compress requires higher memory boundaries (see lzma_memlimit_set)"); savederrno = ENOMEM; err = -1; break; case LZMA_PROG_ERROR: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma compress has been called with incorrect options"); savederrno = EINVAL; err = -1; break; default: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma compress unknown error %u", ret); savederrno = EINVAL; err = -1; break; } errno = savederrno; return err; } -int lzma_decompress( +static int lzma_decompress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int err = 0; int savederrno = 0; uint64_t memlimit = UINT64_MAX; /* disable lzma internal memlimit check */ size_t out_pos = 0, in_pos = 0; lzma_ret ret = 0; - ret = (*_int_lzma_stream_buffer_decode)(&memlimit, 0, NULL, - (const uint8_t *)buf_in, &in_pos, buf_in_len, - (uint8_t *)buf_out, &out_pos, KNET_DATABUFSIZE_COMPRESS); + ret = lzma_stream_buffer_decode(&memlimit, 0, NULL, + (const uint8_t *)buf_in, &in_pos, buf_in_len, + (uint8_t *)buf_out, &out_pos, KNET_DATABUFSIZE_COMPRESS); switch(ret) { case LZMA_OK: *buf_out_len = out_pos; break; case LZMA_MEM_ERROR: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma decompress memory allocation failed"); savederrno = ENOMEM; err = -1; break; case LZMA_MEMLIMIT_ERROR: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma decompress requires higher memory boundaries (see lzma_memlimit_set)"); savederrno = ENOMEM; err = -1; break; case LZMA_DATA_ERROR: case LZMA_FORMAT_ERROR: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma decompress invalid data received"); savederrno = EINVAL; err = -1; break; case LZMA_PROG_ERROR: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma decompress has been called with incorrect options"); savederrno = EINVAL; err = -1; break; default: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma decompress unknown error %u", ret); savederrno = EINVAL; err = -1; break; } errno = savederrno; return err; } -#endif + +compress_ops_t compress_model = { + KNET_COMPRESS_MODEL_ABI, + NULL, + NULL, + NULL, + lzma_val_level, + lzma_compress, + lzma_decompress +}; diff --git a/libknet/compress_lzma.h b/libknet/compress_lzma.h deleted file mode 100644 index f5f155d9..00000000 --- a/libknet/compress_lzma.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2017 Red Hat, Inc. All rights reserved. - * - * Author: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+, LGPL-2.0+ - */ - -#ifndef __KNET_COMPRESS_LZMA_H__ -#define __KNET_COMPRESS_LZMA_H__ - -#include "internals.h" - -int lzma_load_lib( - knet_handle_t knet_h); - -int lzma_val_level( - knet_handle_t knet_h, - int compress_level); - -int lzma_compress( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - -int lzma_decompress( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - -#endif diff --git a/libknet/compress_lzma_remap.h b/libknet/compress_lzma_remap.h deleted file mode 100644 index 780ebd53..00000000 --- a/libknet/compress_lzma_remap.h +++ /dev/null @@ -1,12 +0,0 @@ -#include "remap.h" - -REMAP_PROTO(LZMA_API(lzma_ret),lzma_easy_buffer_encode, - (uint32_t preset, lzma_check check, - const lzma_allocator *allocator, - const uint8_t *in, size_t in_size, - uint8_t *out, size_t *out_pos, size_t out_size)) -REMAP_PROTO(LZMA_API(lzma_ret),lzma_stream_buffer_decode, - (uint64_t *memlimit, uint32_t flags, - const lzma_allocator *allocator, - const uint8_t *in, size_t *in_pos, size_t in_size, - uint8_t *out, size_t *out_pos, size_t out_size)) diff --git a/libknet/compress_lzo2.c b/libknet/compress_lzo2.c index e3476519..a1de3f0d 100644 --- a/libknet/compress_lzo2.c +++ b/libknet/compress_lzo2.c @@ -1,202 +1,165 @@ /* * Copyright (C) 2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ +#define KNET_MODULE #include "config.h" -#include #include +#include #include -#include -#ifdef BUILDCOMPLZO2 #include -#include "internals.h" -#include "compress_lzo2.h" #include "logging.h" -#include "common.h" - -/* - * global vars for dlopen - */ -static void *lzo2_lib; - -#include "compress_lzo2_remap.h" - -static int lzo2_remap_symbols(knet_handle_t knet_h) -{ -#define REMAP_WITH(name) remap_symbol (knet_h, KNET_SUB_LZO2COMP, lzo2_lib, name) -#include "compress_lzo2_remap.h" - return 0; - - fail: -#define REMAP_FAIL -#include "compress_lzo2_remap.h" - errno = EINVAL; - return -1; -} +#include "compress_model.h" -int lzo2_load_lib( - knet_handle_t knet_h) -{ - int err = 0, savederrno = 0; - - if (!lzo2_lib) { - lzo2_lib = open_lib(knet_h, LIBLZO2_2, 0); - if (!lzo2_lib) { - savederrno = EAGAIN; - err = -1; - goto out; - } - } - - if (lzo2_remap_symbols(knet_h) < 0) { - savederrno = errno; - err = -1; - } -out: - errno = savederrno; - return err; -} - -int lzo2_is_init( +static int lzo2_is_init( knet_handle_t knet_h, int method_idx) { if (knet_h->compress_int_data[method_idx]) { return 1; } return 0; } -int lzo2_init( +static int lzo2_init( knet_handle_t knet_h, int method_idx) { /* * LZO1X_999_MEM_COMPRESS is the highest amount of memory lzo2 can use */ if (!knet_h->compress_int_data[method_idx]) { knet_h->compress_int_data[method_idx] = malloc(LZO1X_999_MEM_COMPRESS); if (!knet_h->compress_int_data[method_idx]) { log_err(knet_h, KNET_SUB_LZO2COMP, "lzo2 unable to allocate work memory"); errno = ENOMEM; return -1; } memset(knet_h->compress_int_data[method_idx], 0, LZO1X_999_MEM_COMPRESS); } return 0; } -void lzo2_fini( +static void lzo2_fini( knet_handle_t knet_h, int method_idx) { if (knet_h->compress_int_data[method_idx]) { free(knet_h->compress_int_data[method_idx]); knet_h->compress_int_data[method_idx] = NULL; } return; } -int lzo2_val_level( +static int lzo2_val_level( knet_handle_t knet_h, int compress_level) { switch(compress_level) { case 1: log_debug(knet_h, KNET_SUB_LZO2COMP, "lzo2 will use lzo1x_1_compress internal compress method"); break; case 11: log_debug(knet_h, KNET_SUB_LZO2COMP, "lzo2 will use lzo1x_1_11_compress internal compress method"); break; case 12: log_debug(knet_h, KNET_SUB_LZO2COMP, "lzo2 will use lzo1x_1_12_compress internal compress method"); break; case 15: log_debug(knet_h, KNET_SUB_LZO2COMP, "lzo2 will use lzo1x_1_15_compress internal compress method"); break; case 999: log_debug(knet_h, KNET_SUB_LZO2COMP, "lzo2 will use lzo1x_999_compress internal compress method"); break; default: log_warn(knet_h, KNET_SUB_LZO2COMP, "Unknown lzo2 internal compress method. lzo1x_1_compress will be used as default fallback"); break; } return 0; } -int lzo2_compress( +static int lzo2_compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int savederrno = 0, lzerr = 0, err = 0; lzo_uint cmp_len; switch(knet_h->compress_level) { case 1: - lzerr = (*_int_lzo1x_1_compress)(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); + lzerr = lzo1x_1_compress(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); break; case 11: - lzerr = (*_int_lzo1x_1_11_compress)(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); + lzerr = lzo1x_1_11_compress(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); break; case 12: - lzerr = (*_int_lzo1x_1_12_compress)(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); + lzerr = lzo1x_1_12_compress(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); break; case 15: - lzerr = (*_int_lzo1x_1_15_compress)(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); + lzerr = lzo1x_1_15_compress(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); break; case 999: - lzerr = (*_int_lzo1x_999_compress)(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); + lzerr = lzo1x_999_compress(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); break; default: - lzerr = (*_int_lzo1x_1_compress)(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); + lzerr = lzo1x_1_compress(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); break; } if (lzerr != LZO_E_OK) { log_err(knet_h, KNET_SUB_LZO2COMP, "lzo2 internal compression error"); savederrno = EAGAIN; err = -1; } else { *buf_out_len = cmp_len; } errno = savederrno; return err; } -int lzo2_decompress( +static int lzo2_decompress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int lzerr = 0, err = 0; int savederrno = 0; lzo_uint decmp_len; - lzerr = (*_int_lzo1x_decompress)(buf_in, buf_in_len, buf_out, &decmp_len, NULL); + lzerr = lzo1x_decompress(buf_in, buf_in_len, buf_out, &decmp_len, NULL); if (lzerr != LZO_E_OK) { log_err(knet_h, KNET_SUB_LZO2COMP, "lzo2 internal decompression error"); savederrno = EAGAIN; err = -1; } else { *buf_out_len = decmp_len; } errno = savederrno; return err; } -#endif + +compress_ops_t compress_model = { + KNET_COMPRESS_MODEL_ABI, + lzo2_is_init, + lzo2_init, + lzo2_fini, + lzo2_val_level, + lzo2_compress, + lzo2_decompress +}; diff --git a/libknet/compress_lzo2.h b/libknet/compress_lzo2.h deleted file mode 100644 index 990e63bf..00000000 --- a/libknet/compress_lzo2.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2017 Red Hat, Inc. All rights reserved. - * - * Author: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+, LGPL-2.0+ - */ - -#ifndef __KNET_COMPRESS_LZO2_H__ -#define __KNET_COMPRESS_LZO2_H__ - -#include "internals.h" - -int lzo2_load_lib( - knet_handle_t knet_h); - -int lzo2_is_init( - knet_handle_t knet_h, - int method_idx); - -int lzo2_init( - knet_handle_t knet_h, - int method_idx); - -void lzo2_fini( - knet_handle_t knet_h, - int method_idx); - -int lzo2_val_level( - knet_handle_t knet_h, - int compress_level); - -int lzo2_compress( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - -int lzo2_decompress( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - -#endif diff --git a/libknet/compress_lzo2_remap.h b/libknet/compress_lzo2_remap.h deleted file mode 100644 index c0c7d2b7..00000000 --- a/libknet/compress_lzo2_remap.h +++ /dev/null @@ -1,26 +0,0 @@ -#include "remap.h" - -REMAP_PROTO(int,lzo1x_decompress, - (const lzo_bytep src, lzo_uint src_len, - lzo_bytep dst, lzo_uintp dst_len, - lzo_voidp wrkmem /* NOT USED */ )) -REMAP_PROTO(int,lzo1x_1_compress, - (const lzo_bytep src, lzo_uint src_len, - lzo_bytep dst, lzo_uintp dst_len, - lzo_voidp wrkmem)) -REMAP_PROTO(int,lzo1x_1_11_compress, - (const lzo_bytep src, lzo_uint src_len, - lzo_bytep dst, lzo_uintp dst_len, - lzo_voidp wrkmem)) -REMAP_PROTO(int,lzo1x_1_12_compress, - (const lzo_bytep src, lzo_uint src_len, - lzo_bytep dst, lzo_uintp dst_len, - lzo_voidp wrkmem)) -REMAP_PROTO(int,lzo1x_1_15_compress, - (const lzo_bytep src, lzo_uint src_len, - lzo_bytep dst, lzo_uintp dst_len, - lzo_voidp wrkmem)) -REMAP_PROTO(int,lzo1x_999_compress, - (const lzo_bytep src, lzo_uint src_len, - lzo_bytep dst, lzo_uintp dst_len, - lzo_voidp wrkmem)) diff --git a/libknet/compress.h b/libknet/compress_model.h similarity index 72% copy from libknet/compress.h copy to libknet/compress_model.h index 717698d8..c99de1be 100644 --- a/libknet/compress.h +++ b/libknet/compress_model.h @@ -1,118 +1,91 @@ /* * Copyright (C) 2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ -#ifndef __KNET_COMPRESS_H__ -#define __KNET_COMPRESS_H__ +#ifndef __KNET_COMPRESS_MODEL_H__ +#define __KNET_COMPRESS_MODEL_H__ #include "internals.h" -typedef struct { - const char *model_name; - uint8_t model_id; /* sequencial unique identifier */ - uint8_t built_in; /* set at configure/build time to 1 if available */ - - /* - * shared lib load functions - * - * both are called in shlib_rwlock write context and should - * update the loaded status below. - */ - int (*load_lib) (knet_handle_t knet_h); +#define KNET_COMPRESS_MODEL_ABI 1 - /* - * library is loaded - */ - uint8_t loaded; - - /* - * runtime bits - */ +typedef struct { + uint8_t abi_ver; /* * some libs need special init and handling of buffers etc. * is_init is called in shlib_rwlock read only context to see if * the module has been initialized within this knet_handle. * Providing is_init is optional. A module that does not export * an is_init and if the associated shared library is already loaded * is treated as "does not require init". */ int (*is_init) (knet_handle_t knet_h, int method_idx); /* * init is called when the library requires special init handling, * such as memory allocation and such. * init is invoked in shlib_rwlock write only context when * the module exports this function. * It is optional to provide an init function if the module * does not require any init. */ int (*init) (knet_handle_t knet_h, int method_idx); /* * fini is invoked only on knet_handle_free in a write only context. * It is optional to provide this function if the module * does not require any finalization */ void (*fini) (knet_handle_t knet_h, int method_idx); /* * runtime config validation and compress/decompress */ /* * required functions * * val_level is called upon compress configuration changes * to make sure that the requested compress_level is valid * within the context of a given module. */ int (*val_level)(knet_handle_t knet_h, int compress_level); /* * hopefully those 2 don't require any explanation.... */ int (*compress) (knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int (*decompress)(knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); -} compress_model_t; - -int compress_cfg( - knet_handle_t knet_h, - struct knet_handle_compress_cfg *knet_handle_compress_cfg); - -int compress_init( - knet_handle_t knet_h); +} compress_ops_t; -void compress_fini( - knet_handle_t knet_h, - int all); +typedef struct { + const char *model_name; + uint8_t model_id; /* sequential unique identifier */ + uint8_t built_in; /* set at configure/build time to 1 if available */ -int compress( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); + /* + * library is loaded + */ + uint8_t loaded; -int decompress( - knet_handle_t knet_h, - int compress_model, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); + /* + * runtime bits + */ + compress_ops_t *ops; +} compress_model_t; #endif diff --git a/libknet/compress_zlib.c b/libknet/compress_zlib.c index 76a7d04e..dc5e42e2 100644 --- a/libknet/compress_zlib.c +++ b/libknet/compress_zlib.c @@ -1,175 +1,136 @@ /* * Copyright (C) 2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ +#define KNET_MODULE #include "config.h" -#include -#include #include -#include -#ifdef BUILDCOMPZLIB #include -#include "internals.h" -#include "compress_zlib.h" #include "logging.h" -#include "common.h" +#include "compress_model.h" -/* - * global vars for dlopen - */ -static void *zlib_lib; - -#include "compress_zlib_remap.h" - -static int zlib_remap_symbols(knet_handle_t knet_h) -{ -#define REMAP_WITH(name) remap_symbol (knet_h, KNET_SUB_ZLIBCOMP, zlib_lib, name) -#include "compress_zlib_remap.h" - return 0; - - fail: -#define REMAP_FAIL -#include "compress_zlib_remap.h" - errno = EINVAL; - return -1; -} - -int zlib_load_lib( - knet_handle_t knet_h) -{ - int err = 0, savederrno = 0; - - if (!zlib_lib) { - zlib_lib = open_lib(knet_h, LIBZ_1, 0); - if (!zlib_lib) { - savederrno = EAGAIN; - err = -1; - goto out; - } - } - - if (zlib_remap_symbols(knet_h) < 0) { - savederrno = errno; - err = -1; - } -out: - errno = savederrno; - return err; -} - -int zlib_val_level( +static int zlib_val_level( knet_handle_t knet_h, int compress_level) { if (compress_level < 0) { log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib does not support negative compression level %d", compress_level); return -1; } if (compress_level > 9) { log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib does not support compression level higher than 9"); return -1; } if (compress_level == 0) { log_warn(knet_h, KNET_SUB_ZLIBCOMP, "zlib compress level 0 does NOT perform any compression"); } return 0; } -int zlib_compress( +static int zlib_compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int zerr = 0, err = 0; int savederrno = 0; uLongf destLen = *buf_out_len; - zerr = (*_int_compress2)(buf_out, &destLen, - buf_in, buf_in_len, - knet_h->compress_level); + zerr = compress2(buf_out, &destLen, + buf_in, buf_in_len, + knet_h->compress_level); *buf_out_len = destLen; switch(zerr) { case Z_OK: err = 0; savederrno = 0; break; case Z_MEM_ERROR: log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib compress mem error"); err = -1; savederrno = ENOMEM; break; case Z_BUF_ERROR: log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib compress buf error"); err = -1; savederrno = ENOBUFS; break; case Z_STREAM_ERROR: log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib compress stream error"); err = -1; savederrno = EINVAL; break; default: log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib unknown compress error: %d", zerr); break; } errno = savederrno; return err; } -int zlib_decompress( +static int zlib_decompress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int zerr = 0, err = 0; int savederrno = 0; uLongf destLen = *buf_out_len; - zerr = (*_int_uncompress)(buf_out, &destLen, - buf_in, buf_in_len); + zerr = uncompress(buf_out, &destLen, + buf_in, buf_in_len); *buf_out_len = destLen; switch(zerr) { case Z_OK: err = 0; savederrno = 0; break; case Z_MEM_ERROR: log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib decompress mem error"); err = -1; savederrno = ENOMEM; break; case Z_BUF_ERROR: log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib decompress buf error"); err = -1; savederrno = ENOBUFS; break; case Z_DATA_ERROR: log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib decompress data error"); err = -1; savederrno = EINVAL; break; default: log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib unknown decompress error: %d", zerr); break; } errno = savederrno; return err; } -#endif + +compress_ops_t compress_model = { + KNET_COMPRESS_MODEL_ABI, + NULL, + NULL, + NULL, + zlib_val_level, + zlib_compress, + zlib_decompress +}; diff --git a/libknet/compress_zlib.h b/libknet/compress_zlib.h deleted file mode 100644 index 26791633..00000000 --- a/libknet/compress_zlib.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2017 Red Hat, Inc. All rights reserved. - * - * Author: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+, LGPL-2.0+ - */ - -#ifndef __KNET_COMPRESS_ZLIB_H__ -#define __KNET_COMPRESS_ZLIB_H__ - -#include "internals.h" - -int zlib_load_lib( - knet_handle_t knet_h); - -int zlib_val_level( - knet_handle_t knet_h, - int compress_level); - -int zlib_compress( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - -int zlib_decompress( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - -#endif diff --git a/libknet/compress_zlib_remap.h b/libknet/compress_zlib_remap.h deleted file mode 100644 index 7ff16e67..00000000 --- a/libknet/compress_zlib_remap.h +++ /dev/null @@ -1,9 +0,0 @@ -#include "remap.h" - -REMAP_PROTO(int,uncompress, - (Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)) -REMAP_PROTO(int,compress2, - (Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)) diff --git a/libknet/crypto.c b/libknet/crypto.c index 1d429dea..ede40c2b 100644 --- a/libknet/crypto.c +++ b/libknet/crypto.c @@ -1,210 +1,207 @@ /* * Copyright (C) 2012-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include #include #include #include #include "crypto.h" -#include "crypto_nss.h" -#include "crypto_openssl.h" +#include "crypto_model.h" #include "internals.h" #include "logging.h" +#include "common.h" /* * internal module switch data */ -#define empty_module NULL, 0, NULL, NULL, NULL, NULL, NULL }, - crypto_model_t crypto_modules_cmds[] = { - { "nss", -#ifdef BUILDCRYPTONSS - 1, nsscrypto_load_lib, 0, nsscrypto_init, nsscrypto_fini, nsscrypto_encrypt_and_sign, nsscrypto_encrypt_and_signv, nsscrypto_authenticate_and_decrypt }, -#else - 0,empty_module -#endif - { "openssl", -#ifdef BUILDCRYPTOOPENSSL - 1, opensslcrypto_load_lib, 0, opensslcrypto_init, opensslcrypto_fini, opensslcrypto_encrypt_and_sign, opensslcrypto_encrypt_and_signv, opensslcrypto_authenticate_and_decrypt }, -#else - 0,empty_module -#endif - { NULL, 0, empty_module + { "nss", WITH_CRYPTO_NSS, 0, NULL }, + { "openssl", WITH_CRYPTO_OPENSSL, 0, NULL }, + { NULL, 0, 0, NULL } }; static int crypto_get_model(const char *model) { int idx = 0; while (crypto_modules_cmds[idx].model_name != NULL) { if (!strcmp(crypto_modules_cmds[idx].model_name, model)) return idx; idx++; } return -1; } /* * exported API */ int crypto_encrypt_and_sign ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { - return crypto_modules_cmds[knet_h->crypto_instance->model].crypt(knet_h, buf_in, buf_in_len, buf_out, buf_out_len); + return crypto_modules_cmds[knet_h->crypto_instance->model].ops->crypt(knet_h, buf_in, buf_in_len, buf_out, buf_out_len); } int crypto_encrypt_and_signv ( knet_handle_t knet_h, const struct iovec *iov_in, int iovcnt_in, unsigned char *buf_out, ssize_t *buf_out_len) { - return crypto_modules_cmds[knet_h->crypto_instance->model].cryptv(knet_h, iov_in, iovcnt_in, buf_out, buf_out_len); + return crypto_modules_cmds[knet_h->crypto_instance->model].ops->cryptv(knet_h, iov_in, iovcnt_in, buf_out, buf_out_len); } int crypto_authenticate_and_decrypt ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { - return crypto_modules_cmds[knet_h->crypto_instance->model].decrypt(knet_h, buf_in, buf_in_len, buf_out, buf_out_len); + return crypto_modules_cmds[knet_h->crypto_instance->model].ops->decrypt(knet_h, buf_in, buf_in_len, buf_out, buf_out_len); } int crypto_init( knet_handle_t knet_h, struct knet_handle_crypto_cfg *knet_handle_crypto_cfg) { int savederrno = 0; int model = 0; model = crypto_get_model(knet_handle_crypto_cfg->crypto_model); if (model < 0) { log_err(knet_h, KNET_SUB_CRYPTO, "model %s not supported", knet_handle_crypto_cfg->crypto_model); return -1; } if (crypto_modules_cmds[model].built_in == 0) { log_err(knet_h, KNET_SUB_CRYPTO, "this version of libknet was built without %s support. Please contact your vendor or fix the build.", knet_handle_crypto_cfg->crypto_model); return -1; } savederrno = pthread_rwlock_wrlock(&shlib_rwlock); if (savederrno) { log_err(knet_h, KNET_SUB_CRYPTO, "Unable to get write lock: %s", strerror(savederrno)); return -1; } if (!crypto_modules_cmds[model].loaded) { - if (crypto_modules_cmds[model].load_lib(knet_h) < 0) { + crypto_modules_cmds[model].ops = load_module (knet_h, "crypto", crypto_modules_cmds[model].model_name); + if (!crypto_modules_cmds[model].ops) { log_err(knet_h, KNET_SUB_CRYPTO, "Unable to load %s lib", crypto_modules_cmds[model].model_name); goto out_err; } + if (crypto_modules_cmds[model].ops->abi_ver != KNET_CRYPTO_MODEL_ABI) { + log_err(knet_h, KNET_SUB_CRYPTO, + "ABI mismatch loading module %s. knet ver: %d, module ver: %d", + crypto_modules_cmds[model].model_name, KNET_CRYPTO_MODEL_ABI, + crypto_modules_cmds[model].ops->abi_ver); + errno = EINVAL; + goto out_err; + } crypto_modules_cmds[model].loaded = 1; } log_debug(knet_h, KNET_SUB_CRYPTO, "Initizializing crypto module [%s/%s/%s]", knet_handle_crypto_cfg->crypto_model, knet_handle_crypto_cfg->crypto_cipher_type, knet_handle_crypto_cfg->crypto_hash_type); knet_h->crypto_instance = malloc(sizeof(struct crypto_instance)); if (!knet_h->crypto_instance) { log_err(knet_h, KNET_SUB_CRYPTO, "Unable to allocate memory for crypto instance"); pthread_rwlock_unlock(&shlib_rwlock); goto out_err; } /* - * if crypto_modules_cmds.init fails, it is expected that + * if crypto_modules_cmds.ops->init fails, it is expected that * it will clean everything by itself. - * crypto_modules_cmds.fini is not invoked on error. + * crypto_modules_cmds.ops->fini is not invoked on error. */ knet_h->crypto_instance->model = model; - if (crypto_modules_cmds[knet_h->crypto_instance->model].init(knet_h, knet_handle_crypto_cfg)) + if (crypto_modules_cmds[knet_h->crypto_instance->model].ops->init(knet_h, knet_handle_crypto_cfg)) goto out_err; log_debug(knet_h, KNET_SUB_CRYPTO, "security network overhead: %zu", knet_h->sec_header_size); pthread_rwlock_unlock(&shlib_rwlock); return 0; out_err: if (knet_h->crypto_instance) { free(knet_h->crypto_instance); knet_h->crypto_instance = NULL; } pthread_rwlock_unlock(&shlib_rwlock); return -1; } void crypto_fini( knet_handle_t knet_h) { int savederrno = 0; int model = 0; savederrno = pthread_rwlock_wrlock(&shlib_rwlock); if (savederrno) { log_err(knet_h, KNET_SUB_CRYPTO, "Unable to get write lock: %s", strerror(savederrno)); return; } if (knet_h->crypto_instance) { model = knet_h->crypto_instance->model; - if (crypto_modules_cmds[model].fini != NULL) { - crypto_modules_cmds[model].fini(knet_h); + if (crypto_modules_cmds[model].ops->fini != NULL) { + crypto_modules_cmds[model].ops->fini(knet_h); } free(knet_h->crypto_instance); knet_h->crypto_instance = NULL; } pthread_rwlock_unlock(&shlib_rwlock); return; } int knet_get_crypto_list(struct knet_crypto_info *crypto_list, size_t *crypto_list_entries) { int err = 0; int idx = 0; int outidx = 0; if (!crypto_list_entries) { errno = EINVAL; return -1; } while (crypto_modules_cmds[idx].model_name != NULL) { if (crypto_modules_cmds[idx].built_in) { if (crypto_list) { crypto_list[outidx].name = crypto_modules_cmds[idx].model_name; } outidx++; } idx++; } *crypto_list_entries = outidx; return err; } diff --git a/libknet/crypto.h b/libknet/crypto.h index 2208de84..fbc5d0e1 100644 --- a/libknet/crypto.h +++ b/libknet/crypto.h @@ -1,77 +1,42 @@ /* * Copyright (C) 2012-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #ifndef __KNET_CRYPTO_H__ #define __KNET_CRYPTO_H__ #include "internals.h" -struct crypto_instance { - int model; - void *model_instance; -}; - -typedef struct { - const char *model_name; - uint8_t built_in; - - /* - * see compress.h for explanation of the various lib related functions - */ - int (*load_lib) (knet_handle_t knet_h); - uint8_t loaded; - - int (*init) (knet_handle_t knet_h, - struct knet_handle_crypto_cfg *knet_handle_crypto_cfg); - void (*fini) (knet_handle_t knet_h); - int (*crypt) (knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - int (*cryptv) (knet_handle_t knet_h, - const struct iovec *iov_in, - int iovcnt_in, - unsigned char *buf_out, - ssize_t *buf_out_len); - int (*decrypt) (knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); -} crypto_model_t; - int crypto_authenticate_and_decrypt ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int crypto_encrypt_and_sign ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int crypto_encrypt_and_signv ( knet_handle_t knet_h, const struct iovec *iov_in, int iovcnt_in, unsigned char *buf_out, ssize_t *buf_out_len); int crypto_init( knet_handle_t knet_h, struct knet_handle_crypto_cfg *knet_handle_crypto_cfg); void crypto_fini( knet_handle_t knet_h); #endif diff --git a/libknet/crypto_canary.c b/libknet/crypto_canary.c deleted file mode 100644 index 1555694c..00000000 --- a/libknet/crypto_canary.c +++ /dev/null @@ -1,24 +0,0 @@ -/* Transform the binary into dependencies like: - * dpkg-shlibdeps -pcrypto -dRecommends -xlibc6 -elibknet/crypto_canary -O | sed 's/,/ |/g' >>debian/substvars - */ - -#include "config.h" - -#define CANARY - -#include "crypto_nss_remap.h" -#include "crypto_openssl_remap.h" - -#define CANARY_CALL - -int main (void) -{ - return -#ifdef BUILDCRYPTONSS -#include "crypto_nss_remap.h" -#endif -#ifdef BUILDCRYPTOOPENSSL -#include "crypto_openssl_remap.h" -#endif - 0; -} diff --git a/libknet/crypto.h b/libknet/crypto_model.h similarity index 55% copy from libknet/crypto.h copy to libknet/crypto_model.h index 2208de84..c973d9e7 100644 --- a/libknet/crypto.h +++ b/libknet/crypto_model.h @@ -1,77 +1,53 @@ /* * Copyright (C) 2012-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ -#ifndef __KNET_CRYPTO_H__ -#define __KNET_CRYPTO_H__ +#ifndef __KNET_CRYPTO_MODEL_H__ +#define __KNET_CRYPTO_MODEL_H__ #include "internals.h" struct crypto_instance { int model; void *model_instance; }; -typedef struct { - const char *model_name; - uint8_t built_in; - - /* - * see compress.h for explanation of the various lib related functions - */ - int (*load_lib) (knet_handle_t knet_h); - uint8_t loaded; +#define KNET_CRYPTO_MODEL_ABI 1 +/* + * see compress_model.h for explanation of the various lib related functions + */ +typedef struct { + uint8_t abi_ver; int (*init) (knet_handle_t knet_h, struct knet_handle_crypto_cfg *knet_handle_crypto_cfg); void (*fini) (knet_handle_t knet_h); int (*crypt) (knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int (*cryptv) (knet_handle_t knet_h, const struct iovec *iov_in, int iovcnt_in, unsigned char *buf_out, ssize_t *buf_out_len); int (*decrypt) (knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); -} crypto_model_t; +} crypto_ops_t; -int crypto_authenticate_and_decrypt ( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - -int crypto_encrypt_and_sign ( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - -int crypto_encrypt_and_signv ( - knet_handle_t knet_h, - const struct iovec *iov_in, - int iovcnt_in, - unsigned char *buf_out, - ssize_t *buf_out_len); - -int crypto_init( - knet_handle_t knet_h, - struct knet_handle_crypto_cfg *knet_handle_crypto_cfg); - -void crypto_fini( - knet_handle_t knet_h); +typedef struct { + const char *model_name; + uint8_t built_in; + uint8_t loaded; + crypto_ops_t *ops; +} crypto_model_t; #endif diff --git a/libknet/crypto_nss.c b/libknet/crypto_nss.c index 2b5a7314..077a3b85 100644 --- a/libknet/crypto_nss.c +++ b/libknet/crypto_nss.c @@ -1,856 +1,810 @@ /* * Copyright (C) 2012-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ +#define KNET_MODULE #include "config.h" #include -#include #include -#ifdef BUILDCRYPTONSS #include #include #include #include #include #include #include #include #include #include -#include "common.h" -#include "crypto.h" -#include "crypto_nss.h" +#include "crypto_model.h" #include "logging.h" -/* - * global vars for dlopen - */ -static void *nss_lib; - -#include "crypto_nss_remap.h" - -static int nsscrypto_remap_symbols(knet_handle_t knet_h) -{ -#define REMAP_WITH(name) remap_symbol (knet_h, KNET_SUB_NSSCRYPTO, nss_lib, name) -#include "crypto_nss_remap.h" - return 0; - - fail: -#define REMAP_FAIL -#include "crypto_nss_remap.h" - errno = EINVAL; - return -1; -} - static int nss_db_is_init = 0; -static int at_exit_registered = 0; static void nss_atexit_handler(void) { if (nss_db_is_init) { - if (_int_NSS_Shutdown) { - (*_int_NSS_Shutdown)(); - } - if ((_int_PR_Initialized) && ((*_int_PR_Initialized)())) { - if (_int_PL_ArenaFinish) { - (*_int_PL_ArenaFinish)(); - } - if (_int_PR_Cleanup) { - (*_int_PR_Cleanup)(); - } + NSS_Shutdown(); + if (PR_Initialized()) { + PL_ArenaFinish(); + PR_Cleanup(); } } return; } -int nsscrypto_load_lib( - knet_handle_t knet_h) -{ - int err = 0, savederrno = 0; - - if (!nss_lib) { - nss_lib = open_lib(knet_h, LIBNSS3, 0); - if (!nss_lib) { - savederrno = errno; - err = -1; - goto out; - } - } - - if (nsscrypto_remap_symbols(knet_h) < 0) { - savederrno = errno; - err = -1; - goto out; - } - - if (!at_exit_registered) { - if (atexit(nss_atexit_handler)) { - log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to register NSS atexit handler"); - savederrno = EAGAIN; - err = -1; - goto out; - } - at_exit_registered = 1; - } - - if ((nss_lib) && (_int_NSS_NoDB_Init) && (!nss_db_is_init)) { - if ((*_int_NSS_NoDB_Init)(".") != SECSuccess) { - log_err(knet_h, KNET_SUB_NSSCRYPTO, "NSS DB initialization failed (err %d): %s", - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); - savederrno = EAGAIN; - err = -1; - goto out; - } - nss_db_is_init = 1; - } -out: - errno = savederrno; - return err; -} - /* * crypto definitions and conversion tables */ #define SALT_SIZE 16 /* * This are defined in new NSS. For older one, we will define our own */ #ifndef AES_256_KEY_LENGTH #define AES_256_KEY_LENGTH 32 #endif #ifndef AES_192_KEY_LENGTH #define AES_192_KEY_LENGTH 24 #endif #ifndef AES_128_KEY_LENGTH #define AES_128_KEY_LENGTH 16 #endif enum nsscrypto_crypt_t { CRYPTO_CIPHER_TYPE_NONE = 0, CRYPTO_CIPHER_TYPE_AES256 = 1, CRYPTO_CIPHER_TYPE_AES192 = 2, CRYPTO_CIPHER_TYPE_AES128 = 3, CRYPTO_CIPHER_TYPE_3DES = 4 }; CK_MECHANISM_TYPE cipher_to_nss[] = { 0, /* CRYPTO_CIPHER_TYPE_NONE */ CKM_AES_CBC_PAD, /* CRYPTO_CIPHER_TYPE_AES256 */ CKM_AES_CBC_PAD, /* CRYPTO_CIPHER_TYPE_AES192 */ CKM_AES_CBC_PAD, /* CRYPTO_CIPHER_TYPE_AES128 */ CKM_DES3_CBC_PAD /* CRYPTO_CIPHER_TYPE_3DES */ }; size_t nsscipher_key_len[] = { 0, /* CRYPTO_CIPHER_TYPE_NONE */ AES_256_KEY_LENGTH, /* CRYPTO_CIPHER_TYPE_AES256 */ AES_192_KEY_LENGTH, /* CRYPTO_CIPHER_TYPE_AES192 */ AES_128_KEY_LENGTH, /* CRYPTO_CIPHER_TYPE_AES128 */ 24 /* CRYPTO_CIPHER_TYPE_3DES */ }; size_t nsscypher_block_len[] = { 0, /* CRYPTO_CIPHER_TYPE_NONE */ AES_BLOCK_SIZE, /* CRYPTO_CIPHER_TYPE_AES256 */ AES_BLOCK_SIZE, /* CRYPTO_CIPHER_TYPE_AES192 */ AES_BLOCK_SIZE, /* CRYPTO_CIPHER_TYPE_AES128 */ 0 /* CRYPTO_CIPHER_TYPE_3DES */ }; /* * hash definitions and conversion tables */ enum nsscrypto_hash_t { CRYPTO_HASH_TYPE_NONE = 0, CRYPTO_HASH_TYPE_MD5 = 1, CRYPTO_HASH_TYPE_SHA1 = 2, CRYPTO_HASH_TYPE_SHA256 = 3, CRYPTO_HASH_TYPE_SHA384 = 4, CRYPTO_HASH_TYPE_SHA512 = 5 }; CK_MECHANISM_TYPE hash_to_nss[] = { 0, /* CRYPTO_HASH_TYPE_NONE */ CKM_MD5_HMAC, /* CRYPTO_HASH_TYPE_MD5 */ CKM_SHA_1_HMAC, /* CRYPTO_HASH_TYPE_SHA1 */ CKM_SHA256_HMAC, /* CRYPTO_HASH_TYPE_SHA256 */ CKM_SHA384_HMAC, /* CRYPTO_HASH_TYPE_SHA384 */ CKM_SHA512_HMAC /* CRYPTO_HASH_TYPE_SHA512 */ }; size_t nsshash_len[] = { 0, /* CRYPTO_HASH_TYPE_NONE */ MD5_LENGTH, /* CRYPTO_HASH_TYPE_MD5 */ SHA1_LENGTH, /* CRYPTO_HASH_TYPE_SHA1 */ SHA256_LENGTH, /* CRYPTO_HASH_TYPE_SHA256 */ SHA384_LENGTH, /* CRYPTO_HASH_TYPE_SHA384 */ SHA512_LENGTH /* CRYPTO_HASH_TYPE_SHA512 */ }; enum sym_key_type { SYM_KEY_TYPE_CRYPT, SYM_KEY_TYPE_HASH }; struct nsscrypto_instance { PK11SymKey *nss_sym_key; PK11SymKey *nss_sym_key_sign; unsigned char *private_key; unsigned int private_key_len; int crypto_cipher_type; int crypto_hash_type; }; /* * crypt/decrypt functions */ static int nssstring_to_crypto_cipher_type(const char* crypto_cipher_type) { if (strcmp(crypto_cipher_type, "none") == 0) { return CRYPTO_CIPHER_TYPE_NONE; } else if (strcmp(crypto_cipher_type, "aes256") == 0) { return CRYPTO_CIPHER_TYPE_AES256; } else if (strcmp(crypto_cipher_type, "aes192") == 0) { return CRYPTO_CIPHER_TYPE_AES192; } else if (strcmp(crypto_cipher_type, "aes128") == 0) { return CRYPTO_CIPHER_TYPE_AES128; } else if (strcmp(crypto_cipher_type, "3des") == 0) { return CRYPTO_CIPHER_TYPE_3DES; } return -1; } static PK11SymKey *nssimport_symmetric_key(knet_handle_t knet_h, enum sym_key_type key_type) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; SECItem key_item; PK11SlotInfo *slot; PK11SymKey *res_key; CK_MECHANISM_TYPE cipher; CK_ATTRIBUTE_TYPE operation; CK_MECHANISM_TYPE wrap_mechanism; int wrap_key_len; PK11SymKey *wrap_key; PK11Context *wrap_key_crypt_context; SECItem tmp_sec_item; SECItem wrapped_key; int wrapped_key_len; unsigned char wrapped_key_data[KNET_MAX_KEY_LEN]; memset(&key_item, 0, sizeof(key_item)); slot = NULL; wrap_key = NULL; res_key = NULL; wrap_key_crypt_context = NULL; key_item.type = siBuffer; key_item.data = instance->private_key; switch (key_type) { case SYM_KEY_TYPE_CRYPT: key_item.len = nsscipher_key_len[instance->crypto_cipher_type]; cipher = cipher_to_nss[instance->crypto_cipher_type]; operation = CKA_ENCRYPT|CKA_DECRYPT; break; case SYM_KEY_TYPE_HASH: key_item.len = instance->private_key_len; cipher = hash_to_nss[instance->crypto_hash_type]; operation = CKA_SIGN; break; default: log_err(knet_h, KNET_SUB_NSSCRYPTO, "Import symmetric key failed. Unknown keyimport request"); goto exit_res_key; break; } - slot = (*_int_PK11_GetBestSlot)(cipher, NULL); + slot = PK11_GetBestSlot(cipher, NULL); if (slot == NULL) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to find security slot (%d): %s", - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); goto exit_res_key; } /* * Without FIPS it would be possible to just use * res_key = PK11_ImportSymKey(slot, cipher, PK11_OriginUnwrap, operation, &key_item, NULL); * with FIPS NSS Level 2 certification has to be "workarounded" (so it becomes Level 1) by using * following method: * 1. Generate wrap key * 2. Encrypt authkey with wrap key * 3. Unwrap encrypted authkey using wrap key */ /* * Generate wrapping key */ - wrap_mechanism = (*_int_PK11_GetBestWrapMechanism)(slot); - wrap_key_len = (*_int_PK11_GetBestKeyLength)(slot, wrap_mechanism); - wrap_key = (*_int_PK11_KeyGen)(slot, wrap_mechanism, NULL, wrap_key_len, NULL); + wrap_mechanism = PK11_GetBestWrapMechanism(slot); + wrap_key_len = PK11_GetBestKeyLength(slot, wrap_mechanism); + wrap_key = PK11_KeyGen(slot, wrap_mechanism, NULL, wrap_key_len, NULL); if (wrap_key == NULL) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to generate wrapping key (%d): %s", - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); goto exit_res_key; } /* * Encrypt authkey with wrapping key */ /* * Initialization of IV is not needed because PK11_GetBestWrapMechanism should return ECB mode */ memset(&tmp_sec_item, 0, sizeof(tmp_sec_item)); - wrap_key_crypt_context = (*_int_PK11_CreateContextBySymKey)(wrap_mechanism, CKA_ENCRYPT, - wrap_key, &tmp_sec_item); + wrap_key_crypt_context = PK11_CreateContextBySymKey(wrap_mechanism, CKA_ENCRYPT, + wrap_key, &tmp_sec_item); if (wrap_key_crypt_context == NULL) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to create encrypt context (%d): %s", - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); goto exit_res_key; } wrapped_key_len = (int)sizeof(wrapped_key_data); - if ((*_int_PK11_CipherOp)(wrap_key_crypt_context, wrapped_key_data, &wrapped_key_len, - sizeof(wrapped_key_data), key_item.data, key_item.len) != SECSuccess) { + if (PK11_CipherOp(wrap_key_crypt_context, wrapped_key_data, &wrapped_key_len, + sizeof(wrapped_key_data), key_item.data, key_item.len) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to encrypt authkey (%d): %s", - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); goto exit_res_key; } - if ((*_int_PK11_Finalize)(wrap_key_crypt_context) != SECSuccess) { + if (PK11_Finalize(wrap_key_crypt_context) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to finalize encryption of authkey (%d): %s", - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); goto exit_res_key; } /* * Finally unwrap sym key */ memset(&tmp_sec_item, 0, sizeof(tmp_sec_item)); wrapped_key.data = wrapped_key_data; wrapped_key.len = wrapped_key_len; - res_key = (*_int_PK11_UnwrapSymKey)(wrap_key, wrap_mechanism, &tmp_sec_item, &wrapped_key, - cipher, operation, key_item.len); + res_key = PK11_UnwrapSymKey(wrap_key, wrap_mechanism, &tmp_sec_item, &wrapped_key, + cipher, operation, key_item.len); if (res_key == NULL) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to import key into NSS (%d): %s", - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); - if ((*_int_PR_GetError)() == SEC_ERROR_BAD_DATA) { + if (PR_GetError() == SEC_ERROR_BAD_DATA) { /* * Maximum key length for FIPS enabled softtoken is limited to * MAX_KEY_LEN (pkcs11i.h - 256) and checked in NSC_UnwrapKey. Returned * error is CKR_TEMPLATE_INCONSISTENT which is mapped to SEC_ERROR_BAD_DATA. */ log_err(knet_h, KNET_SUB_NSSCRYPTO, "Secret key is probably too long. " "Try reduce it to 256 bytes"); } goto exit_res_key; } exit_res_key: if (wrap_key_crypt_context != NULL) { - (*_int_PK11_DestroyContext)(wrap_key_crypt_context, PR_TRUE); + PK11_DestroyContext(wrap_key_crypt_context, PR_TRUE); } if (wrap_key != NULL) { - (*_int_PK11_FreeSymKey)(wrap_key); + PK11_FreeSymKey(wrap_key); } if (slot != NULL) { - (*_int_PK11_FreeSlot)(slot); + PK11_FreeSlot(slot); } return (res_key); } static int init_nss_crypto(knet_handle_t knet_h) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; if (!cipher_to_nss[instance->crypto_cipher_type]) { return 0; } instance->nss_sym_key = nssimport_symmetric_key(knet_h, SYM_KEY_TYPE_CRYPT); if (instance->nss_sym_key == NULL) { return -1; } return 0; } static int encrypt_nss( knet_handle_t knet_h, const struct iovec *iov, int iovcnt, unsigned char *buf_out, ssize_t *buf_out_len) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; PK11Context* crypt_context = NULL; SECItem crypt_param; SECItem *nss_sec_param = NULL; int tmp_outlen = 0, tmp1_outlen = 0; unsigned int tmp2_outlen = 0; unsigned char *salt = buf_out; unsigned char *data = buf_out + SALT_SIZE; int err = -1; int i; - if ((*_int_PK11_GenerateRandom)(salt, SALT_SIZE) != SECSuccess) { + if (PK11_GenerateRandom(salt, SALT_SIZE) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to generate a random number (err %d): %s", - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); goto out; } crypt_param.type = siBuffer; crypt_param.data = salt; crypt_param.len = SALT_SIZE; - nss_sec_param = (*_int_PK11_ParamFromIV)(cipher_to_nss[instance->crypto_cipher_type], - &crypt_param); + nss_sec_param = PK11_ParamFromIV(cipher_to_nss[instance->crypto_cipher_type], + &crypt_param); if (nss_sec_param == NULL) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to set up PKCS11 param (err %d): %s", - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); goto out; } /* * Create cipher context for encryption */ - crypt_context = (*_int_PK11_CreateContextBySymKey)(cipher_to_nss[instance->crypto_cipher_type], - CKA_ENCRYPT, - instance->nss_sym_key, - nss_sec_param); + crypt_context = PK11_CreateContextBySymKey(cipher_to_nss[instance->crypto_cipher_type], + CKA_ENCRYPT, + instance->nss_sym_key, + nss_sec_param); if (!crypt_context) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CreateContext failed (encrypt) crypt_type=%d (err %d): %s", (int)cipher_to_nss[instance->crypto_cipher_type], - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); goto out; } for (i=0; icrypto_cipher_type], - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); goto out; } tmp1_outlen = tmp1_outlen + tmp_outlen; } - if ((*_int_PK11_DigestFinal)(crypt_context, data + tmp1_outlen, + if (PK11_DigestFinal(crypt_context, data + tmp1_outlen, &tmp2_outlen, KNET_DATABUFSIZE_CRYPT - tmp1_outlen) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestFinal failed (encrypt) crypt_type=%d (err %d): %s", (int)cipher_to_nss[instance->crypto_cipher_type], - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); goto out; } *buf_out_len = tmp1_outlen + tmp2_outlen + SALT_SIZE; err = 0; out: if (crypt_context) { - (*_int_PK11_DestroyContext)(crypt_context, PR_TRUE); + PK11_DestroyContext(crypt_context, PR_TRUE); } if (nss_sec_param) { - (*_int_SECITEM_FreeItem)(nss_sec_param, PR_TRUE); + SECITEM_FreeItem(nss_sec_param, PR_TRUE); } return err; } static int decrypt_nss ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; PK11Context* decrypt_context = NULL; SECItem decrypt_param; int tmp1_outlen = 0; unsigned int tmp2_outlen = 0; unsigned char *salt = (unsigned char *)buf_in; unsigned char *data = salt + SALT_SIZE; int datalen = buf_in_len - SALT_SIZE; int err = -1; /* Create cipher context for decryption */ decrypt_param.type = siBuffer; decrypt_param.data = salt; decrypt_param.len = SALT_SIZE; - decrypt_context = (*_int_PK11_CreateContextBySymKey)(cipher_to_nss[instance->crypto_cipher_type], - CKA_DECRYPT, - instance->nss_sym_key, &decrypt_param); + decrypt_context = PK11_CreateContextBySymKey(cipher_to_nss[instance->crypto_cipher_type], + CKA_DECRYPT, + instance->nss_sym_key, &decrypt_param); if (!decrypt_context) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CreateContext (decrypt) failed (err %d): %s", - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); goto out; } - if ((*_int_PK11_CipherOp)(decrypt_context, buf_out, &tmp1_outlen, - KNET_DATABUFSIZE_CRYPT, data, datalen) != SECSuccess) { + if (PK11_CipherOp(decrypt_context, buf_out, &tmp1_outlen, + KNET_DATABUFSIZE_CRYPT, data, datalen) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CipherOp (decrypt) failed (err %d): %s", - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); goto out; } - if ((*_int_PK11_DigestFinal)(decrypt_context, buf_out + tmp1_outlen, &tmp2_outlen, - KNET_DATABUFSIZE_CRYPT - tmp1_outlen) != SECSuccess) { + if (PK11_DigestFinal(decrypt_context, buf_out + tmp1_outlen, &tmp2_outlen, + KNET_DATABUFSIZE_CRYPT - tmp1_outlen) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestFinal (decrypt) failed (err %d): %s", - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); goto out; } *buf_out_len = tmp1_outlen + tmp2_outlen; err = 0; out: if (decrypt_context) { - (*_int_PK11_DestroyContext)(decrypt_context, PR_TRUE); + PK11_DestroyContext(decrypt_context, PR_TRUE); } return err; } /* * hash/hmac/digest functions */ static int nssstring_to_crypto_hash_type(const char* crypto_hash_type) { if (strcmp(crypto_hash_type, "none") == 0) { return CRYPTO_HASH_TYPE_NONE; } else if (strcmp(crypto_hash_type, "md5") == 0) { return CRYPTO_HASH_TYPE_MD5; } else if (strcmp(crypto_hash_type, "sha1") == 0) { return CRYPTO_HASH_TYPE_SHA1; } else if (strcmp(crypto_hash_type, "sha256") == 0) { return CRYPTO_HASH_TYPE_SHA256; } else if (strcmp(crypto_hash_type, "sha384") == 0) { return CRYPTO_HASH_TYPE_SHA384; } else if (strcmp(crypto_hash_type, "sha512") == 0) { return CRYPTO_HASH_TYPE_SHA512; } return -1; } static int init_nss_hash(knet_handle_t knet_h) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; if (!hash_to_nss[instance->crypto_hash_type]) { return 0; } instance->nss_sym_key_sign = nssimport_symmetric_key(knet_h, SYM_KEY_TYPE_HASH); if (instance->nss_sym_key_sign == NULL) { return -1; } return 0; } static int calculate_nss_hash( knet_handle_t knet_h, const unsigned char *buf, const size_t buf_len, unsigned char *hash) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; PK11Context* hash_context = NULL; SECItem hash_param; unsigned int hash_tmp_outlen = 0; int err = -1; /* Now do the digest */ hash_param.type = siBuffer; hash_param.data = 0; hash_param.len = 0; - hash_context = (*_int_PK11_CreateContextBySymKey)(hash_to_nss[instance->crypto_hash_type], - CKA_SIGN, - instance->nss_sym_key_sign, - &hash_param); + hash_context = PK11_CreateContextBySymKey(hash_to_nss[instance->crypto_hash_type], + CKA_SIGN, + instance->nss_sym_key_sign, + &hash_param); if (!hash_context) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CreateContext failed (hash) hash_type=%d (err %d): %s", (int)hash_to_nss[instance->crypto_hash_type], - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); goto out; } - if ((*_int_PK11_DigestBegin)(hash_context) != SECSuccess) { + if (PK11_DigestBegin(hash_context) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestBegin failed (hash) hash_type=%d (err %d): %s", (int)hash_to_nss[instance->crypto_hash_type], - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); goto out; } - if ((*_int_PK11_DigestOp)(hash_context, buf, buf_len) != SECSuccess) { + if (PK11_DigestOp(hash_context, buf, buf_len) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestOp failed (hash) hash_type=%d (err %d): %s", (int)hash_to_nss[instance->crypto_hash_type], - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); goto out; } - if ((*_int_PK11_DigestFinal)(hash_context, hash, - &hash_tmp_outlen, nsshash_len[instance->crypto_hash_type]) != SECSuccess) { + if (PK11_DigestFinal(hash_context, hash, + &hash_tmp_outlen, nsshash_len[instance->crypto_hash_type]) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestFinale failed (hash) hash_type=%d (err %d): %s", (int)hash_to_nss[instance->crypto_hash_type], - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); goto out; } err = 0; out: if (hash_context) { - (*_int_PK11_DestroyContext)(hash_context, PR_TRUE); + PK11_DestroyContext(hash_context, PR_TRUE); } return err; } /* * global/glue nss functions */ static int init_nss(knet_handle_t knet_h) { + static int at_exit_registered = 0; + + if (!at_exit_registered) { + if (atexit(nss_atexit_handler)) { + log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to register NSS atexit handler"); + errno = EAGAIN; + return -1; + } + at_exit_registered = 1; + } + + if (!nss_db_is_init) { + if (NSS_NoDB_Init(".") != SECSuccess) { + log_err(knet_h, KNET_SUB_NSSCRYPTO, "NSS DB initialization failed (err %d): %s", + PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); + errno = EAGAIN; + return -1; + } + nss_db_is_init = 1; + } + if (init_nss_crypto(knet_h) < 0) { return -1; } if (init_nss_hash(knet_h) < 0) { return -1; } return 0; } /* * exported API */ -int nsscrypto_encrypt_and_sign ( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len) -{ - struct iovec iov_in; - - memset(&iov_in, 0, sizeof(iov_in)); - iov_in.iov_base = (unsigned char *)buf_in; - iov_in.iov_len = buf_in_len; - - return nsscrypto_encrypt_and_signv(knet_h, &iov_in, 1, buf_out, buf_out_len); -} - -int nsscrypto_encrypt_and_signv ( +static int nsscrypto_encrypt_and_signv ( knet_handle_t knet_h, const struct iovec *iov_in, int iovcnt_in, unsigned char *buf_out, ssize_t *buf_out_len) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; int i; if (cipher_to_nss[instance->crypto_cipher_type]) { if (encrypt_nss(knet_h, iov_in, iovcnt_in, buf_out, buf_out_len) < 0) { return -1; } } else { *buf_out_len = 0; for (i=0; icrypto_hash_type]) { if (calculate_nss_hash(knet_h, buf_out, *buf_out_len, buf_out + *buf_out_len) < 0) { return -1; } *buf_out_len = *buf_out_len + nsshash_len[instance->crypto_hash_type]; } return 0; } -int nsscrypto_authenticate_and_decrypt ( +static int nsscrypto_encrypt_and_sign ( + knet_handle_t knet_h, + const unsigned char *buf_in, + const ssize_t buf_in_len, + unsigned char *buf_out, + ssize_t *buf_out_len) +{ + struct iovec iov_in; + + memset(&iov_in, 0, sizeof(iov_in)); + iov_in.iov_base = (unsigned char *)buf_in; + iov_in.iov_len = buf_in_len; + + return nsscrypto_encrypt_and_signv(knet_h, &iov_in, 1, buf_out, buf_out_len); +} + +static int nsscrypto_authenticate_and_decrypt ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; ssize_t temp_len = buf_in_len; if (hash_to_nss[instance->crypto_hash_type]) { unsigned char tmp_hash[nsshash_len[instance->crypto_hash_type]]; ssize_t temp_buf_len = buf_in_len - nsshash_len[instance->crypto_hash_type]; if ((temp_buf_len < 0) || (temp_buf_len > KNET_MAX_PACKET_SIZE)) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Incorrect packet size."); return -1; } if (calculate_nss_hash(knet_h, buf_in, temp_buf_len, tmp_hash) < 0) { return -1; } if (memcmp(tmp_hash, buf_in + temp_buf_len, nsshash_len[instance->crypto_hash_type]) != 0) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Digest does not match"); return -1; } temp_len = temp_len - nsshash_len[instance->crypto_hash_type]; *buf_out_len = temp_len; } if (cipher_to_nss[instance->crypto_cipher_type]) { if (decrypt_nss(knet_h, buf_in, temp_len, buf_out, buf_out_len) < 0) { return -1; } } else { memmove(buf_out, buf_in, temp_len); *buf_out_len = temp_len; } return 0; } -int nsscrypto_init( +static void nsscrypto_fini( + knet_handle_t knet_h) +{ + struct nsscrypto_instance *nsscrypto_instance = knet_h->crypto_instance->model_instance; + + if (nsscrypto_instance) { + if (nsscrypto_instance->nss_sym_key) { + PK11_FreeSymKey(nsscrypto_instance->nss_sym_key); + nsscrypto_instance->nss_sym_key = NULL; + } + if (nsscrypto_instance->nss_sym_key_sign) { + PK11_FreeSymKey(nsscrypto_instance->nss_sym_key_sign); + nsscrypto_instance->nss_sym_key_sign = NULL; + } + free(nsscrypto_instance); + knet_h->crypto_instance->model_instance = NULL; + knet_h->sec_header_size = 0; + } + + return; +} + +static int nsscrypto_init( knet_handle_t knet_h, struct knet_handle_crypto_cfg *knet_handle_crypto_cfg) { struct nsscrypto_instance *nsscrypto_instance = NULL; log_debug(knet_h, KNET_SUB_NSSCRYPTO, "Initizializing nss crypto module [%s/%s]", knet_handle_crypto_cfg->crypto_cipher_type, knet_handle_crypto_cfg->crypto_hash_type); knet_h->crypto_instance->model_instance = malloc(sizeof(struct nsscrypto_instance)); if (!knet_h->crypto_instance->model_instance) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to allocate memory for nss model instance"); return -1; } nsscrypto_instance = knet_h->crypto_instance->model_instance; memset(nsscrypto_instance, 0, sizeof(struct nsscrypto_instance)); nsscrypto_instance->crypto_cipher_type = nssstring_to_crypto_cipher_type(knet_handle_crypto_cfg->crypto_cipher_type); if (nsscrypto_instance->crypto_cipher_type < 0) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "unknown crypto cipher type requested"); goto out_err; } nsscrypto_instance->crypto_hash_type = nssstring_to_crypto_hash_type(knet_handle_crypto_cfg->crypto_hash_type); if (nsscrypto_instance->crypto_hash_type < 0) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "unknown crypto hash type requested"); goto out_err; } if ((nsscrypto_instance->crypto_cipher_type > 0) && (nsscrypto_instance->crypto_hash_type == 0)) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "crypto communication requires hash specified"); goto out_err; } nsscrypto_instance->private_key = knet_handle_crypto_cfg->private_key; nsscrypto_instance->private_key_len = knet_handle_crypto_cfg->private_key_len; if (init_nss(knet_h) < 0) { goto out_err; } knet_h->sec_header_size = 0; if (nsscrypto_instance->crypto_hash_type > 0) { knet_h->sec_header_size += nsshash_len[nsscrypto_instance->crypto_hash_type]; knet_h->sec_hash_size = nsshash_len[nsscrypto_instance->crypto_hash_type]; } if (nsscrypto_instance->crypto_cipher_type > 0) { int block_size; if (nsscypher_block_len[nsscrypto_instance->crypto_cipher_type]) { block_size = nsscypher_block_len[nsscrypto_instance->crypto_cipher_type]; } else { - block_size = (*_int_PK11_GetBlockSize)(nsscrypto_instance->crypto_cipher_type, NULL); + block_size = PK11_GetBlockSize(nsscrypto_instance->crypto_cipher_type, NULL); if (block_size < 0) { goto out_err; } } knet_h->sec_header_size += (block_size * 2); knet_h->sec_header_size += SALT_SIZE; knet_h->sec_salt_size = SALT_SIZE; knet_h->sec_block_size = block_size; } return 0; out_err: nsscrypto_fini(knet_h); return -1; } -void nsscrypto_fini( - knet_handle_t knet_h) -{ - struct nsscrypto_instance *nsscrypto_instance = knet_h->crypto_instance->model_instance; - - if (nsscrypto_instance) { - if (nsscrypto_instance->nss_sym_key) { - (*_int_PK11_FreeSymKey)(nsscrypto_instance->nss_sym_key); - nsscrypto_instance->nss_sym_key = NULL; - } - if (nsscrypto_instance->nss_sym_key_sign) { - (*_int_PK11_FreeSymKey)(nsscrypto_instance->nss_sym_key_sign); - nsscrypto_instance->nss_sym_key_sign = NULL; - } - free(nsscrypto_instance); - knet_h->crypto_instance->model_instance = NULL; - knet_h->sec_header_size = 0; - } - - return; -} -#endif +crypto_ops_t crypto_model = { + KNET_CRYPTO_MODEL_ABI, + nsscrypto_init, + nsscrypto_fini, + nsscrypto_encrypt_and_sign, + nsscrypto_encrypt_and_signv, + nsscrypto_authenticate_and_decrypt +}; diff --git a/libknet/crypto_nss.h b/libknet/crypto_nss.h deleted file mode 100644 index d77a8d8b..00000000 --- a/libknet/crypto_nss.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2012-2017 Red Hat, Inc. All rights reserved. - * - * Author: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+, LGPL-2.0+ - */ - -#ifndef __KNET_NSSCRYPTO_H__ -#define __KNET_NSSCRYPTO_H__ - -#include "internals.h" - -struct nsscrypto_instance; - -int nsscrypto_load_lib( - knet_handle_t knet_h); - -int nsscrypto_init( - knet_handle_t knet_h, - struct knet_handle_crypto_cfg *knet_handle_crypto_cfg); - -void nsscrypto_fini( - knet_handle_t knet_h); - -int nsscrypto_authenticate_and_decrypt ( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - -int nsscrypto_encrypt_and_sign ( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - -int nsscrypto_encrypt_and_signv ( - knet_handle_t knet_h, - const struct iovec *iov_in, - int iovcnt_in, - unsigned char *buf_out, - ssize_t *buf_out_len); - -#endif diff --git a/libknet/crypto_nss_remap.h b/libknet/crypto_nss_remap.h deleted file mode 100644 index 572aecda..00000000 --- a/libknet/crypto_nss_remap.h +++ /dev/null @@ -1,54 +0,0 @@ -#include "remap.h" - -/* - * nss3 - */ -REMAP_PROTO(CK_MECHANISM_TYPE,PK11_GetBestWrapMechanism,(PK11SlotInfo *slot)) -REMAP_PROTO(PK11SlotInfo *,PK11_GetBestSlot, - (CK_MECHANISM_TYPE type, void *wincx)) -REMAP_PROTO(int,PK11_GetBestKeyLength, - (PK11SlotInfo *slot, CK_MECHANISM_TYPE type)) -REMAP_PROTO(SECStatus,PK11_DigestFinal, - (PK11Context *context, unsigned char *data, - unsigned int *outLen, unsigned int length)) -REMAP_PROTO(void,SECITEM_FreeItem,(SECItem *zap, PRBool freeit)) -REMAP_PROTO(SECStatus,NSS_NoDB_Init,(const char *configdir)) -REMAP_PROTO(SECStatus,NSS_Shutdown,(void)) -REMAP_PROTO(SECStatus,PK11_DigestBegin,(PK11Context *cx)) -REMAP_PROTO(SECStatus,PK11_DigestOp, - (PK11Context *context, const unsigned char *in, unsigned len)) -REMAP_PROTO(void,PK11_DestroyContext,(PK11Context *context, PRBool freeit)) -REMAP_PROTO(SECStatus,PK11_Finalize,(PK11Context *context)) -REMAP_PROTO(SECStatus,PK11_CipherOp, - (PK11Context *context, unsigned char *out, int *outlen, - int maxout, const unsigned char *in, int inlen)) -REMAP_PROTO(PK11SymKey *,PK11_UnwrapSymKey, - (PK11SymKey *key, CK_MECHANISM_TYPE wraptype, SECItem *param, - SECItem *wrapppedKey, CK_MECHANISM_TYPE target, - CK_ATTRIBUTE_TYPE operation, int keySize)) -REMAP_PROTO(void,PK11_FreeSymKey,(PK11SymKey *key)) -REMAP_PROTO(PK11Context *,PK11_CreateContextBySymKey, - (CK_MECHANISM_TYPE type, - CK_ATTRIBUTE_TYPE operation, - PK11SymKey *symKey, SECItem *param)) -REMAP_PROTO(SECStatus,PK11_GenerateRandom,(unsigned char *data, int len)) -REMAP_PROTO(SECItem *,PK11_ParamFromIV,(CK_MECHANISM_TYPE type, SECItem *iv)) -REMAP_PROTO(void,PK11_FreeSlot,(PK11SlotInfo *slot)) -REMAP_PROTO(int,PK11_GetBlockSize,(CK_MECHANISM_TYPE type, SECItem *params)) -REMAP_PROTO(PK11SymKey *,PK11_KeyGen, - (PK11SlotInfo *slot, CK_MECHANISM_TYPE type, - SECItem *param, int keySize, void *wincx)) - -/* - * nspr4 - */ -REMAP_PROTO(PRStatus,PR_Cleanup,(void)) -REMAP_PROTO(const char *,PR_ErrorToString, - (PRErrorCode code, PRLanguageCode language)) -REMAP_PROTO(PRErrorCode,PR_GetError,(void)) -REMAP_PROTO(PRBool,PR_Initialized,(void)) - -/* - * plds4 - */ -REMAP_PROTO(void,PL_ArenaFinish,(void)) diff --git a/libknet/crypto_openssl.c b/libknet/crypto_openssl.c index c44760f7..810dd87c 100644 --- a/libknet/crypto_openssl.c +++ b/libknet/crypto_openssl.c @@ -1,565 +1,524 @@ /* * Copyright (C) 2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ +#define KNET_MODULE #include "config.h" +#include #include #include -#include -#ifdef BUILDCRYPTOOPENSSL #include #include #include #include #include -#include "common.h" -#include "crypto.h" -#include "crypto_openssl.h" #include "logging.h" +#include "crypto_model.h" /* * 1.0.2 requires at least 120 bytes * 1.1.0 requires at least 256 bytes */ #define SSLERR_BUF_SIZE 512 -/* - * global vars for dlopen - */ -static void *openssl_lib; - -#include "crypto_openssl_remap.h" - -static int opensslcrypto_remap_symbols(knet_handle_t knet_h) -{ -#define REMAP_WITH(name) remap_symbol (knet_h, KNET_SUB_OPENSSLCRYPTO, openssl_lib, name) -#include "crypto_openssl_remap.h" - return 0; - - fail: -#define REMAP_FAIL -#include "crypto_openssl_remap.h" - errno = EINVAL; - return -1; -} - -static int openssl_is_init = 0; - -int opensslcrypto_load_lib( - knet_handle_t knet_h) -{ - int err = 0, savederrno = 0; - - if (!openssl_lib) { - openssl_lib = open_lib(knet_h, LIBOPENSSL, 0); - if (!openssl_lib) { - savederrno = errno; - err = -1; - goto out; - } - } - - if (opensslcrypto_remap_symbols(knet_h) < 0) { - savederrno = errno; - err = -1; - goto out; - } - - if (!openssl_is_init) { -#ifdef BUILDCRYPTOOPENSSL10 - (*_int_ERR_load_crypto_strings)(); - (*_int_OPENSSL_add_all_algorithms_noconf)(); -#endif -#ifdef BUILDCRYPTOOPENSSL11 - if (!(*_int_OPENSSL_init_crypto)(OPENSSL_INIT_ADD_ALL_CIPHERS \ - | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)) { - log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to init openssl"); - err = -1; - savederrno = EAGAIN; - goto out; - } -#endif - openssl_is_init = 1; - } - -out: - errno = savederrno; - return err; -} - /* * crypto definitions and conversion tables */ #define SALT_SIZE 16 struct opensslcrypto_instance { void *private_key; int private_key_len; const EVP_CIPHER *crypto_cipher_type; const EVP_MD *crypto_hash_type; }; /* * crypt/decrypt functions openssl1.0 */ #ifdef BUILDCRYPTOOPENSSL10 static int encrypt_openssl( knet_handle_t knet_h, const struct iovec *iov, int iovcnt, unsigned char *buf_out, ssize_t *buf_out_len) { struct opensslcrypto_instance *instance = knet_h->crypto_instance->model_instance; EVP_CIPHER_CTX ctx; int tmplen = 0, offset = 0; unsigned char *salt = buf_out; unsigned char *data = buf_out + SALT_SIZE; int err = 0; int i; char sslerr[SSLERR_BUF_SIZE]; - (*_int_EVP_CIPHER_CTX_init)(&ctx); + EVP_CIPHER_CTX_init(&ctx); /* * contribute to PRNG for each packet we send/receive */ - (*_int_RAND_seed)((unsigned char *)iov[iovcnt - 1].iov_base, iov[iovcnt - 1].iov_len); + RAND_seed((unsigned char *)iov[iovcnt - 1].iov_base, iov[iovcnt - 1].iov_len); - if (!(*_int_RAND_bytes)(salt, SALT_SIZE)) { - (*_int_ERR_error_string_n)((*_int_ERR_get_error)(), sslerr, sizeof(sslerr)); + if (!RAND_bytes(salt, SALT_SIZE)) { + ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr)); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to get random salt data: %s", sslerr); err = -1; goto out; } /* * add warning re keylength */ - (*_int_EVP_EncryptInit_ex)(&ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt); + EVP_EncryptInit_ex(&ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt); for (i=0; icrypto_instance->model_instance; EVP_CIPHER_CTX ctx; int tmplen1 = 0, tmplen2 = 0; unsigned char *salt = (unsigned char *)buf_in; unsigned char *data = salt + SALT_SIZE; int datalen = buf_in_len - SALT_SIZE; int err = 0; char sslerr[SSLERR_BUF_SIZE]; - (*_int_EVP_CIPHER_CTX_init)(&ctx); + EVP_CIPHER_CTX_init(&ctx); /* * contribute to PRNG for each packet we send/receive */ - (*_int_RAND_seed)(buf_in, buf_in_len); + RAND_seed(buf_in, buf_in_len); /* * add warning re keylength */ - (*_int_EVP_DecryptInit_ex)(&ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt); + EVP_DecryptInit_ex(&ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt); - if (!(*_int_EVP_DecryptUpdate)(&ctx, buf_out, &tmplen1, data, datalen)) { - (*_int_ERR_error_string_n)((*_int_ERR_get_error)(), sslerr, sizeof(sslerr)); + if (!EVP_DecryptUpdate(&ctx, buf_out, &tmplen1, data, datalen)) { + ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr)); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to decrypt: %s", sslerr); err = -1; goto out; } - if (!(*_int_EVP_DecryptFinal_ex)(&ctx, buf_out + tmplen1, &tmplen2)) { - (*_int_ERR_error_string_n)((*_int_ERR_get_error)(), sslerr, sizeof(sslerr)); + if (!EVP_DecryptFinal_ex(&ctx, buf_out + tmplen1, &tmplen2)) { + ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr)); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to finalize decrypt: %s", sslerr); err = -1; goto out; } *buf_out_len = tmplen1 + tmplen2; out: - (*_int_EVP_CIPHER_CTX_cleanup)(&ctx); + EVP_CIPHER_CTX_cleanup(&ctx); return err; } #endif #ifdef BUILDCRYPTOOPENSSL11 static int encrypt_openssl( knet_handle_t knet_h, const struct iovec *iov, int iovcnt, unsigned char *buf_out, ssize_t *buf_out_len) { struct opensslcrypto_instance *instance = knet_h->crypto_instance->model_instance; EVP_CIPHER_CTX *ctx; int tmplen = 0, offset = 0; unsigned char *salt = buf_out; unsigned char *data = buf_out + SALT_SIZE; int err = 0; int i; char sslerr[SSLERR_BUF_SIZE]; - ctx = (*_int_EVP_CIPHER_CTX_new)(); + ctx = EVP_CIPHER_CTX_new(); /* * contribute to PRNG for each packet we send/receive */ - (*_int_RAND_seed)((unsigned char *)iov[iovcnt - 1].iov_base, iov[iovcnt - 1].iov_len); + RAND_seed((unsigned char *)iov[iovcnt - 1].iov_base, iov[iovcnt - 1].iov_len); - if (!(*_int_RAND_bytes)(salt, SALT_SIZE)) { - (*_int_ERR_error_string_n)((*_int_ERR_get_error)(), sslerr, sizeof(sslerr)); + if (!RAND_bytes(salt, SALT_SIZE)) { + ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr)); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to get random salt data: %s", sslerr); err = -1; goto out; } /* * add warning re keylength */ - (*_int_EVP_EncryptInit_ex)(ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt); + EVP_EncryptInit_ex(ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt); for (i=0; icrypto_instance->model_instance; EVP_CIPHER_CTX *ctx; int tmplen1 = 0, tmplen2 = 0; unsigned char *salt = (unsigned char *)buf_in; unsigned char *data = salt + SALT_SIZE; int datalen = buf_in_len - SALT_SIZE; int err = 0; char sslerr[SSLERR_BUF_SIZE]; - ctx = (*_int_EVP_CIPHER_CTX_new)(); + ctx = EVP_CIPHER_CTX_new(); /* * contribute to PRNG for each packet we send/receive */ - (*_int_RAND_seed)(buf_in, buf_in_len); + RAND_seed(buf_in, buf_in_len); /* * add warning re keylength */ - (*_int_EVP_DecryptInit_ex)(ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt); + EVP_DecryptInit_ex(ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt); - if (!(*_int_EVP_DecryptUpdate)(ctx, buf_out, &tmplen1, data, datalen)) { - (*_int_ERR_error_string_n)((*_int_ERR_get_error)(), sslerr, sizeof(sslerr)); + if (!EVP_DecryptUpdate(ctx, buf_out, &tmplen1, data, datalen)) { + ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr)); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to decrypt: %s", sslerr); err = -1; goto out; } - if (!(*_int_EVP_DecryptFinal_ex)(ctx, buf_out + tmplen1, &tmplen2)) { - (*_int_ERR_error_string_n)((*_int_ERR_get_error)(), sslerr, sizeof(sslerr)); + if (!EVP_DecryptFinal_ex(ctx, buf_out + tmplen1, &tmplen2)) { + ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr)); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to finalize decrypt: %s", sslerr); err = -1; goto out; } *buf_out_len = tmplen1 + tmplen2; out: - (*_int_EVP_CIPHER_CTX_free)(ctx); + EVP_CIPHER_CTX_free(ctx); return err; } #endif /* * hash/hmac/digest functions */ static int calculate_openssl_hash( knet_handle_t knet_h, const unsigned char *buf, const size_t buf_len, unsigned char *hash) { struct opensslcrypto_instance *instance = knet_h->crypto_instance->model_instance; unsigned int hash_len = 0; unsigned char *hash_out = NULL; char sslerr[SSLERR_BUF_SIZE]; - hash_out = (*_int_HMAC)(instance->crypto_hash_type, - instance->private_key, instance->private_key_len, - buf, buf_len, - hash, &hash_len); + hash_out = HMAC(instance->crypto_hash_type, + instance->private_key, instance->private_key_len, + buf, buf_len, + hash, &hash_len); if ((!hash_out) || (hash_len != knet_h->sec_hash_size)) { - (*_int_ERR_error_string_n)((*_int_ERR_get_error)(), sslerr, sizeof(sslerr)); + ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr)); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to calculate hash: %s", sslerr); return -1; } return 0; } /* * exported API */ -int opensslcrypto_encrypt_and_sign ( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len) -{ - struct iovec iov_in; - - memset(&iov_in, 0, sizeof(iov_in)); - iov_in.iov_base = (unsigned char *)buf_in; - iov_in.iov_len = buf_in_len; - - return opensslcrypto_encrypt_and_signv(knet_h, &iov_in, 1, buf_out, buf_out_len); -} - -int opensslcrypto_encrypt_and_signv ( +static int opensslcrypto_encrypt_and_signv ( knet_handle_t knet_h, const struct iovec *iov_in, int iovcnt_in, unsigned char *buf_out, ssize_t *buf_out_len) { struct opensslcrypto_instance *instance = knet_h->crypto_instance->model_instance; int i; if (instance->crypto_cipher_type) { if (encrypt_openssl(knet_h, iov_in, iovcnt_in, buf_out, buf_out_len) < 0) { return -1; } } else { *buf_out_len = 0; for (i=0; icrypto_hash_type) { if (calculate_openssl_hash(knet_h, buf_out, *buf_out_len, buf_out + *buf_out_len) < 0) { return -1; } *buf_out_len = *buf_out_len + knet_h->sec_hash_size; } return 0; } -int opensslcrypto_authenticate_and_decrypt ( +static int opensslcrypto_encrypt_and_sign ( + knet_handle_t knet_h, + const unsigned char *buf_in, + const ssize_t buf_in_len, + unsigned char *buf_out, + ssize_t *buf_out_len) +{ + struct iovec iov_in; + + memset(&iov_in, 0, sizeof(iov_in)); + iov_in.iov_base = (unsigned char *)buf_in; + iov_in.iov_len = buf_in_len; + + return opensslcrypto_encrypt_and_signv(knet_h, &iov_in, 1, buf_out, buf_out_len); +} + +static int opensslcrypto_authenticate_and_decrypt ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { struct opensslcrypto_instance *instance = knet_h->crypto_instance->model_instance; ssize_t temp_len = buf_in_len; if (instance->crypto_hash_type) { unsigned char tmp_hash[knet_h->sec_hash_size]; ssize_t temp_buf_len = buf_in_len - knet_h->sec_hash_size; if ((temp_buf_len < 0) || (temp_buf_len > KNET_MAX_PACKET_SIZE)) { log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Incorrect packet size."); return -1; } if (calculate_openssl_hash(knet_h, buf_in, temp_buf_len, tmp_hash) < 0) { return -1; } if (memcmp(tmp_hash, buf_in + temp_buf_len, knet_h->sec_hash_size) != 0) { log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Digest does not match"); return -1; } temp_len = temp_len - knet_h->sec_hash_size; *buf_out_len = temp_len; } if (instance->crypto_cipher_type) { if (decrypt_openssl(knet_h, buf_in, temp_len, buf_out, buf_out_len) < 0) { return -1; } } else { memmove(buf_out, buf_in, temp_len); *buf_out_len = temp_len; } return 0; } -int opensslcrypto_init( +static void opensslcrypto_fini( + knet_handle_t knet_h) +{ + struct opensslcrypto_instance *opensslcrypto_instance = knet_h->crypto_instance->model_instance; + + if (opensslcrypto_instance) { + if (opensslcrypto_instance->private_key) { + free(opensslcrypto_instance->private_key); + opensslcrypto_instance->private_key = NULL; + } + free(opensslcrypto_instance); + knet_h->crypto_instance->model_instance = NULL; + knet_h->sec_header_size = 0; + } + + return; +} + +static int opensslcrypto_init( knet_handle_t knet_h, struct knet_handle_crypto_cfg *knet_handle_crypto_cfg) { + static int openssl_is_init = 0; struct opensslcrypto_instance *opensslcrypto_instance = NULL; log_debug(knet_h, KNET_SUB_OPENSSLCRYPTO, "Initizializing openssl crypto module [%s/%s]", knet_handle_crypto_cfg->crypto_cipher_type, knet_handle_crypto_cfg->crypto_hash_type); + if (!openssl_is_init) { +#ifdef BUILDCRYPTOOPENSSL10 + ERR_load_crypto_strings(); + OPENSSL_add_all_algorithms_noconf(); +#endif +#ifdef BUILDCRYPTOOPENSSL11 + if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \ + | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)) { + log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to init openssl"); + errno = EAGAIN; + return -1; + } +#endif + openssl_is_init = 1; + } + knet_h->crypto_instance->model_instance = malloc(sizeof(struct opensslcrypto_instance)); if (!knet_h->crypto_instance->model_instance) { log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to allocate memory for openssl model instance"); return -1; } opensslcrypto_instance = knet_h->crypto_instance->model_instance; memset(opensslcrypto_instance, 0, sizeof(struct opensslcrypto_instance)); if (strcmp(knet_handle_crypto_cfg->crypto_cipher_type, "none") == 0) { opensslcrypto_instance->crypto_cipher_type = NULL; } else { - opensslcrypto_instance->crypto_cipher_type = (*_int_EVP_get_cipherbyname)(knet_handle_crypto_cfg->crypto_cipher_type); + opensslcrypto_instance->crypto_cipher_type = EVP_get_cipherbyname(knet_handle_crypto_cfg->crypto_cipher_type); if (!opensslcrypto_instance->crypto_cipher_type) { log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unknown crypto cipher type requested"); goto out_err; } } if (strcmp(knet_handle_crypto_cfg->crypto_hash_type, "none") == 0) { opensslcrypto_instance->crypto_hash_type = NULL; } else { - opensslcrypto_instance->crypto_hash_type = (*_int_EVP_get_digestbyname)(knet_handle_crypto_cfg->crypto_hash_type); + opensslcrypto_instance->crypto_hash_type = EVP_get_digestbyname(knet_handle_crypto_cfg->crypto_hash_type); if (!opensslcrypto_instance->crypto_hash_type) { log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unknown crypto hash type requested"); goto out_err; } } if ((opensslcrypto_instance->crypto_cipher_type) && (!opensslcrypto_instance->crypto_hash_type)) { log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "crypto communication requires hash specified"); goto out_err; } opensslcrypto_instance->private_key = malloc(knet_handle_crypto_cfg->private_key_len); if (!opensslcrypto_instance->private_key) { log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to allocate memory for openssl private key"); goto out_err; } memmove(opensslcrypto_instance->private_key, knet_handle_crypto_cfg->private_key, knet_handle_crypto_cfg->private_key_len); opensslcrypto_instance->private_key_len = knet_handle_crypto_cfg->private_key_len; knet_h->sec_header_size = 0; if (opensslcrypto_instance->crypto_hash_type) { - knet_h->sec_hash_size = (*_int_EVP_MD_size)(opensslcrypto_instance->crypto_hash_type); + knet_h->sec_hash_size = EVP_MD_size(opensslcrypto_instance->crypto_hash_type); knet_h->sec_header_size += knet_h->sec_hash_size; } if (opensslcrypto_instance->crypto_cipher_type) { int block_size; - block_size = (*_int_EVP_CIPHER_block_size)(opensslcrypto_instance->crypto_cipher_type); + block_size = EVP_CIPHER_block_size(opensslcrypto_instance->crypto_cipher_type); if (block_size < 0) { goto out_err; } knet_h->sec_header_size += (block_size * 2); knet_h->sec_header_size += SALT_SIZE; knet_h->sec_salt_size = SALT_SIZE; knet_h->sec_block_size = block_size; } return 0; out_err: opensslcrypto_fini(knet_h); return -1; } -void opensslcrypto_fini( - knet_handle_t knet_h) -{ - struct opensslcrypto_instance *opensslcrypto_instance = knet_h->crypto_instance->model_instance; - - if (opensslcrypto_instance) { - if (opensslcrypto_instance->private_key) { - free(opensslcrypto_instance->private_key); - opensslcrypto_instance->private_key = NULL; - } - free(opensslcrypto_instance); - knet_h->crypto_instance->model_instance = NULL; - knet_h->sec_header_size = 0; - } - - return; -} -#endif +crypto_ops_t crypto_model = { + KNET_CRYPTO_MODEL_ABI, + opensslcrypto_init, + opensslcrypto_fini, + opensslcrypto_encrypt_and_sign, + opensslcrypto_encrypt_and_signv, + opensslcrypto_authenticate_and_decrypt +}; diff --git a/libknet/crypto_openssl.h b/libknet/crypto_openssl.h deleted file mode 100644 index cdb2fd44..00000000 --- a/libknet/crypto_openssl.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2012-2017 Red Hat, Inc. All rights reserved. - * - * Author: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+, LGPL-2.0+ - */ - -#ifndef __KNET_OPENSSLCRYPTO_H__ -#define __KNET_OPENSSLCRYPTO_H__ - -#include "internals.h" - -struct opensslcrypto_instance; - -int opensslcrypto_load_lib( - knet_handle_t knet_h); - -int opensslcrypto_init( - knet_handle_t knet_h, - struct knet_handle_crypto_cfg *knet_handle_crypto_cfg); - -void opensslcrypto_fini( - knet_handle_t knet_h); - -int opensslcrypto_authenticate_and_decrypt ( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - -int opensslcrypto_encrypt_and_sign ( - knet_handle_t knet_h, - const unsigned char *buf_in, - const ssize_t buf_in_len, - unsigned char *buf_out, - ssize_t *buf_out_len); - -int opensslcrypto_encrypt_and_signv ( - knet_handle_t knet_h, - const struct iovec *iov_in, - int iovcnt_in, - unsigned char *buf_out, - ssize_t *buf_out_len); - -#endif diff --git a/libknet/crypto_openssl_remap.h b/libknet/crypto_openssl_remap.h deleted file mode 100644 index 6d2d609e..00000000 --- a/libknet/crypto_openssl_remap.h +++ /dev/null @@ -1,58 +0,0 @@ -#include "remap.h" - -#ifdef BUILDCRYPTOOPENSSL10 -REMAP_PROTO(void,OPENSSL_add_all_algorithms_noconf,(void)) -#endif -#ifdef BUILDCRYPTOOPENSSL11 -REMAP_PROTO(int,OPENSSL_init_crypto, - (uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)) -#endif - -#ifdef BUILDCRYPTOOPENSSL10 -REMAP_PROTO(void,ERR_load_crypto_strings,(void)) -#endif -REMAP_PROTO(unsigned long,ERR_get_error,(void)) -REMAP_PROTO(void,ERR_error_string_n, - (unsigned long e, char *buf, size_t len)) - -REMAP_PROTO(void,RAND_seed,(const void *buf, int num)) -REMAP_PROTO(int,RAND_bytes,(unsigned char *buf, int num)) - -REMAP_PROTO(const EVP_MD *,EVP_get_digestbyname,(const char *name)) -REMAP_PROTO(int,EVP_MD_size,(const EVP_MD *md)) -REMAP_PROTO(unsigned char *,HMAC, - (const EVP_MD *evp_md, const void *key, int key_len, - const unsigned char *d, size_t n, unsigned char *md, - unsigned int *md_len)) - -REMAP_PROTO(const EVP_CIPHER *,EVP_get_cipherbyname,(const char *name)) -REMAP_PROTO(int,EVP_CIPHER_block_size,(const EVP_CIPHER *cipher)) - -#ifdef BUILDCRYPTOOPENSSL10 -REMAP_PROTO(void,EVP_CIPHER_CTX_init,(EVP_CIPHER_CTX *a)) -REMAP_PROTO(int,EVP_CIPHER_CTX_cleanup,(EVP_CIPHER_CTX *a)) -#endif -#ifdef BUILDCRYPTOOPENSSL11 -REMAP_PROTO(EVP_CIPHER_CTX *,EVP_CIPHER_CTX_new,(void)) -REMAP_PROTO(void,EVP_CIPHER_CTX_free,(EVP_CIPHER_CTX *c)) -#endif - -REMAP_PROTO(int,EVP_EncryptInit_ex, - (EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, - ENGINE *impl, const unsigned char *key, - const unsigned char *iv)) -REMAP_PROTO(int,EVP_EncryptUpdate, - (EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, - const unsigned char *in, int inl)) -REMAP_PROTO(int,EVP_EncryptFinal_ex, - (EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)) - -REMAP_PROTO(int,EVP_DecryptInit_ex, - (EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, - ENGINE *impl, const unsigned char *key, - const unsigned char *iv)) -REMAP_PROTO(int,EVP_DecryptUpdate, - (EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, - const unsigned char *in, int inl)) -REMAP_PROTO(int,EVP_DecryptFinal_ex, - (EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl)) diff --git a/libknet/libknet.h b/libknet/libknet.h index 621673fb..705440eb 100644 --- a/libknet/libknet.h +++ b/libknet/libknet.h @@ -1,1944 +1,1945 @@ /* * Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. * * Authors: Fabio M. Di Nitto * Federico Simoncelli * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #ifndef __LIBKNET_H__ #define __LIBKNET_H__ #include #include #include +#include /** * @file libknet.h * @brief kronosnet API include file * @copyright Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. * * Kronosnet is an advanced VPN system for High Availability applications. */ /* * libknet limits */ /* * Maximum number of hosts */ typedef uint16_t knet_node_id_t; #define KNET_MAX_HOST 65536 /* * Maximum number of links between 2 hosts */ #define KNET_MAX_LINK 8 /* * Maximum packet size that should be written to datafd * see knet_handle_new for details */ #define KNET_MAX_PACKET_SIZE 65536 /* * Buffers used for pretty logging * host is used to store both ip addresses and hostnames */ #define KNET_MAX_HOST_LEN 256 #define KNET_MAX_PORT_LEN 6 /* * Some notifications can be generated either on TX or RX */ #define KNET_NOTIFY_TX 0 #define KNET_NOTIFY_RX 1 /* * Link flags */ /* * Where possible, set traffic priority to high. * On Linux this sets the TOS to INTERACTIVE (6), * see tc-prio(8) for more infomation */ #define KNET_LINK_FLAG_TRAFFICHIPRIO (1ULL << 0) typedef struct knet_handle *knet_handle_t; /* * Handle structs/API calls */ /** * knet_handle_new * * @brief create a new instance of a knet handle * * host_id - Each host in a knet is identified with a unique * ID. when creating a new handle local host_id * must be specified (0 to UINT16T_MAX are all valid). * It is the user's responsibility to check that the value * is unique, or bad things might happen. * * log_fd - Write file descriptor. If set to a value > 0, it will be used * to write log packets from libknet to the application. * Setting to 0 will disable logging from libknet. * It is possible to enable logging at any given time (see logging API). * Make sure to either read from this filedescriptor properly and/or * mark it O_NONBLOCK, otherwise if the fd becomes full, libknet could * block. * * default_log_level - * If logfd is specified, it will initialize all subsystems to log * at default_log_level value. (see logging API) * * @return * on success, a new knet_handle_t is returned. * on failure, NULL is returned and errno is set. */ knet_handle_t knet_handle_new(knet_node_id_t host_id, int log_fd, uint8_t default_log_level); /** * knet_handle_free * @brief Destroy a knet handle, free all resources * * knet_h - pointer to knet_handle_t * * @return * knet_handle_free returns * 0 on success * -1 on error and errno is set. */ int knet_handle_free(knet_handle_t knet_h); /** * knet_handle_enable_sock_notify * @brief Register a callback to receive socket events * * knet_h - pointer to knet_handle_t * * sock_notify_fn_private_data * void pointer to data that can be used to identify * the callback. * * sock_notify_fn * A callback function that is invoked every time * a socket in the datafd pool will report an error (-1) * or an end of read (0) (see socket.7). * This function MUST NEVER block or add substantial delays. * The callback is invoked in an internal unlocked area * to allow calls to knet_handle_add_datafd/knet_handle_remove_datafd * to swap/replace the bad fd. * if both err and errno are 0, it means that the socket * has received a 0 byte packet (EOF?). * The callback function must either remove the fd from knet * (by calling knet_handle_remove_fd()) or dup a new fd in its place. * Failure to do this can cause problems. * * @return * knet_handle_enable_sock_notify returns * 0 on success * -1 on error and errno is set. */ int knet_handle_enable_sock_notify(knet_handle_t knet_h, void *sock_notify_fn_private_data, void (*sock_notify_fn) ( void *private_data, int datafd, int8_t channel, uint8_t tx_rx, int error, int errorno)); /* sorry! can't call it errno ;) */ #define KNET_DATAFD_MAX 32 /** * knet_handle_add_datafd * * @brief Install a file descriptor for communication * * IMPORTANT: In order to add datafd to knet, knet_handle_enable_sock_notify * _MUST_ be set and be able to handle both errors (-1) and * 0 bytes read / write from the provided datafd. * On read error (< 0) from datafd, the socket is automatically * removed from polling to avoid spinning on dead sockets. * It is safe to call knet_handle_remove_datafd even on sockets * that have been removed. * * knet_h - pointer to knet_handle_t * * *datafd - read/write file descriptor. * knet will read data here to send to the other hosts * and will write data received from the network. * Each data packet can be of max size KNET_MAX_PACKET_SIZE! * Applications using knet_send/knet_recv will receive a * proper error if the packet size is not within boundaries. * Applications using their own functions to write to the * datafd should NOT write more than KNET_MAX_PACKET_SIZE. * * Please refer to handle.c on how to set up a socketpair. * * datafd can be 0, and knet_handle_add_datafd will create a properly * populated socket pair the same way as ping_test, or a value * higher than 0. A negative number will return an error. * On exit knet_handle_free will take care to cleanup the * socketpair only if they have been created by knet_handle_add_datafd. * * It is possible to pass either sockets or normal fds. * User provided datafd will be marked as non-blocking and close-on-exit. * * *channel - This value has the same effect of VLAN tagging. * A negative value will auto-allocate a channel. * Setting a value between 0 and 31 will try to allocate that * specific channel (unless already in use). * * It is possible to add up to 32 datafds but be aware that each * one of them must have a receiving end on the other host. * * Example: * hostA channel 0 will be delivered to datafd on hostB channel 0 * hostA channel 1 to hostB channel 1. * * Each channel must have a unique file descriptor. * * If your application could have 2 channels on one host and one * channel on another host, then you can use dst_host_filter * to manipulate channel values on TX and RX. * * @return * knet_handle_add_datafd returns * @retval 0 on success, * *datafd will be populated with a socket if the original value was 0 * or if a specific fd was set, the value is untouched. * *channel will be populated with a channel number if the original value * was negative or the value is untouched if a specific channel * was requested. * * @retval -1 on error and errno is set. * *datafd and *channel are untouched or empty. */ int knet_handle_add_datafd(knet_handle_t knet_h, int *datafd, int8_t *channel); /** * knet_handle_remove_datafd * @brief Remove a file descriptor from knet * * knet_h - pointer to knet_handle_t * * datafd - file descriptor to remove. * NOTE that if the socket/fd was created by knet_handle_add_datafd, * the socket will be closed by libknet. * * @return * knet_handle_remove_datafd returns * 0 on success * -1 on error and errno is set. */ int knet_handle_remove_datafd(knet_handle_t knet_h, int datafd); /** * knet_handle_get_channel * @brief Get the channel associated with a file descriptor * * knet_h - pointer to knet_handle_t * * datafd - get the channel associated to this datafd * * *channel - will contain the result * * @return * knet_handle_get_channel returns * @retval 0 on success * and *channel will contain the result * @retval -1 on error and errno is set. * and *channel content is meaningless */ int knet_handle_get_channel(knet_handle_t knet_h, const int datafd, int8_t *channel); /** * knet_handle_get_datafd * @brief Get the file descriptor associated with a channel * * knet_h - pointer to knet_handle_t * * channel - get the datafd associated to this channel * * *datafd - will contain the result * * @return * knet_handle_get_datafd returns * @retval 0 on success * and *datafd will contain the results * @retval -1 on error and errno is set. * and *datafd content is meaningless */ int knet_handle_get_datafd(knet_handle_t knet_h, const int8_t channel, int *datafd); /** * knet_recv * @brief Receive data from knet nodes * * knet_h - pointer to knet_handle_t * * buff - pointer to buffer to store the received data * * buff_len - buffer length * * channel - channel number * * @return * knet_recv is a commodity function to wrap iovec operations * around a socket. It returns a call to readv(2). */ ssize_t knet_recv(knet_handle_t knet_h, char *buff, const size_t buff_len, const int8_t channel); /** * knet_send * @brief Send data to knet nodes * * knet_h - pointer to knet_handle_t * * buff - pointer to the buffer of data to send * * buff_len - length of data to send * * channel - channel number * * @return * knet_send is a commodity function to wrap iovec operations * around a socket. It returns a call to writev(2). */ ssize_t knet_send(knet_handle_t knet_h, const char *buff, const size_t buff_len, const int8_t channel); /** * knet_send_sync * * @brief Synchronously send data to knet nodes * * knet_h - pointer to knet_handle_t * * buff - pointer to the buffer of data to send * * buff_len - length of data to send * * channel - data channel to use (see knet_handle_add_datafd(3)) * * All knet RX/TX operations are async for performance reasons. * There are applications that might need a sync version of data * transmission and receive errors in case of failure to deliver * to another host. * knet_send_sync bypasses the whole TX async layer and delivers * data directly to the link layer, and returns errors accordingly. * knet_send_sync allows to send only one packet to one host at * a time. It does NOT support multiple destinations or multicast * packets. Decision is still based on dst_host_filter_fn. * * @return * knet_send_sync returns 0 on success and -1 on error. * In addition to normal sendmmsg errors, knet_send_sync can fail * due to: * * @retval ECANCELED - data forward is disabled * @retval EFAULT - dst_host_filter fatal error * @retval EINVAL - dst_host_filter did not provide dst_host_ids_entries on unicast pckts * @retval E2BIG - dst_host_filter did return more than one dst_host_ids_entries on unicast pckts * @retval ENOMSG - received unknown message type * @retval EHOSTDOWN - unicast pckt cannot be delivered because dest host is not connected yet * @retval ECHILD - crypto failed * @retval EAGAIN - sendmmsg was unable to send all messages and there was no progress during retry */ int knet_send_sync(knet_handle_t knet_h, const char *buff, const size_t buff_len, const int8_t channel); /** * knet_handle_enable_filter * * @brief install a filter to route packets * * knet_h - pointer to knet_handle_t * * dst_host_filter_fn_private_data * void pointer to data that can be used to identify * the callback. * * dst_host_filter_fn - * is a callback function that is invoked every time * a packet hits datafd (see knet_handle_new(3)). * the function allows users to tell libknet where the * packet has to be delivered. * * const unsigned char *outdata - is a pointer to the * current packet * ssize_t outdata_len - length of the above data * uint8_t tx_rx - filter is called on tx or rx * (KNET_NOTIFY_TX, KNET_NOTIFY_RX) * knet_node_id_t this_host_id - host_id processing the packet * knet_node_id_t src_host_id - host_id that generated the * packet * knet_node_id_t *dst_host_ids - array of KNET_MAX_HOST knet_node_id_t * where to store the destinations * size_t *dst_host_ids_entries - number of hosts to send the message * * dst_host_filter_fn should return * -1 on error, packet is discarded. * 0 packet is unicast and should be sent to dst_host_ids and there are * dst_host_ids_entries in the buffer. * 1 packet is broadcast/multicast and is sent all hosts. * contents of dst_host_ids and dst_host_ids_entries are ignored. * (see also kronosnetd/etherfilter.* for an example that filters based * on ether protocol) * * @return * knet_handle_enable_filter returns * 0 on success * -1 on error and errno is set. */ int knet_handle_enable_filter(knet_handle_t knet_h, void *dst_host_filter_fn_private_data, int (*dst_host_filter_fn) ( void *private_data, const unsigned char *outdata, ssize_t outdata_len, uint8_t tx_rx, knet_node_id_t this_host_id, knet_node_id_t src_host_id, int8_t *channel, knet_node_id_t *dst_host_ids, size_t *dst_host_ids_entries)); /** * knet_handle_setfwd * * @brief Start packet forwarding * * knet_h - pointer to knet_handle_t * * enable - set to 1 to allow data forwarding, 0 to disable data forwarding. * * @return * knet_handle_setfwd returns * 0 on success * -1 on error and errno is set. * * By default data forwarding is off and no traffic will pass through knet until * it is set on. */ int knet_handle_setfwd(knet_handle_t knet_h, unsigned int enabled); #define KNET_PMTUD_DEFAULT_INTERVAL 60 /** * knet_handle_pmtud_setfreq * * @brief Set the interval between PMTUd scans * * knet_h - pointer to knet_handle_t * * interval - define the interval in seconds between PMTUd scans * range from 1 to 86400 (24h) * * @return * knet_handle_pmtud_setfreq returns * 0 on success * -1 on error and errno is set. * * default interval is 60. */ int knet_handle_pmtud_setfreq(knet_handle_t knet_h, unsigned int interval); /** * knet_handle_pmtud_getfreq * * @brief Get the interval between PMTUd scans * * knet_h - pointer to knet_handle_t * * interval - pointer where to store the current interval value * * @return * knet_handle_pmtud_setfreq returns * 0 on success * -1 on error and errno is set. */ int knet_handle_pmtud_getfreq(knet_handle_t knet_h, unsigned int *interval); /** * knet_handle_enable_pmtud_notify * * @brief install a callback to receive PMTUd changes * * knet_h - pointer to knet_handle_t * * pmtud_notify_fn_private_data * void pointer to data that can be used to identify * the callback. * * pmtud_notify_fn * is a callback function that is invoked every time * a path MTU size change is detected. * The function allows libknet to notify the user * of data MTU, that's the max value that can be send * onwire without fragmentation. The data MTU will always * be lower than real link MTU because it accounts for * protocol overhead, knet packet header and (if configured) * crypto overhead, * This function MUST NEVER block or add substantial delays. * * @return * knet_handle_enable_pmtud_notify returns * 0 on success * -1 on error and errno is set. */ int knet_handle_enable_pmtud_notify(knet_handle_t knet_h, void *pmtud_notify_fn_private_data, void (*pmtud_notify_fn) ( void *private_data, unsigned int data_mtu)); /** * knet_handle_pmtud_get * * @brief Get the current data MTU * * knet_h - pointer to knet_handle_t * * data_mtu - pointer where to store data_mtu * * @return * knet_handle_pmtud_get returns * 0 on success * -1 on error and errno is set. */ int knet_handle_pmtud_get(knet_handle_t knet_h, unsigned int *data_mtu); #define KNET_MIN_KEY_LEN 256 #define KNET_MAX_KEY_LEN 4096 struct knet_handle_crypto_cfg { char crypto_model[16]; char crypto_cipher_type[16]; char crypto_hash_type[16]; unsigned char private_key[KNET_MAX_KEY_LEN]; unsigned int private_key_len; }; /** * knet_handle_crypto * * @brief set up packet cryptographic signing & encryption * * knet_h - pointer to knet_handle_t * * knet_handle_crypto_cfg - * pointer to a knet_handle_crypto_cfg structure * * crypto_model should contain the model name. * Currently only "openssl" and "nss" are supported. * Setting to "none" will disable crypto. * * crypto_cipher_type * should contain the cipher algo name. * It can be set to "none" to disable * encryption. * Currently supported by "nss" model: * "3des", "aes128", "aes192" and "aes256". * "openssl" model supports more modes and it strictly * depends on the openssl build. See: EVP_get_cipherbyname * openssl API call for details. * * crypto_hash_type * should contain the hashing algo name. * It can be set to "none" to disable * hashing. * Currently supported by "nss" model: * "md5", "sha1", "sha256", "sha384" and "sha512". * "openssl" model supports more modes and it strictly * depends on the openssl build. See: EVP_get_digestbyname * openssl API call for details. * * private_key will contain the private shared key. * It has to be at least KNET_MIN_KEY_LEN long. * * private_key_len * length of the provided private_key. * * Implementation notes/current limitations: * - enabling crypto, will increase latency as packets have * to processed. * - enabling crypto might reduce the overall throughtput * due to crypto data overhead. * - re-keying is not implemented yet. * - private/public key encryption/hashing is not currently * planned. * - crypto key must be the same for all hosts in the same * knet instance. * - it is safe to call knet_handle_crypto multiple times at runtime. * The last config will be used. * IMPORTANT: a call to knet_handle_crypto can fail due to: * 1) failure to obtain locking * 2) errors to initializing the crypto level. * This can happen even in subsequent calls to knet_handle_crypto. * A failure in crypto init, might leave your traffic unencrypted! * It's best to stop data forwarding (see knet_handle_setfwd(3)), change crypto config, * start forward again. * * @return * knet_handle_crypto returns: * @retval 0 on success * @retval -1 on error and errno is set. * @retval -2 on crypto subsystem initialization error. No errno is provided at the moment (yet). */ int knet_handle_crypto(knet_handle_t knet_h, struct knet_handle_crypto_cfg *knet_handle_crypto_cfg); #define KNET_COMPRESS_THRESHOLD 100 struct knet_handle_compress_cfg { char compress_model[16]; uint32_t compress_threshold; int compress_level; }; /** * knet_handle_compress * * @brief Set up packet compression * * knet_h - pointer to knet_handle_t * * knet_handle_compress_cfg - * pointer to a knet_handle_compress_cfg structure * * compress_model should contain the mode name. * Currently only "zlib" and "lz4" are supported. * Setting to "none" will disable compression. * * compress_threshold * tells the transmission thread to NOT compress * any packets that are smaller than the value * indicated. Default 100 bytes. * Set to 0 to reset to the default. * Set to 1 to compress everything. * Max accepted value is KNET_MAX_PACKET_SIZE. * * compress_level some compression libraries allow tuning of compression * parameters. * For example zlib value ranges from 0 to 9 where 0 is no * compression and 9 is max compression. * This value is passed pristine to the compression library. * zlib: 0 (no compression), 1 (minimal) .. 9 (max compression). * lz4: 1 (max compression)... 9 (fastest compression). * lz4hc: 1 (min compression) ... LZ4HC_MAX_CLEVEL (16) or LZ4HC_CLEVEL_MAX (12) * depends on the installed version of lz4hc. libknet can detects the max * value and will print an appropriate warning. * lzo2: accepts only some specific values depending on the * requested algorithm: * 1 : lzo1x_1_compress (default) * 11 : lzo1x_1_11_compress * 12 : lzo1x_1_12_compress * 15 : lzo1x_1_15_compress * 999: lzo1x_999_compress * every other values will use default * lzma: 0 (minimal) .. 9 (max compression) * bzip2: 1 (minimal) .. 9 (max compression) * Please refer to the library man pages * on how to be set this value, as it is passed * unmodified to the compression algorithm where supported. * * Implementation notes: * - it is possible to enable/disable compression at any time. * - nodes can be using a different compression algorithm at any time. * - knet does NOT implement the compression algorithm directly. it relies * on external libraries for this functionality. Please read * the libraries man pages to figure out which algorithm/compression * level is best for the data you are planning to transmit. * * @return * knet_handle_compress returns * 0 on success * -1 on error and errno is set. EINVAL means that either the model or the * level are not supported. */ int knet_handle_compress(knet_handle_t knet_h, struct knet_handle_compress_cfg *knet_handle_compress_cfg); struct knet_handle_stats { size_t size; uint64_t tx_uncompressed_packets; uint64_t tx_compressed_packets; uint64_t tx_compressed_original_bytes; uint64_t tx_compressed_size_bytes; uint64_t tx_compress_time_ave; uint64_t tx_compress_time_min; uint64_t tx_compress_time_max; uint64_t rx_compressed_packets; uint64_t rx_compressed_original_bytes; uint64_t rx_compressed_size_bytes; uint64_t rx_compress_time_ave; uint64_t rx_compress_time_min; uint64_t rx_compress_time_max; /* Overhead times, measured in usecs */ uint64_t tx_crypt_packets; uint64_t tx_crypt_byte_overhead; uint64_t tx_crypt_time_ave; uint64_t tx_crypt_time_min; uint64_t tx_crypt_time_max; uint64_t rx_crypt_packets; uint64_t rx_crypt_time_ave; uint64_t rx_crypt_time_min; uint64_t rx_crypt_time_max; }; /** * knet_handle_get_stats * * @brief Get statistics for compression & crypto * * knet_h - pointer to knet_handle_t * * knet_handle_stats * pointer to a knet_handle_stats structure * * struct_size * size of knet_handle_stats structure to allow * for backwards compatibility. libknet will only * copy this much data into the stats structure * so that older callers will not get overflowed if * new fields are added. * * @return * 0 on success * -1 on error and errno is set. * */ int knet_handle_get_stats(knet_handle_t knet_h, struct knet_handle_stats *stats, size_t struct_size); /* * Tell knet_handle_clear_stats whether to clear just the handle stats * or all of them. */ #define KNET_CLEARSTATS_HANDLE_ONLY 1 #define KNET_CLEARSTATS_HANDLE_AND_LINK 2 /** * knet_handle_clear_stats * * @brief Clear knet stats, link and/or handle * * knet_h - pointer to knet_handle_t * * clear_option - Which stats to clear, must be one of * * KNET_CLEARSTATS_HANDLE_ONLY or * KNET_CLEARSTATS_HANDLE_AND_LINK * * @return * 0 on success * -1 on error and errno is set. * */ int knet_handle_clear_stats(knet_handle_t knet_h, int clear_option); struct knet_crypto_info { const char *name; /* openssl,nss,etc.. */ uint8_t properties; /* currently unused */ char pad[256]; /* currently unused */ }; /** * knet_get_crypto_list * * @brief Get a list of supported crypto libraries * * crypto_list - array of struct knet_crypto_info * * If NULL then only the number of structs is returned in crypto_list_entries * to allow the caller to allocate sufficient space. * libknet does not allow more than 256 crypto methods at the moment. * it is safe to allocate 256 structs to avoid calling * knet_get_crypto_list twice. * * crypto_list_entries - returns the number of structs in crypto_list * * @return * knet_get_crypto_list returns * 0 on success * -1 on error and errno is set. */ int knet_get_crypto_list(struct knet_crypto_info *crypto_list, size_t *crypto_list_entries); struct knet_compress_info { const char *name; /* bzip2, lz4, etc.. */ uint8_t properties; /* currently unused */ char pad[256]; /* currently unused */ }; /** * knet_get_compress_list * * @brief Get a list of support compression types * * compress_list - array of struct knet_compress_info * * If NULL then only the number of structs is returned in compress_list_entries * to allow the caller to allocate sufficient space. * libknet does not allow more than 256 compress methods at the moment. * it is safe to allocate 256 structs to avoid calling * knet_get_compress_list twice. * * compress_list_entries - returns the number of structs in compress_list * * @return * knet_get_compress_list returns * 0 on success * -1 on error and errno is set. */ int knet_get_compress_list(struct knet_compress_info *compress_list, size_t *compress_list_entries); /* * host structs/API calls */ /** * knet_host_add * * @brief Add a new host ID to knet * * knet_h - pointer to knet_handle_t * * host_id - each host in a knet is identified with a unique ID * (see also knet_handle_new(3)) * * @return * knet_host_add returns: * 0 on success * -1 on error and errno is set. */ int knet_host_add(knet_handle_t knet_h, knet_node_id_t host_id); /** * knet_host_remove * * @brief Remove a host ID from knet * * knet_h - pointer to knet_handle_t * * host_id - each host in a knet is identified with a unique ID * (see also knet_handle_new(3)) * * @return * knet_host_remove returns: * 0 on success * -1 on error and errno is set. */ int knet_host_remove(knet_handle_t knet_h, knet_node_id_t host_id); /** * knet_host_set_name * * @brief Set the name of a knet host * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * name - this name will be used for pretty logging and eventually * search for hosts (see also knet_handle_host_get_name(2) and knet_handle_host_get_id(3)). * Only up to KNET_MAX_HOST_LEN - 1 bytes will be accepted and * name has to be unique for each host. * * @return * knet_host_set_name returns: * 0 on success * -1 on error and errno is set. */ int knet_host_set_name(knet_handle_t knet_h, knet_node_id_t host_id, const char *name); /** * knet_host_get_name_by_host_id * * @brief Get the name of a host given its ID * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * name - pointer to a preallocated buffer of at least size KNET_MAX_HOST_LEN * where the current host name will be stored * (as set by knet_host_set_name or default by knet_host_add) * * @return * knet_host_get_name_by_host_id returns: * 0 on success * -1 on error and errno is set (name is left untouched) */ int knet_host_get_name_by_host_id(knet_handle_t knet_h, knet_node_id_t host_id, char *name); /** * knet_host_get_id_by_host_name * * @brief Get the ID of a host given its name * * knet_h - pointer to knet_handle_t * * name - name to lookup, max len KNET_MAX_HOST_LEN * * host_id - where to store the result * * @return * knet_host_get_id_by_host_name returns: * 0 on success * -1 on error and errno is set. */ int knet_host_get_id_by_host_name(knet_handle_t knet_h, const char *name, knet_node_id_t *host_id); /** * knet_host_get_host_list * * @brief Get a list of hosts known to knet * * knet_h - pointer to knet_handle_t * * host_ids - array of at lest KNET_MAX_HOST size * * host_ids_entries - * number of entries writted in host_ids * * @return * knet_host_get_host_list returns * 0 on success * -1 on error and errno is set. */ int knet_host_get_host_list(knet_handle_t knet_h, knet_node_id_t *host_ids, size_t *host_ids_entries); /* * define switching policies */ #define KNET_LINK_POLICY_PASSIVE 0 #define KNET_LINK_POLICY_ACTIVE 1 #define KNET_LINK_POLICY_RR 2 /** * knet_host_set_policy * * knet_h - pointer to knet_handle_t * * @brief Set the switching policy for a host's links * * host_id - see knet_host_add(3) * * policy - there are currently 3 kind of simple switching policies * based on link configuration. * KNET_LINK_POLICY_PASSIVE - the active link with the lowest * priority will be used. * if one or more active links share * the same priority, the one with * lowest link_id will be used. * * KNET_LINK_POLICY_ACTIVE - all active links will be used * simultaneously to send traffic. * link priority is ignored. * * KNET_LINK_POLICY_RR - round-robin policy, every packet * will be send on a different active * link. * * @return * knet_host_set_policy returns * 0 on success * -1 on error and errno is set. */ int knet_host_set_policy(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t policy); /** * knet_host_get_policy * * @brief Get the switching policy for a host's links * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * policy - will contain the current configured switching policy. * Default is passive when creating a new host. * * @return * knet_host_get_policy returns * 0 on success * -1 on error and errno is set. */ int knet_host_get_policy(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t *policy); /** * knet_host_enable_status_change_notify * * @brief Install a callback to get host status change events * * knet_h - pointer to knet_handle_t * * host_status_change_notify_fn_private_data - * void pointer to data that can be used to identify * the callback * * host_status_change_notify_fn - * is a callback function that is invoked every time * there is a change in the host status. * host status is identified by: * - reachable, this host can send/receive data to/from host_id * - remote, 0 if the host_id is connected locally or 1 if * the there is one or more knet host(s) in between. * NOTE: re-switching is NOT currently implemented, * but this is ready for future and can avoid * an API/ABI breakage later on. * - external, 0 if the host_id is configured locally or 1 if * it has been added from remote nodes config. * NOTE: dynamic topology is NOT currently implemented, * but this is ready for future and can avoid * an API/ABI breakage later on. * This function MUST NEVER block or add substantial delays. * * @return * knet_host_status_change_notify returns * 0 on success * -1 on error and errno is set. */ int knet_host_enable_status_change_notify(knet_handle_t knet_h, void *host_status_change_notify_fn_private_data, void (*host_status_change_notify_fn) ( void *private_data, knet_node_id_t host_id, uint8_t reachable, uint8_t remote, uint8_t external)); /* * define host status structure for quick lookup * struct is in flux as more stats will be added soon * * reachable host_id can be seen either directly connected * or via another host_id * * remote 0 = node is connected locally, 1 is visible via * via another host_id * * external 0 = node is configured/known locally, * 1 host_id has been received via another host_id */ struct knet_host_status { uint8_t reachable; uint8_t remote; uint8_t external; /* add host statistics */ }; /** * knet_host_status_get * * @brief Get the status of a host * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * status - pointer to knet_host_status struct * * @return * knet_handle_pmtud_get returns * 0 on success * -1 on error and errno is set. */ int knet_host_get_status(knet_handle_t knet_h, knet_node_id_t host_id, struct knet_host_status *status); /* * link structs/API calls * * every host allocated/managed by knet_host_* has * KNET_MAX_LINK structures to define the network * paths that connect 2 hosts. * * Each link is identified by a link_id that has a * values between 0 and KNET_MAX_LINK - 1. * * KNOWN LIMITATIONS: * * - let's assume the scenario where two hosts are connected * with any number of links. link_id must match on both sides. * If host_id 0 link_id 0 is configured to connect IP1 to IP2 and * host_id 0 link_id 1 is configured to connect IP3 to IP4, * host_id 1 link_id 0 _must_ connect IP2 to IP1 and likewise * host_id 1 link_id 1 _must_ connect IP4 to IP3. * We might be able to lift this restriction in future, by using * other data to determine src/dst link_id, but for now, deal with it. */ /* * commodity functions to convert strings to sockaddr and viceversa */ /** * knet_strtoaddr * * @brief Convert a hostname string to an address * * host - IPaddr/hostname to convert * be aware only the first IP address will be returned * in case a hostname resolves to multiple IP * * port - port to connect to * * ss - sockaddr_storage where to store the converted data * * sslen - len of the sockaddr_storage * * @return * knet_strtoaddr returns same error codes as getaddrinfo * */ int knet_strtoaddr(const char *host, const char *port, struct sockaddr_storage *ss, socklen_t sslen); /** * knet_addrtostr * * @brief Convert an address to a host name * * ss - sockaddr_storage to convert * * sslen - len of the sockaddr_storage * * host - IPaddr/hostname where to store data * (recommended size: KNET_MAX_HOST_LEN) * * port - port buffer where to store data * (recommended size: KNET_MAX_PORT_LEN) * * @return * knet_strtoaddr returns same error codes as getnameinfo */ int knet_addrtostr(const struct sockaddr_storage *ss, socklen_t sslen, char *addr_buf, size_t addr_buf_size, char *port_buf, size_t port_buf_size); #define KNET_TRANSPORT_LOOPBACK 0 #define KNET_TRANSPORT_UDP 1 #define KNET_TRANSPORT_SCTP 2 #define KNET_MAX_TRANSPORTS UINT8_MAX /* * The Loopback transport is only valid for connections to localhost, the host * with the same node_id specified in knet_handle_new(). Only one link of this * type is allowed. Data sent down a LOOPBACK link will be copied directly from * the knet send datafd to the knet receive datafd so the application must be set * up to take data from that socket at least as often as it is sent or deadlocks * could occur. If used, a LOOPBACK link must be the only link configured to the * local host. */ struct knet_transport_info { const char *name; /* UDP/SCTP/etc... */ uint8_t id; /* value that can be used for link_set_config */ uint8_t properties; /* currently unused */ char pad[256]; /* currently unused */ }; /** * knet_get_transport_list * * @brief Get a list of the transports support by this build of knet * * transport_list - an array of struct transport_info that must be * at least of size struct transport_info * KNET_MAX_TRANSPORTS * * transport_list_entries - pointer to a size_t where to store how many transports * are available in this build of libknet. * * @return * knet_get_transport_list returns * 0 on success * -1 on error and errno is set. */ int knet_get_transport_list(struct knet_transport_info *transport_list, size_t *transport_list_entries); /** * knet_get_transport_name_by_id * * @brief Get a transport name from its ID number * * transport - one of the KNET_TRANSPORT_xxx constants * * @return * knet_get_transport_name_by_id returns: * * @retval pointer to the name on success or * @retval NULL on error and errno is set. */ const char *knet_get_transport_name_by_id(uint8_t transport); /** * knet_get_transport_id_by_name * * @brief Get a transport ID from its name * * name - transport name (UDP/SCTP/etc) * * @return * knet_get_transport_name_by_id returns: * * @retval KNET_MAX_TRANSPORTS on error and errno is set accordingly * @retval KNET_TRANSPORT_xxx on success. */ uint8_t knet_get_transport_id_by_name(const char *name); #define KNET_TRANSPORT_DEFAULT_RECONNECT_INTERVAL 1000 /** * knet_handle_set_transport_reconnect_interval * * @brief Set the interval between transport attempts to reconnect a failed link * * knet_h - pointer to knet_handle_t * * msecs - milliseconds * * @return * knet_handle_set_transport_reconnect_interval returns * 0 on success * -1 on error and errno is set. */ int knet_handle_set_transport_reconnect_interval(knet_handle_t knet_h, uint32_t msecs); /** * knet_handle_get_transport_reconnect_interval * * @brief Get the interval between transport attempts to reconnect a failed link * * knet_h - pointer to knet_handle_t * * msecs - milliseconds * * @return * knet_handle_get_transport_reconnect_interval returns * 0 on success * -1 on error and errno is set. */ int knet_handle_get_transport_reconnect_interval(knet_handle_t knet_h, uint32_t *msecs); /** * knet_link_set_config * * @brief Configure the link to a host * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * link_id - see knet_link_set_config(3) * * transport - one of the KNET_TRANSPORT_xxx constants * * src_addr - sockaddr_storage that can be either IPv4 or IPv6 * * dst_addr - sockaddr_storage that can be either IPv4 or IPv6 * this can be null if we don't know the incoming * IP address/port and the link will remain quiet * till the node on the other end will initiate a * connection * * flags - KNET_LINK_FLAG_* * * @return * knet_link_set_config returns * 0 on success * -1 on error and errno is set. */ int knet_link_set_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id, uint8_t transport, struct sockaddr_storage *src_addr, struct sockaddr_storage *dst_addr, uint64_t flags); /** * knet_link_get_config * * @brief Get the link configutation information * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * link_id - see knet_link_set_config(3) * * transport - see knet_link_set_config(3) * * src_addr - sockaddr_storage that can be either IPv4 or IPv6 * * dst_addr - sockaddr_storage that can be either IPv4 or IPv6 * * dynamic - 0 if dst_addr is static or 1 if dst_addr is dynamic. * In case of 1, dst_addr can be NULL and it will be left * untouched. * * flags - KNET_LINK_FLAG_* * * @return * knet_link_get_config returns * 0 on success. * -1 on error and errno is set. */ int knet_link_get_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id, uint8_t *transport, struct sockaddr_storage *src_addr, struct sockaddr_storage *dst_addr, uint8_t *dynamic, uint64_t *flags); /** * knet_link_clear_config * * @brief Clear link information and disconnect the link * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * link_id - see knet_link_set_config(3) * * @return * knet_link_clear_config returns * 0 on success. * -1 on error and errno is set. */ int knet_link_clear_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id); /** * knet_link_set_enable * * @brief Enable traffic on a link * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * link_id - see knet_link_set_config(3) * * enabled - 0 disable the link, 1 enable the link * * @return * knet_link_set_enable returns * 0 on success * -1 on error and errno is set. */ int knet_link_set_enable(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id, unsigned int enabled); /** * knet_link_get_enable * * @brief Find out whether a link is enabled or not * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * link_id - see knet_link_set_config(3) * * enabled - 0 disable the link, 1 enable the link * * @return * knet_link_get_enable returns * 0 on success * -1 on error and errno is set. */ int knet_link_get_enable(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id, unsigned int *enabled); #define KNET_LINK_DEFAULT_PING_INTERVAL 1000 /* 1 second */ #define KNET_LINK_DEFAULT_PING_TIMEOUT 2000 /* 2 seconds */ #define KNET_LINK_DEFAULT_PING_PRECISION 2048 /* samples */ /** * knet_link_set_ping_timers * * @brief Set the ping timers for a link * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * link_id - see knet_link_set_config(3) * * interval - specify the ping interval in milliseconds. * * timeout - if no pong is received within this time, * the link is declared dead, in milliseconds. * NOTE: in future it will be possible to set timeout to 0 * for an autocalculated timeout based on interval, pong_count * and latency. The API already accept 0 as value and it will * return ENOSYS / -1. Once the automatic calculation feature * will be implemented, this call will only return EINVAL * for incorrect values. * * precision - how many values of latency are used to calculate * the average link latency (see also knet_link_get_status(3)) * * @return * knet_link_set_ping_timers returns * 0 on success * -1 on error and errno is set. */ int knet_link_set_ping_timers(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id, time_t interval, time_t timeout, unsigned int precision); /** * knet_link_get_ping_timers * * @brief Get the ping timers for a link * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * link_id - see knet_link_set_config(3) * * interval - ping interval * * timeout - if no pong is received within this time, * the link is declared dead * * precision - how many values of latency are used to calculate * the average link latency (see also knet_link_get_status(3)) * * @return * knet_link_get_ping_timers returns * 0 on success * -1 on error and errno is set. */ int knet_link_get_ping_timers(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id, time_t *interval, time_t *timeout, unsigned int *precision); #define KNET_LINK_DEFAULT_PONG_COUNT 5 /** * knet_link_set_pong_count * * @brief Set the pong count for a link * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * link_id - see knet_link_set_config(3) * * pong_count - how many valid ping/pongs before a link is marked UP. * default: 5, value should be > 0 * * @return * knet_link_set_pong_count returns * 0 on success * -1 on error and errno is set. */ int knet_link_set_pong_count(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id, uint8_t pong_count); /** * knet_link_get_pong_count * * @brief Get the pong count for a link * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * link_id - see knet_link_set_config(3) * * pong_count - how many valid ping/pongs before a link is marked UP. * default: 5, value should be > 0 * * @return * knet_link_get_pong_count returns * 0 on success * -1 on error and errno is set. */ int knet_link_get_pong_count(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id, uint8_t *pong_count); /** * knet_link_set_priority * * @brief Set the priority for a link * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * link_id - see knet_link_set_config(3) * * priority - specify the switching priority for this link * see also knet_host_set_policy * * @return * knet_link_set_priority returns * 0 on success * -1 on error and errno is set. */ int knet_link_set_priority(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id, uint8_t priority); /** * knet_link_get_priority * * @brief Get the priority for a link * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * link_id - see knet_link_set_config(3) * * priority - gather the switching priority for this link * see also knet_host_set_policy * * @return * knet_link_get_priority returns * 0 on success * -1 on error and errno is set. */ int knet_link_get_priority(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id, uint8_t *priority); /** * knet_link_get_link_list * * @brief Get a list of links connecting a host * * knet_h - pointer to knet_handle_t * * link_ids - array of at lest KNET_MAX_LINK size * with the list of configured links for a certain host. * * link_ids_entries - * number of entries contained in link_ids * * @return * knet_link_get_link_list returns * 0 on success * -1 on error and errno is set. */ int knet_link_get_link_list(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t *link_ids, size_t *link_ids_entries); /* * define link status structure for quick lookup * * src/dst_{ipaddr,port} strings are filled by * getnameinfo(3) when configuring the link. * if the link is dynamic (see knet_link_set_config(3)) * dst_ipaddr/port will contain ipaddr/port of the currently * connected peer or "Unknown" if it was not possible * to determine the ipaddr/port at runtime. * * enabled see also knet_link_set/get_enable. * * connected the link is connected to a peer and ping/pong traffic * is flowing. * * dynconnected the link has dynamic ip on the other end, and * we can see the other host is sending pings to us. * * latency average latency of this link * see also knet_link_set/get_timeout. * * pong_last if the link is down, this value tells us how long * ago this link was active. A value of 0 means that the link * has never been active. * * knet_link_stats structure that contains details statistics for the link */ #define MAX_LINK_EVENTS 16 struct knet_link_stats { /* onwire values */ uint64_t tx_data_packets; uint64_t rx_data_packets; uint64_t tx_data_bytes; uint64_t rx_data_bytes; uint64_t rx_ping_packets; uint64_t tx_ping_packets; uint64_t rx_ping_bytes; uint64_t tx_ping_bytes; uint64_t rx_pong_packets; uint64_t tx_pong_packets; uint64_t rx_pong_bytes; uint64_t tx_pong_bytes; uint64_t rx_pmtu_packets; uint64_t tx_pmtu_packets; uint64_t rx_pmtu_bytes; uint64_t tx_pmtu_bytes; /* Only filled in when requested */ uint64_t tx_total_packets; uint64_t rx_total_packets; uint64_t tx_total_bytes; uint64_t rx_total_bytes; uint64_t tx_total_errors; uint64_t tx_total_retries; uint32_t tx_pmtu_errors; uint32_t tx_pmtu_retries; uint32_t tx_ping_errors; uint32_t tx_ping_retries; uint32_t tx_pong_errors; uint32_t tx_pong_retries; uint32_t tx_data_errors; uint32_t tx_data_retries; /* measured in usecs */ uint32_t latency_min; uint32_t latency_max; uint32_t latency_ave; uint32_t latency_samples; /* how many times the link has been going up/down */ uint32_t down_count; uint32_t up_count; /* * circular buffer of time_t structs collecting the history * of up/down events on this link. * the index indicates current/last event. * it is safe to walk back the history by decreasing the index */ time_t last_up_times[MAX_LINK_EVENTS]; time_t last_down_times[MAX_LINK_EVENTS]; int8_t last_up_time_index; int8_t last_down_time_index; /* Always add new stats at the end */ }; struct knet_link_status { size_t size; /* For ABI checking */ char src_ipaddr[KNET_MAX_HOST_LEN]; char src_port[KNET_MAX_PORT_LEN]; char dst_ipaddr[KNET_MAX_HOST_LEN]; char dst_port[KNET_MAX_PORT_LEN]; uint8_t enabled; /* link is configured and admin enabled for traffic */ uint8_t connected; /* link is connected for data (local view) */ uint8_t dynconnected; /* link has been activated by remote dynip */ unsigned long long latency; /* average latency computed by fix/exp */ struct timespec pong_last; unsigned int mtu; /* current detected MTU on this link */ unsigned int proto_overhead; /* contains the size of the IP protocol, knet headers and * crypto headers (if configured). This value is filled in * ONLY after the first PMTUd run on that given link, * and can change if link configuration or crypto configuration * changes at runtime. * WARNING: in general mtu + proto_overhead might or might * not match the output of ifconfig mtu due to crypto * requirements to pad packets to some specific boundaries. */ /* Link statistics */ struct knet_link_stats stats; }; /** * knet_link_get_status * * @brief Get the status (and statistics) for a link * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * link_id - see knet_link_set_config(3) * * status - pointer to knet_link_status struct * * struct_size - max size of knet_link_status - allows library to * add fields without ABI change. Returned structure * will be truncated to this length and .size member * indicates the full size. * * @return * knet_link_get_status returns * 0 on success * -1 on error and errno is set. */ int knet_link_get_status(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id, struct knet_link_status *status, size_t struct_size); /* * logging structs/API calls */ /* * libknet is composed of several subsystems. In order * to easily distinguish log messages coming from different * places, each subsystem has its own ID. * * 0-19 config/management * 20-39 internal threads * 40-59 transports * 60-69 crypto implementations */ #define KNET_SUB_COMMON 0 /* common.c */ #define KNET_SUB_HANDLE 1 /* handle.c alloc/dealloc config changes */ #define KNET_SUB_HOST 2 /* host add/del/modify */ #define KNET_SUB_LISTENER 3 /* listeners add/del/modify... */ #define KNET_SUB_LINK 4 /* link add/del/modify */ #define KNET_SUB_TRANSPORT 5 /* Transport common */ #define KNET_SUB_CRYPTO 6 /* crypto.c config generic layer */ #define KNET_SUB_COMPRESS 7 /* compress.c config generic layer */ #define KNET_SUB_FILTER 19 /* allocated for users to log from dst_filter */ #define KNET_SUB_DSTCACHE 20 /* switching thread (destination cache handling) */ #define KNET_SUB_HEARTBEAT 21 /* heartbeat thread */ #define KNET_SUB_PMTUD 22 /* Path MTU Discovery thread */ #define KNET_SUB_TX 23 /* send to link thread */ #define KNET_SUB_RX 24 /* recv from link thread */ #define KNET_SUB_TRANSP_BASE 40 /* Base log level for transports */ #define KNET_SUB_TRANSP_LOOPBACK (KNET_SUB_TRANSP_BASE + KNET_TRANSPORT_LOOPBACK) #define KNET_SUB_TRANSP_UDP (KNET_SUB_TRANSP_BASE + KNET_TRANSPORT_UDP) #define KNET_SUB_TRANSP_SCTP (KNET_SUB_TRANSP_BASE + KNET_TRANSPORT_SCTP) #define KNET_SUB_NSSCRYPTO 60 /* nsscrypto.c */ #define KNET_SUB_OPENSSLCRYPTO 61 /* opensslcrypto.c */ #define KNET_SUB_ZLIBCOMP 70 /* compress_zlib.c */ #define KNET_SUB_LZ4COMP 71 /* compress_lz4.c */ #define KNET_SUB_LZ4HCCOMP 72 /* compress_lz4.c */ #define KNET_SUB_LZO2COMP 73 /* compress_lzo.c */ #define KNET_SUB_LZMACOMP 74 /* compress_lzma.c */ #define KNET_SUB_BZIP2COMP 75 /* compress_bzip2.c */ #define KNET_SUB_UNKNOWN UINT8_MAX - 1 #define KNET_MAX_SUBSYSTEMS UINT8_MAX /* * Convert between subsystem IDs and names */ /** * knet_log_get_subsystem_name * * @brief Get a logging system name from its numeric ID * * @return * returns internal name of the subsystem or "common" */ const char *knet_log_get_subsystem_name(uint8_t subsystem); /** * knet_log_get_subsystem_id * * @brief Get a logging system ID from its name * * @return * returns internal ID of the subsystem or KNET_SUB_COMMON */ uint8_t knet_log_get_subsystem_id(const char *name); /* * 4 log levels are enough for everybody */ #define KNET_LOG_ERR 0 /* unrecoverable errors/conditions */ #define KNET_LOG_WARN 1 /* recoverable errors/conditions */ #define KNET_LOG_INFO 2 /* info, link up/down, config changes.. */ #define KNET_LOG_DEBUG 3 /* * Convert between log level values and names */ /** * knet_log_get_loglevel_name * * @brief Get a logging level name from its numeric ID * * @return * returns internal name of the log level or "ERROR" for unknown values */ const char *knet_log_get_loglevel_name(uint8_t level); /** * knet_log_get_loglevel_id * * @brief Get a logging level ID from its name * * @return * returns internal log level ID or KNET_LOG_ERR for invalid names */ uint8_t knet_log_get_loglevel_id(const char *name); /* * every log message is composed by a text message (including a trailing \n) * and message level/subsystem IDs. * In order to make debugging easier it is possible to send those packets * straight to stdout/stderr (see knet_bench.c stdout option). */ #define KNET_MAX_LOG_MSG_SIZE 256 struct knet_log_msg { char msg[KNET_MAX_LOG_MSG_SIZE - (sizeof(uint8_t)*2)]; uint8_t subsystem; /* KNET_SUB_* */ uint8_t msglevel; /* KNET_LOG_* */ }; /** * knet_log_set_log_level * * @brief Set the logging level for a subsystem * * knet_h - same as above * * subsystem - same as above * * level - same as above * * knet_log_set_loglevel allows fine control of log levels by subsystem. * See also knet_handle_new for defaults. * * @return * knet_log_set_loglevel returns * 0 on success * -1 on error and errno is set. */ int knet_log_set_loglevel(knet_handle_t knet_h, uint8_t subsystem, uint8_t level); /** * knet_log_get_log_level * * @brief Get the logging level for a subsystem * * knet_h - same as above * * subsystem - same as above * * level - same as above * * @return * knet_log_get_loglevel returns * 0 on success * -1 on error and errno is set. */ int knet_log_get_loglevel(knet_handle_t knet_h, uint8_t subsystem, uint8_t *level); #endif diff --git a/libknet/logging.h b/libknet/logging.h index 6f9e8666..785198c9 100644 --- a/libknet/logging.h +++ b/libknet/logging.h @@ -1,30 +1,38 @@ /* * Copyright (C) 2012-2017 Red Hat, Inc. All rights reserved. * * Authors: Fabio M. Di Nitto * Federico Simoncelli * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #ifndef __KNET_LOGGING_H__ #define __KNET_LOGGING_H__ #include "internals.h" -void log_msg(knet_handle_t knet_h, uint8_t subsystem, uint8_t msglevel, - const char *fmt, ...) __attribute__((format(printf, 4, 5)));; +typedef void log_msg_t(knet_handle_t knet_h, uint8_t subsystem, uint8_t msglevel, + const char *fmt, ...) __attribute__((format(printf, 4, 5))); + +#ifdef KNET_MODULE +#define LOG_MSG (*log_msg) +#else +#define LOG_MSG log_msg +#endif + +log_msg_t LOG_MSG; #define log_err(knet_h, subsys, fmt, args...) \ - log_msg(knet_h, subsys, KNET_LOG_ERR, fmt, ##args) + LOG_MSG(knet_h, subsys, KNET_LOG_ERR, fmt, ##args) #define log_warn(knet_h, subsys, fmt, args...) \ - log_msg(knet_h, subsys, KNET_LOG_WARN, fmt, ##args) + LOG_MSG(knet_h, subsys, KNET_LOG_WARN, fmt, ##args) #define log_info(knet_h, subsys, fmt, args...) \ - log_msg(knet_h, subsys, KNET_LOG_INFO, fmt, ##args) + LOG_MSG(knet_h, subsys, KNET_LOG_INFO, fmt, ##args) #define log_debug(knet_h, subsys, fmt, args...) \ - log_msg(knet_h, subsys, KNET_LOG_DEBUG, fmt, ##args) + LOG_MSG(knet_h, subsys, KNET_LOG_DEBUG, fmt, ##args) #endif diff --git a/libknet/remap.h b/libknet/remap.h deleted file mode 100644 index 87c1e679..00000000 --- a/libknet/remap.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Repeated inclusions define this differently */ -#undef REMAP_PROTO - -#ifdef CANARY - -/* Canary uses fake prototype to make "calls" uniform */ -#ifdef CANARY_CALL -#define REMAP_PROTO(ret,name,args) name() + -#else -#define REMAP_PROTO(ret,name,args) char name(void); -#endif /* CANARY_CALL */ - -#else - -#ifdef REMAP_FAIL -#define REMAP_PROTO(ret,name,args) _int_ ## name = NULL; -#else -#ifdef REMAP_WITH -#define REMAP_PROTO(ret,name,args) if (!(_int_ ## name = REMAP_WITH(#name))) goto fail; -#else -/* Provide the plain prototype as well for validation */ -#define REMAP_PROTO(ret,name,args) ret (*_int_ ## name)args; \ - ret name args; -#endif /* REMAP_WITH */ -#endif /* REMAP_FAIL */ - -#endif /* CANARY */ diff --git a/libknet/tests/Makefile.am b/libknet/tests/Makefile.am index 85fed2cf..dc00351a 100644 --- a/libknet/tests/Makefile.am +++ b/libknet/tests/Makefile.am @@ -1,91 +1,69 @@ # # Copyright (C) 2016-2017 Red Hat, Inc. All rights reserved. # # Authors: Fabio M. Di Nitto # # This software licensed under GPL-2.0+, LGPL-2.0+ # MAINTAINERCLEANFILES = Makefile.in include $(top_srcdir)/build-aux/check.mk include $(top_srcdir)/libknet/tests/api-check.mk EXTRA_DIST = \ api-test-coverage \ api-check.mk AM_CPPFLAGS = -I$(top_srcdir)/libknet AM_CFLAGS = $(PTHREAD_CFLAGS) LIBS = $(top_builddir)/libknet/libknet.la \ $(PTHREAD_LIBS) $(dl_LIBS) noinst_HEADERS = \ test-common.h # the order of those tests is NOT random. # some functions can only be tested properly after some dependents # API have been validated upfront. check_PROGRAMS = \ $(api_checks) \ $(int_checks) \ $(fun_checks) int_checks = \ - int_crypto_test \ int_timediff_test fun_checks = benchmarks = \ - crypto_bench_test \ knet_bench_test noinst_PROGRAMS = \ api_knet_handle_new_limit_test \ pckt_test \ $(benchmarks) \ $(check_PROGRAMS) noinst_SCRIPTS = \ api-test-coverage TESTS = $(check_PROGRAMS) check-local: check-api-test-coverage check-api-test-coverage: chmod u+x $(top_srcdir)/libknet/tests/api-test-coverage $(top_srcdir)/libknet/tests/api-test-coverage $(top_srcdir) $(top_builddir) pckt_test_SOURCES = pckt_test.c -int_crypto_test_SOURCES = int_crypto.c \ - ../common.c \ - ../crypto.c \ - ../crypto_nss.c \ - ../crypto_openssl.c \ - ../logging.c \ - test-common.c - -int_crypto_test_CFLAGS = $(nss_CFLAGS) $(openssl_CFLAGS) - int_timediff_test_SOURCES = int_timediff.c -crypto_bench_test_SOURCES = crypto_bench.c \ - ../common.c \ - ../crypto.c \ - ../crypto_nss.c \ - ../crypto_openssl.c \ - ../logging.c \ - test-common.c - -crypto_bench_test_CFLAGS = $(nss_CFLAGS) $(openssl_CFLAGS) - knet_bench_test_SOURCES = knet_bench.c \ test-common.c \ ../common.c \ ../logging.c \ ../compat.c \ ../transport_common.c diff --git a/libknet/tests/api_knet_handle_compress.c b/libknet/tests/api_knet_handle_compress.c index 628f683c..704e2e79 100644 --- a/libknet/tests/api_knet_handle_compress.c +++ b/libknet/tests/api_knet_handle_compress.c @@ -1,173 +1,188 @@ /* * Copyright (C) 2017 Red Hat, Inc. All rights reserved. * * Authors: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include #include #include #include #include "libknet.h" #include "internals.h" #include "test-common.h" static void test(void) { knet_handle_t knet_h; int logfds[2]; struct knet_handle_compress_cfg knet_handle_compress_cfg; memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg)); printf("Test knet_handle_compress incorrect knet_h\n"); if ((!knet_handle_compress(NULL, &knet_handle_compress_cfg)) || (errno != EINVAL)) { printf("knet_handle_compress accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno)); exit(FAIL); } setup_logpipes(logfds); knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG); if (!knet_h) { printf("knet_handle_new failed: %s\n", strerror(errno)); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); printf("Test knet_handle_compress with invalid cfg\n"); if ((!knet_handle_compress(knet_h, NULL)) || (errno != EINVAL)) { printf("knet_handle_compress accepted invalid cfg or returned incorrect error: %s\n", strerror(errno)); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); printf("Test knet_handle_compress with un-initialized cfg\n"); memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg)); if ((!knet_handle_compress(knet_h, &knet_handle_compress_cfg)) || (errno != EINVAL)) { printf("knet_handle_compress accepted invalid un-initialized cfg\n"); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); printf("Test knet_handle_compress with none compress model (disable compress)\n"); memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg)); strncpy(knet_handle_compress_cfg.compress_model, "none", sizeof(knet_handle_compress_cfg.compress_model) - 1); if (knet_handle_compress(knet_h, &knet_handle_compress_cfg) != 0) { printf("knet_handle_compress did not accept none compress mode cfg\n"); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); -#ifdef BUILDCOMPZLIB printf("Test knet_handle_compress with zlib compress and negative level\n"); memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg)); strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1); knet_handle_compress_cfg.compress_level = -1; if ((!knet_handle_compress(knet_h, &knet_handle_compress_cfg)) || (errno != EINVAL)) { printf("knet_handle_compress accepted invalid (-1) compress level for zlib\n"); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); printf("Test knet_handle_compress with zlib compress and excessive compress level\n"); memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg)); strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1); knet_handle_compress_cfg.compress_level = 10; if ((!knet_handle_compress(knet_h, &knet_handle_compress_cfg)) || (errno != EINVAL)) { printf("knet_handle_compress accepted invalid (10) compress level for zlib\n"); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); printf("Test knet_handle_compress with zlib compress and excessive compress threshold\n"); memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg)); strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1); knet_handle_compress_cfg.compress_level = 1; knet_handle_compress_cfg.compress_threshold = KNET_MAX_PACKET_SIZE +1; if ((!knet_handle_compress(knet_h, &knet_handle_compress_cfg)) || (errno != EINVAL)) { printf("knet_handle_compress accepted invalid compress threshold\n"); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); printf("Test knet_handle_compress with zlib compress model normal compress level and threshold\n"); memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg)); strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1); knet_handle_compress_cfg.compress_level = 1; knet_handle_compress_cfg.compress_threshold = 64; if (knet_handle_compress(knet_h, &knet_handle_compress_cfg) != 0) { printf("knet_handle_compress did not accept zlib compress mode with compress level 1 cfg\n"); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } -#endif flush_logs(logfds[0], stdout); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); } int main(int argc, char *argv[]) { - test(); + struct knet_compress_info compress_list[16]; + size_t compress_list_entries; + size_t i; + + memset(compress_list, 0, sizeof(compress_list)); + + if (knet_get_compress_list(compress_list, &compress_list_entries) < 0) { + printf("knet_get_compress_list failed: %s\n", strerror(errno)); + return FAIL; + } + + if (compress_list_entries == 0) { + printf("no compression modules detected. Skipping\n"); + return SKIP; + } + + for (i=0; i < compress_list_entries; i++) { + if (!strcmp(compress_list[i].name, "zlib")) { + test(); + return PASS; + } + } -#ifdef BUILDCOMPZLIB - return PASS; -#else printf("WARNING: zlib support not builtin the library. Unable to test/verify internal compress API calls\n"); return SKIP; -#endif } diff --git a/libknet/tests/api_knet_handle_crypto.c b/libknet/tests/api_knet_handle_crypto.c index 81ceb874..5336502e 100644 --- a/libknet/tests/api_knet_handle_crypto.c +++ b/libknet/tests/api_knet_handle_crypto.c @@ -1,270 +1,226 @@ /* * Copyright (C) 2016-2017 Red Hat, Inc. All rights reserved. * * Authors: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include #include #include #include #include "libknet.h" #include "internals.h" #include "test-common.h" -static void test(void) +static void test(const char *model) { knet_handle_t knet_h; int logfds[2]; struct knet_handle_crypto_cfg knet_handle_crypto_cfg; memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); printf("Test knet_handle_crypto incorrect knet_h\n"); if ((!knet_handle_crypto(NULL, &knet_handle_crypto_cfg)) || (errno != EINVAL)) { printf("knet_handle_crypto accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno)); exit(FAIL); } setup_logpipes(logfds); knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG); if (!knet_h) { printf("knet_handle_new failed: %s\n", strerror(errno)); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); printf("Test knet_handle_crypto with invalid cfg\n"); if ((!knet_handle_crypto(knet_h, NULL)) || (errno != EINVAL)) { printf("knet_handle_crypto accepted invalid cfg or returned incorrect error: %s\n", strerror(errno)); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); printf("Test knet_handle_crypto with un-initialized cfg\n"); if ((!knet_handle_crypto(knet_h, &knet_handle_crypto_cfg)) || (errno != EINVAL)) { printf("knet_handle_crypto accepted invalid un-initialized cfg\n"); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); printf("Test knet_handle_crypto with none crypto model (disable crypto)\n"); memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); strncpy(knet_handle_crypto_cfg.crypto_model, "none", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); if (knet_handle_crypto(knet_h, &knet_handle_crypto_cfg) != 0) { printf("knet_handle_crypto did not accept none crypto mode cfg\n"); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); printf("Test knet_handle_crypto with none crypto cipher and hash (disable crypto)\n"); memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); + strncpy(knet_handle_crypto_cfg.crypto_model, model, sizeof(knet_handle_crypto_cfg.crypto_model) - 1); strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "none", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); if (knet_handle_crypto(knet_h, &knet_handle_crypto_cfg) != 0) { printf("knet_handle_crypto did not accept none crypto cipher and hash cfg\n"); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); - printf("Test knet_handle_crypto with nss/aes128/sha1 and too short key\n"); + printf("Test knet_handle_crypto with %s/aes128/sha1 and too short key\n", model); memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); + strncpy(knet_handle_crypto_cfg.crypto_model, model, sizeof(knet_handle_crypto_cfg.crypto_model) - 1); strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); knet_handle_crypto_cfg.private_key_len = 10; if ((!knet_handle_crypto(knet_h, &knet_handle_crypto_cfg)) || (errno != EINVAL)) { printf("knet_handle_crypto accepted too short private key\n"); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); - printf("Test knet_handle_crypto with nss/aes128/sha1 and too long key\n"); + printf("Test knet_handle_crypto with %s/aes128/sha1 and too long key\n", model); memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); + strncpy(knet_handle_crypto_cfg.crypto_model, model, sizeof(knet_handle_crypto_cfg.crypto_model) - 1); strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); knet_handle_crypto_cfg.private_key_len = 10000; if ((!knet_handle_crypto(knet_h, &knet_handle_crypto_cfg)) || (errno != EINVAL)) { printf("knet_handle_crypto accepted too long private key\n"); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); -#ifdef BUILDCRYPTONSS - printf("Test knet_handle_crypto with nss/aes128/sha1 and normal key\n"); + printf("Test knet_handle_crypto with %s/aes128/sha1 and normal key\n", model); memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); + strncpy(knet_handle_crypto_cfg.crypto_model, model, sizeof(knet_handle_crypto_cfg.crypto_model) - 1); strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); knet_handle_crypto_cfg.private_key_len = 2000; if (knet_handle_crypto(knet_h, &knet_handle_crypto_cfg)) { printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); - printf("Test knet_handle_crypto (nss specific test) with nss/aes128/none and normal key\n"); + printf("Test knet_handle_crypto with %s/aes128/none and normal key\n", model); memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); + strncpy(knet_handle_crypto_cfg.crypto_model, model, sizeof(knet_handle_crypto_cfg.crypto_model) - 1); strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); knet_handle_crypto_cfg.private_key_len = 2000; if (!knet_handle_crypto(knet_h, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto (nss) accepted crypto without hashing\n"); + printf("knet_handle_crypto accepted crypto without hashing\n"); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); printf("Shutdown crypto\n"); memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); strncpy(knet_handle_crypto_cfg.crypto_model, "none", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "none", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); knet_handle_crypto_cfg.private_key_len = 2000; if (knet_handle_crypto(knet_h, &knet_handle_crypto_cfg) < 0) { printf("Unable to shutdown crypto: %s\n", strerror(errno)); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); -#endif - -#ifdef BUILDCRYPTOOPENSSL - printf("Test knet_handle_crypto with openssl/aes128/sha1 and normal key\n"); - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "openssl", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; - - if (knet_handle_crypto(knet_h, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } + knet_handle_free(knet_h); flush_logs(logfds[0], stdout); + close_logpipes(logfds); +} - printf("Test knet_handle_crypto (nss specific test) with openssl/aes128/none and normal key\n"); +int main(int argc, char *argv[]) +{ + struct knet_crypto_info crypto_list[16]; + size_t crypto_list_entries; + size_t i; - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "openssl", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; + memset(crypto_list, 0, sizeof(crypto_list)); - if (!knet_handle_crypto(knet_h, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto (nss) accepted crypto without hashing\n"); - knet_handle_free(knet_h); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); + if (knet_get_crypto_list(crypto_list, &crypto_list_entries) < 0) { + printf("knet_get_crypto_list failed: %s\n", strerror(errno)); + return FAIL; } - flush_logs(logfds[0], stdout); - - printf("Shutdown crypto\n"); - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "none", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "none", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; - - if (knet_handle_crypto(knet_h, &knet_handle_crypto_cfg) < 0) { - printf("Unable to shutdown crypto: %s\n", strerror(errno)); - knet_handle_free(knet_h); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); + if (crypto_list_entries == 0) { + printf("no crypto modules detected. Skipping\n"); + return SKIP; } - flush_logs(logfds[0], stdout); -#endif - knet_handle_free(knet_h); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); -} - -int main(int argc, char *argv[]) -{ - test(); + for (i=0; i < crypto_list_entries; i++) { + test(crypto_list[i].name); + } -#if defined(BUILDCRYPTONSS) || defined(BUILDCRYPTOOPENSSL) return PASS; -#else - printf("WARNING: nss support not builtin the library. Unable to test/verify internal crypto API calls\n"); - return SKIP; -#endif } diff --git a/libknet/tests/api_knet_send_compress.c b/libknet/tests/api_knet_send_compress.c index 1386768f..80c4c5a8 100644 --- a/libknet/tests/api_knet_send_compress.c +++ b/libknet/tests/api_knet_send_compress.c @@ -1,290 +1,293 @@ /* * Copyright (C) 2016-2017 Red Hat, Inc. All rights reserved. * * Authors: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include #include #include #include #include #include "libknet.h" #include "compress.h" #include "internals.h" #include "netutils.h" #include "test-common.h" static int private_data; static void sock_notify(void *pvt_data, int datafd, int8_t channel, uint8_t tx_rx, int error, int errorno) { return; } static void test(const char *model) { knet_handle_t knet_h; int logfds[2]; int datafd = 0; int8_t channel = 0; struct knet_handle_stats stats; char send_buff[KNET_MAX_PACKET_SIZE]; char recv_buff[KNET_MAX_PACKET_SIZE]; ssize_t send_len = 0; int recv_len = 0; int savederrno; struct sockaddr_storage lo; struct knet_handle_compress_cfg knet_handle_compress_cfg; if (make_local_sockaddr(&lo, 0) < 0) { printf("Unable to convert loopback to sockaddr: %s\n", strerror(errno)); exit(FAIL); } memset(send_buff, 0, sizeof(send_buff)); setup_logpipes(logfds); knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG); if (!knet_h) { printf("knet_handle_new failed: %s\n", strerror(errno)); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); printf("Test knet_send with %s and valid data\n", model); memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg)); strncpy(knet_handle_compress_cfg.compress_model, model, sizeof(knet_handle_compress_cfg.compress_model) - 1); knet_handle_compress_cfg.compress_level = 4; knet_handle_compress_cfg.compress_threshold = 0; if (knet_handle_compress(knet_h, &knet_handle_compress_cfg) < 0) { printf("knet_handle_compress did not accept zlib compress mode with compress level 1 cfg\n"); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } if (knet_handle_enable_sock_notify(knet_h, &private_data, sock_notify) < 0) { printf("knet_handle_enable_sock_notify failed: %s\n", strerror(errno)); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } datafd = 0; channel = -1; if (knet_handle_add_datafd(knet_h, &datafd, &channel) < 0) { printf("knet_handle_add_datafd failed: %s\n", strerror(errno)); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } if (knet_host_add(knet_h, 1) < 0) { printf("knet_host_add failed: %s\n", strerror(errno)); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } if (knet_link_set_config(knet_h, 1, 0, KNET_TRANSPORT_UDP, &lo, &lo, 0) < 0) { printf("Unable to configure link: %s\n", strerror(errno)); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } if (knet_link_set_enable(knet_h, 1, 0, 1) < 0) { printf("knet_link_set_enable failed: %s\n", strerror(errno)); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } if (knet_handle_setfwd(knet_h, 1) < 0) { printf("knet_handle_setfwd failed: %s\n", strerror(errno)); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } if (wait_for_host(knet_h, 1, 10, logfds[0], stdout) < 0) { printf("timeout waiting for host to be reachable"); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } send_len = knet_send(knet_h, send_buff, KNET_MAX_PACKET_SIZE, channel); if (send_len <= 0) { printf("knet_send failed: %s\n", strerror(errno)); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } if (send_len != sizeof(send_buff)) { printf("knet_send sent only %zd bytes: %s\n", send_len, strerror(errno)); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); if (wait_for_packet(knet_h, 10, datafd)) { printf("Error waiting for packet: %s\n", strerror(errno)); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } recv_len = knet_recv(knet_h, recv_buff, KNET_MAX_PACKET_SIZE, channel); savederrno = errno; if (recv_len != send_len) { printf("knet_recv received only %d bytes: %s (errno: %d)\n", recv_len, strerror(errno), errno); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); if ((is_helgrind()) && (recv_len == -1) && (savederrno == EAGAIN)) { printf("helgrind exception. this is normal due to possible timeouts\n"); exit(PASS); } exit(FAIL); } if (memcmp(recv_buff, send_buff, KNET_MAX_PACKET_SIZE)) { printf("recv and send buffers are different!\n"); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } /* A sanity check on the stats */ if (knet_handle_get_stats(knet_h, &stats, sizeof(stats)) < 0) { printf("knet_handle_get_stats failed: %s\n", strerror(errno)); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } if (strcmp(model, "none") == 0) { if (stats.tx_compressed_packets != 0 || stats.rx_compressed_packets != 0) { printf("stats look wrong: s/b all 0 for model 'none' tx_packets: %" PRIu64 " (%" PRIu64 "/%" PRIu64 " comp/uncomp), rx_packets: %" PRIu64 " (%" PRIu64 "/%" PRIu64 " comp/uncomp)\n", stats.tx_compressed_packets, stats.tx_compressed_size_bytes, stats.tx_compressed_original_bytes, stats.rx_compressed_packets, stats.rx_compressed_size_bytes, stats.rx_compressed_original_bytes); } } else { if (stats.tx_compressed_packets != 1 || stats.rx_compressed_packets != 1 || stats.tx_compressed_original_bytes < stats.tx_compressed_size_bytes || stats.tx_compressed_original_bytes < stats.tx_compressed_size_bytes) { printf("stats look wrong: tx_packets: %" PRIu64 " (%" PRIu64 "/%" PRIu64 " comp/uncomp), rx_packets: %" PRIu64 " (%" PRIu64 "/%" PRIu64 " comp/uncomp)\n", stats.tx_compressed_packets, stats.tx_compressed_size_bytes, stats.tx_compressed_original_bytes, stats.rx_compressed_packets, stats.rx_compressed_size_bytes, stats.rx_compressed_original_bytes); } } flush_logs(logfds[0], stdout); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); } int main(int argc, char *argv[]) { + struct knet_compress_info compress_list[16]; + size_t compress_list_entries; + size_t i; + + memset(compress_list, 0, sizeof(compress_list)); + + if (knet_get_compress_list(compress_list, &compress_list_entries) < 0) { + printf("knet_get_compress_list failed: %s\n", strerror(errno)); + return FAIL; + } + + if (compress_list_entries == 0) { + printf("no compression modules detected. Skipping\n"); + return SKIP; + } + test("none"); -#ifdef BUILDCOMPZLIB - test("zlib"); -#endif -#ifdef BUILDCOMPLZ4 - test("lz4"); - test("lz4hc"); -#endif -#ifdef BUILDCOMPLZO2 - test("lzo2"); -#endif -#ifdef BUILDCOMPLZMA - test("lzma"); -#endif -#ifdef BUILDCOMPBZIP2 - test("bzip2"); -#endif + for (i=0; i < compress_list_entries; i++) { + test(compress_list[i].name); + } return PASS; } diff --git a/libknet/tests/api_knet_send_crypto.c b/libknet/tests/api_knet_send_crypto.c index 3061ce67..44361774 100644 --- a/libknet/tests/api_knet_send_crypto.c +++ b/libknet/tests/api_knet_send_crypto.c @@ -1,265 +1,279 @@ /* * Copyright (C) 2016-2017 Red Hat, Inc. All rights reserved. * * Authors: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include #include #include #include #include #include "libknet.h" #include "compress.h" #include "internals.h" #include "netutils.h" #include "test-common.h" static int private_data; static void sock_notify(void *pvt_data, int datafd, int8_t channel, uint8_t tx_rx, int error, int errorno) { return; } static void test(const char *model) { knet_handle_t knet_h; int logfds[2]; int datafd = 0; int8_t channel = 0; struct knet_handle_stats stats; char send_buff[KNET_MAX_PACKET_SIZE]; char recv_buff[KNET_MAX_PACKET_SIZE]; ssize_t send_len = 0; int recv_len = 0; int savederrno; struct sockaddr_storage lo; struct knet_handle_crypto_cfg knet_handle_crypto_cfg; if (make_local_sockaddr(&lo, 0) < 0) { printf("Unable to convert loopback to sockaddr: %s\n", strerror(errno)); exit(FAIL); } memset(send_buff, 0, sizeof(send_buff)); setup_logpipes(logfds); knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG); if (!knet_h) { printf("knet_handle_new failed: %s\n", strerror(errno)); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); printf("Test knet_send with %s and valid data\n", model); memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); strncpy(knet_handle_crypto_cfg.crypto_model, model, sizeof(knet_handle_crypto_cfg.crypto_model) - 1); strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); knet_handle_crypto_cfg.private_key_len = 2000; if (knet_handle_crypto(knet_h, &knet_handle_crypto_cfg)) { printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } if (knet_handle_enable_sock_notify(knet_h, &private_data, sock_notify) < 0) { printf("knet_handle_enable_sock_notify failed: %s\n", strerror(errno)); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } datafd = 0; channel = -1; if (knet_handle_add_datafd(knet_h, &datafd, &channel) < 0) { printf("knet_handle_add_datafd failed: %s\n", strerror(errno)); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } if (knet_host_add(knet_h, 1) < 0) { printf("knet_host_add failed: %s\n", strerror(errno)); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } if (knet_link_set_config(knet_h, 1, 0, KNET_TRANSPORT_UDP, &lo, &lo, 0) < 0) { printf("Unable to configure link: %s\n", strerror(errno)); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } if (knet_link_set_enable(knet_h, 1, 0, 1) < 0) { printf("knet_link_set_enable failed: %s\n", strerror(errno)); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } if (knet_handle_setfwd(knet_h, 1) < 0) { printf("knet_handle_setfwd failed: %s\n", strerror(errno)); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } if (wait_for_host(knet_h, 1, 10, logfds[0], stdout) < 0) { printf("timeout waiting for host to be reachable"); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } send_len = knet_send(knet_h, send_buff, KNET_MAX_PACKET_SIZE, channel); if (send_len <= 0) { printf("knet_send failed: %s\n", strerror(errno)); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } if (send_len != sizeof(send_buff)) { printf("knet_send sent only %zd bytes: %s\n", send_len, strerror(errno)); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } flush_logs(logfds[0], stdout); if (wait_for_packet(knet_h, 10, datafd)) { printf("Error waiting for packet: %s\n", strerror(errno)); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } recv_len = knet_recv(knet_h, recv_buff, KNET_MAX_PACKET_SIZE, channel); savederrno = errno; if (recv_len != send_len) { printf("knet_recv received only %d bytes: %s (errno: %d)\n", recv_len, strerror(errno), errno); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); if ((is_helgrind()) && (recv_len == -1) && (savederrno == EAGAIN)) { printf("helgrind exception. this is normal due to possible timeouts\n"); exit(PASS); } exit(FAIL); } if (memcmp(recv_buff, send_buff, KNET_MAX_PACKET_SIZE)) { printf("recv and send buffers are different!\n"); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } /* A sanity check on the stats */ if (knet_handle_get_stats(knet_h, &stats, sizeof(stats)) < 0) { printf("knet_handle_get_stats failed: %s\n", strerror(errno)); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); exit(FAIL); } if (stats.tx_crypt_packets >= 1 || stats.rx_crypt_packets < 1) { printf("stats look wrong: tx_packets: %" PRIu64 ", rx_packets: %" PRIu64 "\n", stats.tx_crypt_packets, stats.rx_crypt_packets); } flush_logs(logfds[0], stdout); knet_link_set_enable(knet_h, 1, 0, 0); knet_link_clear_config(knet_h, 1, 0); knet_host_remove(knet_h, 1); knet_handle_free(knet_h); flush_logs(logfds[0], stdout); close_logpipes(logfds); } int main(int argc, char *argv[]) { -#ifdef BUILDCRYPTONSS - test("nss"); -#endif -#ifdef BUILDCRYPTOOPENSSL + struct knet_crypto_info crypto_list[16]; + size_t crypto_list_entries; + size_t i; + #ifdef KNET_BSD if (is_memcheck() || is_helgrind()) { printf("valgrind-freebsd cannot run this test properly. Skipping\n"); - return PASS; + return SKIP; } #endif - test("openssl"); -#endif + + memset(crypto_list, 0, sizeof(crypto_list)); + + if (knet_get_crypto_list(crypto_list, &crypto_list_entries) < 0) { + printf("knet_get_crypto_list failed: %s\n", strerror(errno)); + return FAIL; + } + + if (crypto_list_entries == 0) { + printf("no crypto modules detected. Skipping\n"); + return SKIP; + } + + for (i=0; i < crypto_list_entries; i++) { + test(crypto_list[i].name); + } return PASS; } diff --git a/libknet/tests/crypto_bench.c b/libknet/tests/crypto_bench.c deleted file mode 100644 index cf00403d..00000000 --- a/libknet/tests/crypto_bench.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright (C) 2016-2017 Red Hat, Inc. All rights reserved. - * - * Authors: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+, LGPL-2.0+ - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "libknet.h" - -#include "common.h" -#include "internals.h" -#include "crypto.h" -#include "threads_common.h" - -#include "test-common.h" - -pthread_rwlock_t shlib_rwlock; - -static void test(void) -{ - knet_handle_t knet_h; - int logfd; - struct knet_handle_crypto_cfg knet_handle_crypto_cfg; - struct knet_handle_stats knet_stats; - char *buf1, *buf2, *buf3; - const char *input = "Encrypt me!\x0"; - ssize_t input_len = strlen(input) + 1; - ssize_t outbuf_len; - int loops; - struct timespec clock_start, clock_end; - unsigned long long time_diff; - struct iovec iov_in; - struct iovec iov_multi[4]; - int err = 0; - - err = pthread_rwlock_init(&shlib_rwlock, NULL); - if (err) { - printf("unable to init lock: %s\n", strerror(err)); - exit(FAIL); - } - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - - logfd = start_logging(stdout); - - knet_h = knet_handle_new(1, logfd, KNET_LOG_DEBUG); - - if (!knet_h) { - printf("knet_handle_new failed: %s\n", strerror(errno)); - exit(FAIL); - } - - printf("Test knet_handle_crypto with nss/aes128/sha1 and normal key\n"); - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; - - if (crypto_init(knet_h, &knet_handle_crypto_cfg) < 0) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h); - exit(FAIL); - } - - buf1=malloc(input_len); - buf2=malloc(input_len + knet_h->sec_header_size); - buf3=malloc(input_len + knet_h->sec_header_size); - - memset(buf1, 0, input_len); - memset(buf2, 0, input_len + knet_h->sec_header_size); - memset(buf3, 0, input_len + knet_h->sec_header_size); - - /* - * setup source buffer - */ - - if (clock_gettime(CLOCK_MONOTONIC, &clock_start) != 0) { - printf("Unable to get start time!\n"); - knet_handle_free(knet_h); - exit(FAIL); - } - - for (loops=0; loops<1000000; loops++) { - memset(buf1, 0, input_len); - memset(buf2, 0, input_len + knet_h->sec_header_size); - memset(buf3, 0, input_len + knet_h->sec_header_size); - - strncpy(buf1, input, input_len); - - if (crypto_encrypt_and_sign(knet_h, (unsigned char *)buf1, strlen(buf1)+1, (unsigned char *)buf2, &outbuf_len) < 0) { - printf("Unable to crypt and sign!\n"); - knet_handle_free(knet_h); - exit(FAIL); - } - - if (crypto_authenticate_and_decrypt(knet_h, (unsigned char *)buf2, outbuf_len, (unsigned char *)buf3, &outbuf_len) < 0) { - printf("Unable to auth and decrypt!\n"); - knet_handle_free(knet_h); - exit(FAIL); - } - - - if (memcmp(buf1, buf3, outbuf_len)) { - printf("Crypt / Descrypt produced two different data set!\n"); - knet_handle_free(knet_h); - exit(FAIL); - } - } - - if (clock_gettime(CLOCK_MONOTONIC, &clock_end) != 0) { - printf("Unable to get end time!\n"); - knet_handle_free(knet_h); - exit(FAIL); - } - - timespec_diff(clock_start, clock_end, &time_diff); - - printf("Execution of 1000000 loops (buf_in api): %llu/ns\n", time_diff); - - if (clock_gettime(CLOCK_MONOTONIC, &clock_start) != 0) { - printf("Unable to get start time!\n"); - knet_handle_free(knet_h); - exit(FAIL); - } - - memset(buf1, 0, input_len); - strncpy(buf1, input, input_len); - - for (loops=0; loops<1000000; loops++) { - memset(buf2, 0, input_len + knet_h->sec_header_size); - memset(buf3, 0, input_len + knet_h->sec_header_size); - memset(&iov_in, 0, sizeof(iov_in)); - - iov_in.iov_base = (unsigned char *)buf1; - iov_in.iov_len = strlen(buf1)+1; - - if (crypto_encrypt_and_signv(knet_h, &iov_in, 1, (unsigned char *)buf2, &outbuf_len) < 0) { - printf("Unable to crypt and sign!\n"); - knet_handle_free(knet_h); - exit(FAIL); - } - - if (crypto_authenticate_and_decrypt(knet_h, (unsigned char *)buf2, outbuf_len, (unsigned char *)buf3, &outbuf_len) < 0) { - printf("Unable to auth and decrypt!\n"); - knet_handle_free(knet_h); - exit(FAIL); - } - - - if (memcmp(buf1, buf3, outbuf_len)) { - printf("Crypt / Descrypt produced two different data set!\n"); - knet_handle_free(knet_h); - exit(FAIL); - } - } - - if (clock_gettime(CLOCK_MONOTONIC, &clock_end) != 0) { - printf("Unable to get end time!\n"); - knet_handle_free(knet_h); - exit(FAIL); - } - - timespec_diff(clock_start, clock_end, &time_diff); - - printf("Execution of 1000000 loops (iov_in api): %llu/ns\n", time_diff); - - if (clock_gettime(CLOCK_MONOTONIC, &clock_start) != 0) { - printf("Unable to get start time!\n"); - knet_handle_free(knet_h); - exit(FAIL); - } - - memset(buf1, 0, input_len); - strncpy(buf1, input, input_len); - - for (loops=0; loops<1000000; loops++) { - memset(buf2, 0, input_len + knet_h->sec_header_size); - memset(buf3, 0, input_len + knet_h->sec_header_size); - memset(&iov_multi, 0, sizeof(iov_multi)); - - /* - * "Encrypt me!\n" = 12 bytes - */ - - iov_multi[0].iov_base = (unsigned char *)buf1; - iov_multi[0].iov_len = 3; - iov_multi[1].iov_base = (unsigned char *)buf1 + 3; - iov_multi[1].iov_len = 3; - iov_multi[2].iov_base = (unsigned char *)buf1 + 6; - iov_multi[2].iov_len = 3; - iov_multi[3].iov_base = (unsigned char *)buf1 + 9; - iov_multi[3].iov_len = 3; - - if (crypto_encrypt_and_signv(knet_h, iov_multi, 4, (unsigned char *)buf2, &outbuf_len) < 0) { - printf("Unable to crypt and sign!\n"); - knet_handle_free(knet_h); - exit(FAIL); - } - - if (crypto_authenticate_and_decrypt(knet_h, (unsigned char *)buf2, outbuf_len, (unsigned char *)buf3, &outbuf_len) < 0) { - printf("Unable to auth and decrypt!\n"); - knet_handle_free(knet_h); - exit(FAIL); - } - - - if (memcmp(buf1, buf3, outbuf_len)) { - printf("Crypt / Descrypt produced two different data set!\n"); - knet_handle_free(knet_h); - exit(FAIL); - } - } - - if (clock_gettime(CLOCK_MONOTONIC, &clock_end) != 0) { - printf("Unable to get end time!\n"); - knet_handle_free(knet_h); - exit(FAIL); - } - - timespec_diff(clock_start, clock_end, &time_diff); - - printf("Execution of 1000000 loops (iov_in multi api): %llu/ns\n", time_diff); - - knet_handle_get_stats(knet_h, &knet_stats, sizeof(knet_stats)); - - printf("Shutdown crypto\n"); - - crypto_fini(knet_h); - - knet_handle_free(knet_h); - free(buf1); - free(buf2); - free(buf3); - pthread_rwlock_destroy(&shlib_rwlock); -} - -int main(int argc, char *argv[]) -{ - printf("Testing with default scheduler\n"); - - set_scheduler(SCHED_OTHER); - - test(); - - printf("Testing with SCHED_RR scheduler\n"); - - set_scheduler(SCHED_RR); - - test(); - - printf("Testing with SCHED_FIFO scheduler\n"); - - set_scheduler(SCHED_FIFO); - - test(); - - return PASS; -} diff --git a/libknet/tests/int_crypto.c b/libknet/tests/int_crypto.c deleted file mode 100644 index 164c40da..00000000 --- a/libknet/tests/int_crypto.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2016-2017 Red Hat, Inc. All rights reserved. - * - * Authors: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+, LGPL-2.0+ - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#include "libknet.h" - -#include "common.h" -#include "internals.h" -#include "crypto.h" -#include "test-common.h" - -pthread_rwlock_t shlib_rwlock; - -static void test(void) -{ - knet_handle_t knet_h; - int logfds[2]; - struct knet_handle_crypto_cfg knet_handle_crypto_cfg; - char *buf1, *buf2, *buf3; - const char *input = "Encrypt me!\x0"; - ssize_t input_len = strlen(input) + 1; - ssize_t outbuf_len; - int i; - int err = 0; - - err = pthread_rwlock_init(&shlib_rwlock, NULL); - if (err) { - printf("unable to init lock: %s\n", strerror(err)); - exit(FAIL); - } - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - - setup_logpipes(logfds); - - knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG); - - if (!knet_h) { - printf("knet_handle_new failed: %s\n", strerror(errno)); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - flush_logs(logfds[0], stdout); - - printf("Test knet_handle_crypto with nss/aes128/sha1 and normal key\n"); - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; - - if (crypto_init(knet_h, &knet_handle_crypto_cfg) < 0) { - printf("crypto_init failed: %s\n", strerror(errno)); - knet_handle_free(knet_h); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - flush_logs(logfds[0], stdout); - - buf1=malloc(input_len); - buf2=malloc(input_len + knet_h->sec_header_size); - buf3=malloc(input_len + knet_h->sec_header_size); - - memset(buf1, 0, input_len); - memset(buf2, 0, input_len + knet_h->sec_header_size); - memset(buf3, 0, input_len + knet_h->sec_header_size); - - /* - * setup source buffer - */ - - strncpy(buf1, input, input_len); - printf("Source Data: %s\n", buf1); - - if (crypto_encrypt_and_sign(knet_h, (unsigned char *)buf1, strlen(buf1)+1, (unsigned char *)buf2, &outbuf_len) < 0) { - printf("Unable to crypt and sign!\n"); - knet_handle_free(knet_h); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - printf("Encrypted Data: "); - for (i=0; i