diff --git a/Makefile.am b/Makefile.am index cf1366e1..ff85e55b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,214 +1,209 @@ # # Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. # # Author: Fabio M. Di Nitto # # This software licensed under GPL-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 = autogen.sh .version \ NOTES_TO_PACKAGE_MAINTAINERS \ $(SPEC).in build-aux -SUBDIRS = init libnozzle libknet kronosnetd +SUBDIRS = libnozzle libknet if BUILD_MAN SUBDIRS += man endif if BUILD_POC SUBDIRS += poc-code endif dist_doc_DATA = \ COPYING.applications \ COPYING.libraries \ COPYRIGHT \ README.licence \ README all-local: $(SPEC) clean-local: rm -rf $(SPEC) cov* 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 $(UTC_DATE_AT)$(SOURCE_EPOCH) "+%a %b %d %Y"`" && \ gvgver="`cd $(abs_srcdir); build-aux/git-version-gen --fallback $(VERSION) .tarball-version .gitarchivever`" && \ if [ "$$gvgver" = "`echo $$gvgver | sed 's/-/./'`" ];then \ rpmver="$$gvgver" && \ alphatag="" && \ dirty="" && \ numcomm="0"; \ else \ gitver="`echo $$gvgver | sed 's/\(.*\)\./\1-/'`" && \ rpmver=`echo $$gitver | sed 's/-.*//g'` && \ alphatag=`echo $$gvgver | sed 's/[^-]*-\([^-]*\).*/\1/'` && \ numcomm=`echo $$gitver | sed 's/[^-]*-\([^-]*\).*/\1/'` && \ dirty="" && \ if [ "`echo $$gitver | sed 's/^.*-dirty$$//g'`" = "" ];then \ dirty="dirty"; \ fi \ 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 BUILD_SCTP sed -i -e "s#@sctp@#bcond_without#g" $@-t else sed -i -e "s#@sctp@#bcond_with#g" $@-t endif 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 BUILD_CRYPTO_OPENSSL sed -i -e "s#@openssl@#bcond_without#g" $@-t else sed -i -e "s#@openssl@#bcond_with#g" $@-t endif 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 BUILD_COMPRESS_LZ4 sed -i -e "s#@lz4@#bcond_without#g" $@-t else sed -i -e "s#@lz4@#bcond_with#g" $@-t endif 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 BUILD_COMPRESS_LZMA sed -i -e "s#@lzma@#bcond_without#g" $@-t else sed -i -e "s#@lzma@#bcond_with#g" $@-t endif 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_COMPRESS_ZSTD sed -i -e "s#@zstd@#bcond_without#g" $@-t else sed -i -e "s#@zstd@#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_LIBNOZZLE sed -i -e "s#@libnozzle@#bcond_without#g" $@-t else sed -i -e "s#@libnozzle@#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 if OVERRIDE_RPM_DEBUGINFO sed -i -e "s#@overriderpmdebuginfo@#bcond_without#g" $@-t else sed -i -e "s#@overriderpmdebuginfo@#bcond_with#g" $@-t endif if BUILD_RPM_DEBUGINFO sed -i -e "s#@rpmdebuginfo@#bcond_without#g" $@-t else sed -i -e "s#@rpmdebuginfo@#bcond_with#g" $@-t endif if BUILD_MAN sed -i -e "s#@buildman@#bcond_without#g" $@-t else sed -i -e "s#@buildman@#bcond_with#g" $@-t endif if INSTALL_TESTS sed -i -e "s#@installtests@#bcond_without#g" $@-t else sed -i -e "s#@installtests@#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 echo $(SOURCE_EPOCH) > $(distdir)/source_epoch gen_start_date = 2000-01-01 .PHONY: gen-ChangeLog gen-ChangeLog: if test -d $(abs_srcdir)/.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/NOTES_TO_PACKAGE_MAINTAINERS b/NOTES_TO_PACKAGE_MAINTAINERS index 5acff702..fd931f4b 100644 --- a/NOTES_TO_PACKAGE_MAINTAINERS +++ b/NOTES_TO_PACKAGE_MAINTAINERS @@ -1,34 +1,29 @@ To: distribution package maintainers Those are a few things about this project that you should know. I surely welcome patches to support both in a better way. -DO NOT ship kronosnetd. It's an experimental piece of super -crappy code. IF you decide to ship it anyway, you get to -be also the upstream maintainer :-) you have been warned. - -libnozzle is a simple commodity library used only by kronosnetd -and a future release of corosync. This is the first GA release -for libnozzle, please allow space for minor screw ups. +libnozzle is a simple commodity library currently used by +corosync, to manage tun/tap devices. libknet is the core of this project. It is considered stable and supported in the stable* branches and still under heavy development in master branch. Upstream does guarantee onwire and update compatibility between releases in the same major versions (aka 1.x will always be able to talk to 1.x+n). There is NO guarantee of onwire compatibility between major versions of knet (aka: 1.x might not be able to talk to 2.x). libknet has a lot of build dependencies due to its modular implementation. It does not, however, link with all those libraries but uses a dlopen model to save runtime resources and provide flexibility to users to install only the libraries they are planning to use. Make sure that you do build with all feature enabled (compatible with your distribution licencing/patent policy of course) and tune your packaging to Recommend/Suggest the external libraries. Thanks Your upstream maintainers diff --git a/configure.ac b/configure.ac index f311764b..f3d12d2d 100644 --- a/configure.ac +++ b/configure.ac @@ -1,533 +1,419 @@ # # Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. # # Authors: Fabio M. Di Nitto # Federico Simoncelli # # This software licensed under GPL-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 .gitarchivever]), [devel@lists.kronosnet.org]) # Don't let AC_PROC_CC (invoked by AC_USE_SYSTEM_EXTENSIONS) replace # undefined CFLAGS with -g -O2, overriding our special OPT_CFLAGS. : ${CFLAGS=""} AC_USE_SYSTEM_EXTENSIONS AM_INIT_AUTOMAKE([1.13 dist-bzip2 dist-xz color-tests -Wno-portability subdir-objects]) LT_PREREQ([2.2.6]) # --enable-new-dtags: Use RUNPATH instead of RPATH. # It is necessary to have this done before libtool does linker detection. # See also: https://github.com/kronosnet/kronosnet/issues/107 # --as-needed: Modern systems have builtin ceil() making -lm superfluous but # AC_SEARCH_LIBS can't detect this because it tests with a false prototype AX_CHECK_LINK_FLAG([-Wl,--enable-new-dtags], [AM_LDFLAGS=-Wl,--enable-new-dtags], [AC_MSG_ERROR(["Linker support for --enable-new-dtags is required"])]) AX_CHECK_LINK_FLAG([-Wl,--as-needed], [AM_LDFLAGS="$AM_LDFLAGS -Wl,--as-needed"]) AC_SUBST([AM_LDFLAGS]) saved_LDFLAGS="$LDFLAGS" LDFLAGS="$AM_LDFLAGS $LDFLAGS" LT_INIT LDFLAGS="$saved_LDFLAGS" AC_CONFIG_MACRO_DIR([m4]) -AC_CONFIG_SRCDIR([kronosnetd/main.c]) +AC_CONFIG_SRCDIR([libknet/handle.c]) AC_CONFIG_HEADERS([config.h]) AC_CANONICAL_HOST 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([VALGRIND_EXEC], [valgrind]) AM_CONDITIONAL([HAS_VALGRIND], [test x$VALGRIND_EXEC != "x"]) AC_CHECK_PROGS([COVBUILD_EXEC], [cov-build]) AM_CONDITIONAL([HAS_COVBUILD], [test x$COVBUILD_EXEC != "x"]) AC_CHECK_PROGS([COVANALYZE_EXEC], [cov-analyze]) AM_CONDITIONAL([HAS_COVANALYZE], [test x$COVANALYZE_EXEC != "x"]) AC_CHECK_PROGS([COVFORMATERRORS_EXEC], [cov-format-errors]) AM_CONDITIONAL([HAS_COVFORMATERRORS], [test x$COVFORMATERRORS_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([man], [AS_HELP_STRING([--disable-man],[disable man page creation])],, [ enable_man="yes" ]) AM_CONDITIONAL([BUILD_MAN], [test x$enable_man = xyes]) AC_ARG_ENABLE([libknet-sctp], [AS_HELP_STRING([--disable-libknet-sctp],[disable libknet SCTP support])],, [ enable_libknet_sctp="yes" ]) AM_CONDITIONAL([BUILD_SCTP], [test x$enable_libknet_sctp = xyes]) AC_ARG_ENABLE([crypto-all], [AS_HELP_STRING([--disable-crypto-all],[disable libknet all crypto modules support])],, [ enable_crypto_all="yes" ]) KNET_OPTION_DEFINES([nss],[crypto],[PKG_CHECK_MODULES([nss], [nss])]) KNET_OPTION_DEFINES([openssl],[crypto],[PKG_CHECK_MODULES([openssl],[libcrypto])]) AC_ARG_ENABLE([compress-all], [AS_HELP_STRING([--disable-compress-all],[disable libknet all compress modules support])],, [ enable_compress_all="yes" ]) KNET_OPTION_DEFINES([zstd],[compress],[PKG_CHECK_MODULES([libzstd], [libzstd])]) 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], [# work around broken pkg-config file in v2.10 AC_SUBST([lzo2_CFLAGS],[`echo $lzo2_CFLAGS | sed 's,/lzo *, ,'`])], [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([install-tests], [AS_HELP_STRING([--enable-install-tests],[install tests])],, [ enable_install_tests="no" ]) AM_CONDITIONAL([INSTALL_TESTS], [test x$enable_install_tests = xyes]) AC_ARG_ENABLE([poc], [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], - [AS_HELP_STRING([--enable-kronosnetd],[Kronosnetd support])],, - [ enable_kronosnetd="no" ]) -AM_CONDITIONAL([BUILD_KRONOSNETD], [test x$enable_kronosnetd = xyes]) - AC_ARG_ENABLE([runautogen], [AS_HELP_STRING([--enable-runautogen],[run autogen.sh])],, [ enable_runautogen="no" ]) AM_CONDITIONAL([BUILD_RUNAUTOGEN], [test x$enable_runautogen = xyes]) override_rpm_debuginfo_option="yes" AC_ARG_ENABLE([rpm-debuginfo], [AS_HELP_STRING([--enable-rpm-debuginfo],[build debuginfo packages])],, [ enable_rpm_debuginfo="no", override_rpm_debuginfo_option="no" ]) AM_CONDITIONAL([BUILD_RPM_DEBUGINFO], [test x$enable_rpm_debuginfo = xyes]) AM_CONDITIONAL([OVERRIDE_RPM_DEBUGINFO], [test x$override_rpm_debuginfo_option = xyes]) AC_ARG_ENABLE([libnozzle], [AS_HELP_STRING([--enable-libnozzle],[libnozzle support])],, [ enable_libnozzle="yes" ]) -if test "x$enable_kronosnetd" = xyes; then - enable_libnozzle=yes -fi AM_CONDITIONAL([BUILD_LIBNOZZLE], [test x$enable_libnozzle = xyes]) # Checks for libraries. AX_PTHREAD(,[AC_MSG_ERROR([POSIX threads support is required])]) saved_LIBS="$LIBS" LIBS= AC_SEARCH_LIBS([ceil], [m], , [AC_MSG_ERROR([ceil not found])]) AC_SUBST([m_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" # Check RTLD_DI_ORIGIN (not decalred by musl. glibc has it as an enum so cannot use ifdef) AC_CHECK_DECL([RTLD_DI_ORIGIN], [AC_DEFINE([HAVE_RTLD_DI_ORIGIN], 1, [define when RTLD_DI_ORIGIN is declared])], ,[[#include ]]) # 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]) ;; *) AC_MSG_ERROR([Unsupported OS? hmmmm]) ;; esac # Checks for header files. AC_CHECK_HEADERS([sys/epoll.h]) 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 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_PID_T AC_TYPE_SIZE_T AC_TYPE_SSIZE_T AC_TYPE_UINT8_T AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_INT8_T AC_TYPE_INT16_T AC_TYPE_INT32_T AC_TYPE_INT64_T PKG_CHECK_MODULES([libqb], [libqb]) if test "x$enable_man" = "xyes"; then AC_ARG_VAR([DOXYGEN], [override doxygen executable]) AC_CHECK_PROGS([DOXYGEN], [doxygen], [no]) if test "x$DOXYGEN" = xno; then AC_MSG_ERROR(["Doxygen command not found"]) fi AC_ARG_VAR([DOXYGEN2MAN], [override doxygen2man executable]) # required to detect doxygen2man when libqb is installed # in non standard paths saved_PKG_CONFIG="$PKG_CONFIG" saved_ac_cv_path_PKG_CONFIG="$ac_cv_path_PKG_CONFIG" unset PKG_CONFIG ac_cv_path_PKG_CONFIG AC_PATH_PROG([PKG_CONFIG], [pkg-config]) PKG_CHECK_MODULES([libqb_BUILD], [libqb]) PKG_CHECK_VAR([libqb_BUILD_PREFIX], [libqb], [prefix]) AC_PATH_PROG([DOXYGEN2MAN], [doxygen2man], [no], [$libqb_BUILD_PREFIX/bin$PATH_SEPARATOR$PATH]) PKG_CONFIG="$saved_PKG_CONFIG" ac_cv_path_PKG_CONFIG="$saved_ac_cv_path_PKG_CONFIG" if test "x$DOXYGEN2MAN" = "xno"; then AC_MSG_ERROR(["doxygen2man command not found"]) fi AC_SUBST([DOXYGEN2MAN]) fi # checks for libnozzle if test "x$enable_libnozzle" = xyes; then if `echo $host_os | grep -q linux`; then PKG_CHECK_MODULES([libnl], [libnl-3.0]) PKG_CHECK_MODULES([libnlroute], [libnl-route-3.0 >= 3.3], [], [PKG_CHECK_MODULES([libnlroute], [libnl-route-3.0 < 3.3], [AC_DEFINE_UNQUOTED([LIBNL3_WORKAROUND], [1], [Enable libnl < 3.3 build workaround])], [])]) fi 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])])]) - - 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], [AS_HELP_STRING([--enable-debug],[enable debug build])]) AC_ARG_WITH([sanitizers], [AS_HELP_STRING([--with-sanitizers=...,...], [enable SANitizer build, do *NOT* use for production. Only ASAN/UBSAN/TSAN are currently supported])], [ SANITIZERS="$withval" ], [ SANITIZERS="" ]) AC_ARG_WITH([testdir], [AS_HELP_STRING([--with-testdir=DIR],[path to /usr/lib../kronosnet/tests/ dir where to install the test suite])], [ TESTDIR="$withval" ], [ TESTDIR="$libdir/kronosnet/tests" ]) -AC_ARG_WITH([initdefaultdir], - [AS_HELP_STRING([--with-initdefaultdir=DIR],[path to /etc/sysconfig or /etc/default dir])], - [ INITDEFAULTDIR="$withval" ], - [ INITDEFAULTDIR="$sysconfdir/default" ]) - -AC_ARG_WITH([initddir], - [AS_HELP_STRING([--with-initddir=DIR],[path to init script directory])], - [ INITDDIR="$withval" ], - [ INITDDIR="$sysconfdir/init.d" ]) - -AC_ARG_WITH([systemddir], - [AS_HELP_STRING([--with-systemddir=DIR],[path to systemd unit files directory])], - [ SYSTEMDDIR="$withval" ], - [ SYSTEMDDIR="$systemddir" ]) - -AC_ARG_WITH([syslogfacility], - [AS_HELP_STRING([--with-syslogfacility=FACILITY],[default syslog facility])], - [ SYSLOGFACILITY="$withval" ], - [ SYSLOGFACILITY="LOG_DAEMON" ]) - -AC_ARG_WITH([sysloglevel], - [AS_HELP_STRING([--with-sysloglevel=LEVEL],[default syslog level])], - [ SYSLOGLEVEL="$withval" ], - [ SYSLOGLEVEL="LOG_INFO" ]) - -AC_ARG_WITH([defaultadmgroup], - [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 AC_SUBST([TESTDIR]) -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]) # 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 # --- ASAN/UBSAN/TSAN (see man gcc) --- # when using SANitizers, we need to pass the -fsanitize.. # to both CFLAGS and LDFLAGS. The CFLAGS/LDFLAGS must be # specified as first in the list or there will be runtime # issues (for example user has to LD_PRELOAD asan for it to work # properly). if test -n "${SANITIZERS}"; then SANITIZERS=$(echo $SANITIZERS | sed -e 's/,/ /g') for SANITIZER in $SANITIZERS; do case $SANITIZER in asan|ASAN) SANITIZERS_CFLAGS="$SANITIZERS_CFLAGS -fsanitize=address" SANITIZERS_LDFLAGS="$SANITIZERS_LDFLAGS -fsanitize=address -lasan" AC_CHECK_LIB([asan],[main],,AC_MSG_ERROR([Unable to find libasan])) ;; ubsan|UBSAN) SANITIZERS_CFLAGS="$SANITIZERS_CFLAGS -fsanitize=undefined" SANITIZERS_LDFLAGS="$SANITIZERS_LDFLAGS -fsanitize=undefined -lubsan" AC_CHECK_LIB([ubsan],[main],,AC_MSG_ERROR([Unable to find libubsan])) ;; tsan|TSAN) SANITIZERS_CFLAGS="$SANITIZERS_CFLAGS -fsanitize=thread" SANITIZERS_LDFLAGS="$SANITIZERS_LDFLAGS -fsanitize=thread -ltsan" AC_CHECK_LIB([tsan],[main],,AC_MSG_ERROR([Unable to find libtsan])) ;; esac done fi DEFAULT_CFLAGS="-Werror -Wall -Wextra" # manual overrides # generates too much noise for stub APIs UNWANTED_CFLAGS="-Wno-unused-parameter" AC_SUBST([AM_CFLAGS],["$SANITIZERS_CFLAGS $OPT_CFLAGS $GDB_FLAGS $DEFAULT_CFLAGS $UNWANTED_CFLAGS"]) LDFLAGS="$SANITIZERS_LDFLAGS $LDFLAGS" AX_PROG_DATE AS_IF([test "$ax_cv_prog_date_gnu_date:$ax_cv_prog_date_gnu_utc" = yes:yes], [UTC_DATE_AT="date -u -d@"], [AS_IF([test "x$ax_cv_prog_date_bsd_date" = xyes], [UTC_DATE_AT="date -u -r"], [AC_MSG_ERROR([date utility unable to convert epoch to UTC])])]) AC_SUBST([UTC_DATE_AT]) AC_ARG_VAR([SOURCE_EPOCH],[last modification date of the source]) AC_MSG_NOTICE([trying to determine source epoch]) AC_MSG_CHECKING([for source epoch in \$SOURCE_EPOCH]) AS_IF([test -n "$SOURCE_EPOCH"], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_CHECKING([for source epoch in source_epoch file]) AS_IF([test -e "$srcdir/source_epoch"], [read SOURCE_EPOCH <"$srcdir/source_epoch" AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_CHECKING([for source epoch baked in by gitattributes export-subst]) SOURCE_EPOCH='$Format:%at$' # template for rewriting by git-archive AS_CASE([$SOURCE_EPOCH], [?Format:*], # was not rewritten [AC_MSG_RESULT([no]) AC_MSG_CHECKING([for source epoch in \$SOURCE_DATE_EPOCH]) AS_IF([test "x$SOURCE_DATE_EPOCH" != x], [SOURCE_EPOCH="$SOURCE_DATE_EPOCH" AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_CHECKING([whether git log can provide a source epoch]) SOURCE_EPOCH=f${SOURCE_EPOCH#\$F} # convert into git log --pretty format SOURCE_EPOCH=$(cd "$srcdir" && git log -1 --pretty=${SOURCE_EPOCH%$} 2>/dev/null) AS_IF([test -n "$SOURCE_EPOCH"], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no, using current time and breaking reproducibility]) SOURCE_EPOCH=$(date +%s)])])], [AC_MSG_RESULT([yes])] )]) ]) AC_MSG_NOTICE([using source epoch $($UTC_DATE_AT$SOURCE_EPOCH +'%F %T %Z')]) AC_CONFIG_FILES([ Makefile - init/Makefile libnozzle/Makefile libnozzle/libnozzle.pc libnozzle/tests/Makefile - kronosnetd/Makefile - kronosnetd/kronosnetd.logrotate libknet/Makefile libknet/libknet.pc libknet/tests/Makefile man/Makefile man/Doxyfile-knet man/Doxyfile-nozzle poc-code/Makefile poc-code/iov-hash/Makefile ]) if test "x$VERSION" = "xUNKNOWN"; then AC_MSG_ERROR([m4_text_wrap([ configure was unable to determine the source tree's current version. This generally happens when using git archive (or the github download button) generated tarball/zip file. In order to workaround this issue, either use git clone https://github.com/kronosnet/kronosnet.git or use an official release tarball, available at https://kronosnet.org/releases/. Alternatively you can add a compatible version in a .tarball-version file at the top of the source tree, wipe your autom4te.cache dir and generated configure, and rerun autogen.sh. ], [ ], [ ], [76])]) fi AC_OUTPUT diff --git a/init/Makefile.am b/init/Makefile.am deleted file mode 100644 index 9a8dccac..00000000 --- a/init/Makefile.am +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. -# -# Author: Fabio M. Di Nitto -# -# This software licensed under GPL-2.0+ -# - -MAINTAINERCLEANFILES = Makefile.in - -include $(top_srcdir)/build-aux/check.mk - -EXTRA_DIST = kronosnetd.in kronosnetd.service.in \ - kronosnetd.default - -if BUILD_KRONOSNETD - -systemdconfdir = $(SYSTEMDDIR) -systemdconf_DATA = kronosnetd.service - -initscriptdir = $(INITDDIR) -initscript_SCRIPTS = kronosnetd - -kronosnetd: kronosnetd.in Makefile - rm -f $@-t $@ - cat $@.in | sed \ - -e 's#@''SBINDIR@#$(sbindir)#g' \ - -e 's#@''SYSCONFDIR@#$(sysconfdir)#g' \ - -e 's#@''INITDDIR@#$(INITDDIR)#g' \ - -e 's#@''LOCALSTATEDIR@#$(localstatedir)#g' \ - > $@-t - mv $@-t $@ - -kronosnetd.service: kronosnetd.service.in Makefile - rm -f $@-t $@ - cat $@.in | sed \ - -e 's#@''SBINDIR@#$(sbindir)#g' \ - -e 's#@''SYSCONFDIR@#$(sysconfdir)#g' \ - -e 's#@''INITDDIR@#$(INITDDIR)#g' \ - -e 's#@''LOCALSTATEDIR@#$(localstatedir)#g' \ - > $@-t - mv $@-t $@ - -install-exec-local: - $(INSTALL) -d $(DESTDIR)/$(INITDEFAULTDIR) - $(INSTALL) -m 644 $(srcdir)/kronosnetd.default $(DESTDIR)/$(INITDEFAULTDIR)/kronosnetd - -uninstall-local: - rm -f $(DESTDIR)/$(INITDEFAULTDIR)/kronosnetd - rmdir $(DESTDIR)/$(INITDEFAULTDIR) || :; - -all-local: $(initscript_SCRIPTS) $(systemdconf_DATA) - -clean-local: - rm -rf $(initscript_SCRIPTS) $(systemdconf_DATA) - -endif diff --git a/init/kronosnetd.default b/init/kronosnetd.default deleted file mode 100644 index a29b829f..00000000 --- a/init/kronosnetd.default +++ /dev/null @@ -1,11 +0,0 @@ -# kronosnetd startup options (see man kronosnetd.8) -# -# Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. -# -# Author: Fabio M. Di Nitto -# -# This software licensed under GPL-2.0+ -# - - -KNETD_OPTS="" diff --git a/init/kronosnetd.in b/init/kronosnetd.in deleted file mode 100644 index d1a58909..00000000 --- a/init/kronosnetd.in +++ /dev/null @@ -1,152 +0,0 @@ -#!/bin/bash - -# -# Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. -# -# Author: Fabio M. Di Nitto -# -# This software licensed under GPL-2.0+ -# - -# chkconfig: - 20 80 -# description: kronosnetd vpn daemon -# processname: kronosnetd -# -### BEGIN INIT INFO -# Provides: kronosnetd -# Required-Start: $network $remote_fs $syslog -# Required-Stop: $network $remote_fs $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: -# Short-Description: Starts and stops kronosnetd vpn daemon. -# Description: Starts and stops kronosnetd vpn daemon. -### END INIT INFO - -desc="kronosnetd" -prog="kronosnetd" - -# set secure PATH -PATH="/sbin:/bin:/usr/sbin:/usr/bin:@SBINDIR@" - -success() -{ - echo -ne "[ OK ]\r" -} - -failure() -{ - echo -ne "[FAILED]\r" -} - -status() -{ - pid=$(pidof $1 2>/dev/null) - rtrn=$? - if [ $rtrn -ne 0 ]; then - echo "$1 is stopped" - else - echo "$1 (pid $pid) is running..." - fi - return $rtrn -} - -# rpm based distros -if [ -d @SYSCONFDIR@/sysconfig ]; then - [ -f @INITDDIR@/functions ] && . @INITDDIR@/functions - [ -f @SYSCONFDIR@/sysconfig/$prog ] && . @SYSCONFDIR@/sysconfig/$prog - [ -z "$LOCK_FILE" ] && LOCK_FILE="@LOCALSTATEDIR@/lock/subsys/$prog" -fi - -# deb based distros -if [ -d @SYSCONFDIR@/default ]; then - [ -f @SYSCONFDIR@/default/$prog ] && . @SYSCONFDIR@/default/$prog - [ -z "$LOCK_FILE" ] && LOCK_FILE="@LOCALSTATEDIR@/lock/$prog" -fi - -# The version of __pids_pidof in /etc/init.d/functions calls pidof with -x -# This means it matches scripts, including this one. -# Redefine it here so that status (from the same file) works. -# Otherwise simultaneous calls to stop() will loop forever -__pids_pidof() { - pidof -c -o $$ -o $PPID -o %PPID "$1" || \ - pidof -c -o $$ -o $PPID -o %PPID "${1##*/}" -} - -start() -{ - echo -n "Starting $desc ($prog): " - - # most recent distributions use tmpfs for @LOCALSTATEDIR@/run - # to avoid to clean it up on every boot. - # they also assume that init scripts will create - # required subdirectories for proper operations - mkdir -p @LOCALSTATEDIR@/run - - if status $prog > /dev/null 2>&1; then - success - else - $prog $KNETD_OPTS > /dev/null 2>&1 - touch $LOCK_FILE - success - fi - echo -} - -stop() -{ - ! status $prog > /dev/null 2>&1 && return - - echo -n "Signaling $desc ($prog) to terminate: " - kill -TERM $(pidof $prog) > /dev/null 2>&1 - success - echo - - echo -n "Waiting for $prog to unload:" - while status $prog > /dev/null 2>&1; do - sleep 1 - echo -n "." - done - - rm -f $LOCK_FILE - success - echo -} - -restart() -{ - stop - start -} - -rtrn=0 - -case "$1" in -start) - start - rtrn=$? -;; -restart|reload|force-reload) - restart - rtrn=$? -;; -condrestart|try-restart) - if status $prog > /dev/null 2>&1; then - restart - rtrn=$? - fi -;; -status) - status $prog - rtrn=$? -;; -stop) - stop - rtrn=$? -;; -*) - echo "usage: $0 {start|stop|restart|reload|force-reload|condrestart|try-restart|status}" - rtrn=2 -;; -esac - -exit $rtrn diff --git a/init/kronosnetd.service.in b/init/kronosnetd.service.in deleted file mode 100644 index 04507c51..00000000 --- a/init/kronosnetd.service.in +++ /dev/null @@ -1,20 +0,0 @@ -# -# Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. -# -# Author: Fabio M. Di Nitto -# -# This software licensed under GPL-2.0+ -# - -[Unit] -Description=kronosnetd -Requires=network.target -After=network.target syslog.target - -[Service] -Type=forking -EnvironmentFile=/etc/sysconfig/kronosnetd -ExecStart=@SBINDIR@/kronosnetd $KNETD_OPTS - -[Install] -WantedBy=multi-user.target diff --git a/kronosnet.spec.in b/kronosnet.spec.in index 14343eee..7a3290ce 100644 --- a/kronosnet.spec.in +++ b/kronosnet.spec.in @@ -1,512 +1,461 @@ ############################################################################### ############################################################################### ## ## Copyright (C) 2012-2020 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 %@zstd@ zstd -%@kronosnetd@ kronosnetd %@libnozzle@ libnozzle %@runautogen@ runautogen %@rpmdebuginfo@ rpmdebuginfo %@overriderpmdebuginfo@ overriderpmdebuginfo %@buildman@ buildman %@installtests@ installtests %if %{with overriderpmdebuginfo} %undefine _enable_debug_packages %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+ URL: https://kronosnet.org Source0: https://kronosnet.org/releases/%{name}-%{version}%{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}}.tar.gz # Build dependencies BuildRequires: gcc libqb-devel # required to build man pages %if %{with buildman} BuildRequires: doxygen doxygen2man %endif %if %{with sctp} BuildRequires: lksctp-tools-devel %endif %if %{with nss} %if 0%{?suse_version} BuildRequires: mozilla-nss-devel %else BuildRequires: nss-devel %endif %endif %if %{with openssl} %if 0%{?suse_version} BuildRequires: libopenssl-devel %else BuildRequires: openssl-devel %endif %endif %if %{with zlib} BuildRequires: zlib-devel %endif %if %{with lz4} %if 0%{?suse_version} BuildRequires: liblz4-devel %else BuildRequires: lz4-devel %endif %endif %if %{with lzo2} BuildRequires: lzo-devel %endif %if %{with lzma} BuildRequires: xz-devel %endif %if %{with bzip2} %if 0%{?suse_version} BuildRequires: libbz2-devel %else BuildRequires: bzip2-devel %endif %endif %if %{with zstd} BuildRequires: libzstd-devel %endif -%if %{with kronosnetd} -BuildRequires: pam-devel -%endif %if %{with libnozzle} BuildRequires: libnl3-devel %endif %if %{with runautogen} BuildRequires: autoconf automake libtool %endif %prep %setup -q -n %{name}-%{version}%{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}} %build %if %{with runautogen} ./autogen.sh %endif %{configure} \ %if %{with installtests} --enable-install-tests \ %else --disable-install-tests \ %endif %if %{with buildman} --enable-man \ %else --disable-man \ %endif %if %{with sctp} --enable-libknet-sctp \ %else --disable-libknet-sctp \ %endif %if %{with nss} --enable-crypto-nss \ %else --disable-crypto-nss \ %endif %if %{with openssl} --enable-crypto-openssl \ %else --disable-crypto-openssl \ %endif %if %{with zlib} --enable-compress-zlib \ %else --disable-compress-zlib \ %endif %if %{with lz4} --enable-compress-lz4 \ %else --disable-compress-lz4 \ %endif %if %{with lzo2} --enable-compress-lzo2 \ %else --disable-compress-lzo2 \ %endif %if %{with lzma} --enable-compress-lzma \ %else --disable-compress-lzma \ %endif %if %{with bzip2} --enable-compress-bzip2 \ %else --disable-compress-bzip2 \ %endif %if %{with zstd} --enable-compress-zstd \ %else --disable-compress-zstd \ %endif -%if %{with kronosnetd} - --enable-kronosnetd \ -%else - --disable-kronosnetd \ -%endif %if %{with libnozzle} --enable-libnozzle \ %else --disable-libnozzle \ %endif --with-initdefaultdir=%{_sysconfdir}/sysconfig/ \ --with-systemddir=%{_unitdir} 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 {} \; # remove init scripts rm -rf %{buildroot}/etc/init.d # remove docs rm -rf %{buildroot}/usr/share/doc/kronosnet # main empty package %description The kronosnet source -%if %{with kronosnetd} -## Runtime and subpackages section -%package -n kronosnetd -Summary: Multipoint-to-Multipoint VPN daemon -License: GPLv2+ -Requires(post): systemd-sysv -Requires(post): systemd-units -Requires(preun): systemd-units -Requires(postun): systemd-units -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 -%systemd_post kronosnetd.service -getent group @defaultadmgroup@ >/dev/null || groupadd --force --system @defaultadmgroup@ - -%preun -n kronosnetd -%systemd_preun kronosnetd.service - -%files -n kronosnetd -%license 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 -%{_unitdir}/kronosnetd.service -%{_sbindir}/* -%{_mandir}/man8/* -%endif - %if %{with libnozzle} %package -n libnozzle1 Summary: Simple userland wrapper around kernel tap devices License: LGPLv2+ %description -n libnozzle1 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 libnozzle1 %license COPYING.* COPYRIGHT %{_libdir}/libnozzle.so.* %if 0%{?ldconfig_scriptlets} %ldconfig_scriptlets -n libnozzle1 %else %post -n libnozzle1 -p /sbin/ldconfig %postun -n libnozzle1 -p /sbin/ldconfig %endif %package -n libnozzle1-devel Summary: Simple userland wrapper around kernel tap devices (developer files) License: LGPLv2+ Requires: libnozzle1%{_isa} = %{version}-%{release} Requires: pkgconfig %description -n libnozzle1-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 libnozzle1-devel %license COPYING.* COPYRIGHT %{_libdir}/libnozzle.so %{_includedir}/libnozzle.h %{_libdir}/pkgconfig/libnozzle.pc %if %{with buildman} %{_mandir}/man3/nozzle*.3.gz %endif %endif %package -n libknet1 Summary: Kronosnet core switching implementation License: LGPLv2+ %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 %license COPYING.* COPYRIGHT %{_libdir}/libknet.so.* %dir %{_libdir}/kronosnet %if 0%{?ldconfig_scriptlets} %ldconfig_scriptlets -n libknet1 %else %post -n libknet1 -p /sbin/ldconfig %postun -n libknet1 -p /sbin/ldconfig %endif %package -n libknet1-devel Summary: Kronosnet core switching implementation (developer files) License: LGPLv2+ Requires: libknet1%{_isa} = %{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 %license COPYING.* COPYRIGHT %{_libdir}/libknet.so %{_includedir}/libknet.h %{_libdir}/pkgconfig/libknet.pc %if %{with buildman} %{_mandir}/man3/knet*.3.gz %endif %if %{with nss} %package -n libknet1-crypto-nss-plugin Summary: Provides libknet1 nss support License: LGPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n libknet1-crypto-nss-plugin Provides NSS crypto support for libknet1. %files -n libknet1-crypto-nss-plugin %{_libdir}/kronosnet/crypto_nss.so %endif %if %{with openssl} %package -n libknet1-crypto-openssl-plugin Summary: Provides libknet1 openssl support License: LGPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n libknet1-crypto-openssl-plugin Provides OpenSSL crypto support for libknet1. %files -n libknet1-crypto-openssl-plugin %{_libdir}/kronosnet/crypto_openssl.so %endif %if %{with zlib} %package -n libknet1-compress-zlib-plugin Summary: Provides libknet1 zlib support License: LGPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n libknet1-compress-zlib-plugin Provides zlib compression support for libknet1. %files -n libknet1-compress-zlib-plugin %{_libdir}/kronosnet/compress_zlib.so %endif %if %{with lz4} %package -n libknet1-compress-lz4-plugin Summary: Provides libknet1 lz4 and lz4hc support License: LGPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n libknet1-compress-lz4-plugin Provides lz4 and lz4hc compression support for libknet1. %files -n libknet1-compress-lz4-plugin %{_libdir}/kronosnet/compress_lz4.so %{_libdir}/kronosnet/compress_lz4hc.so %endif %if %{with lzo2} %package -n libknet1-compress-lzo2-plugin Summary: Provides libknet1 lzo2 support License: LGPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n libknet1-compress-lzo2-plugin Provides lzo2 compression support for libknet1. %files -n libknet1-compress-lzo2-plugin %{_libdir}/kronosnet/compress_lzo2.so %endif %if %{with lzma} %package -n libknet1-compress-lzma-plugin Summary: Provides libknet1 lzma support License: LGPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n libknet1-compress-lzma-plugin Provides lzma compression support for libknet1. %files -n libknet1-compress-lzma-plugin %{_libdir}/kronosnet/compress_lzma.so %endif %if %{with bzip2} %package -n libknet1-compress-bzip2-plugin Summary: Provides libknet1 bzip2 support License: LGPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n libknet1-compress-bzip2-plugin Provides bzip2 compression support for libknet1. %files -n libknet1-compress-bzip2-plugin %{_libdir}/kronosnet/compress_bzip2.so %endif %if %{with zstd} %package -n libknet1-compress-zstd-plugin Summary: Provides libknet1 zstd support License: LGPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n libknet1-compress-zstd-plugin Provides zstd compression support for libknet1. %files -n libknet1-compress-zstd-plugin %{_libdir}/kronosnet/compress_zstd.so %endif %package -n libknet1-crypto-plugins-all Summary: Provides libknet1 crypto plugins meta package License: LGPLv2+ %if %{with nss} Requires: libknet1-crypto-nss-plugin%{_isa} = %{version}-%{release} %endif %if %{with openssl} Requires: libknet1-crypto-openssl-plugin%{_isa} = %{version}-%{release} %endif %description -n libknet1-crypto-plugins-all Provides meta package to install all of libknet1 crypto plugins %files -n libknet1-crypto-plugins-all %package -n libknet1-compress-plugins-all Summary: Provides libknet1 compress plugins meta package License: LGPLv2+ %if %{with zlib} Requires: libknet1-compress-zlib-plugin%{_isa} = %{version}-%{release} %endif %if %{with lz4} Requires: libknet1-compress-lz4-plugin%{_isa} = %{version}-%{release} %endif %if %{with lzo2} Requires: libknet1-compress-lzo2-plugin%{_isa} = %{version}-%{release} %endif %if %{with lzma} Requires: libknet1-compress-lzma-plugin%{_isa} = %{version}-%{release} %endif %if %{with bzip2} Requires: libknet1-compress-bzip2-plugin%{_isa} = %{version}-%{release} %endif %if %{with zstd} Requires: libknet1-compress-zstd-plugin%{_isa} = %{version}-%{release} %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 Summary: Provides libknet1 plugins meta package License: LGPLv2+ Requires: libknet1-compress-plugins-all%{_isa} = %{version}-%{release} Requires: libknet1-crypto-plugins-all%{_isa} = %{version}-%{release} %description -n libknet1-plugins-all Meta package to install all of libknet1 plugins %files -n libknet1-plugins-all %if %{with installtests} %package -n kronosnet-tests Summary: Provides kronosnet test suite License: GPLv2+ Requires: libknet1%{_isa} = %{version}-%{release} %description -n kronosnet-tests This package contains all the libknet and libnozzle test suite. %files -n kronosnet-tests %{_libdir}/kronosnet/tests/* %endif %if %{with rpmdebuginfo} %debug_package %endif %changelog * @date@ Autotools generated version - @version@-1-@numcomm@.@alphatag@.@dirty@ - These aren't the droids you're looking for. diff --git a/kronosnetd/Makefile.am b/kronosnetd/Makefile.am deleted file mode 100644 index 041d1f8c..00000000 --- a/kronosnetd/Makefile.am +++ /dev/null @@ -1,89 +0,0 @@ -# -# Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. -# -# Author: Fabio M. Di Nitto -# -# This software licensed under GPL-2.0+ -# - -MAINTAINERCLEANFILES = Makefile.in kronostnetd.logrotate - -include $(top_srcdir)/build-aux/check.mk - -EXTRA_DIST = kronosnetd.logrotate.in - -noinst_HEADERS = \ - cfg.h \ - etherfilter.h \ - logging.h \ - vty.h \ - vty_auth.h \ - vty_cli.h \ - vty_cli_cmds.h \ - vty_utils.h - -kronosnetd_SOURCES = \ - cfg.c \ - etherfilter.c \ - main.c \ - logging.c \ - vty.c \ - vty_auth.c \ - vty_cli.c \ - vty_cli_cmds.c \ - vty_utils.c - -kronosnetd_CPPFLAGS = \ - -I$(top_srcdir)/libnozzle \ - -I$(top_srcdir)/libknet - -kronosnetd_CFLAGS = $(AM_CFLAGS) $(libqb_CFLAGS) - -kronosnetd_LDADD = \ - $(top_builddir)/libknet/libknet.la \ - $(top_builddir)/libnozzle/libnozzle.la \ - $(libqb_LIBS) \ - $(pam_misc_LIBS) $(pam_LIBS) - -knet_keygen_SOURCES = keygen.c - -knet_keygen_CPPFLAGS = -I$(top_srcdir)/libknet - -if BUILD_KRONOSNETD - -sbin_PROGRAMS = kronosnetd \ - knet-keygen - -install-exec-local: - $(INSTALL) -d $(DESTDIR)/$(DEFAULT_CONFIG_DIR) - $(INSTALL) -d $(DESTDIR)/$(DEFAULT_CONFIG_DIR)/down.d - $(INSTALL) -d $(DESTDIR)/$(DEFAULT_CONFIG_DIR)/post-down.d - $(INSTALL) -d $(DESTDIR)/$(DEFAULT_CONFIG_DIR)/pre-up.d - $(INSTALL) -d $(DESTDIR)/$(DEFAULT_CONFIG_DIR)/up.d - $(INSTALL) -d $(DESTDIR)/$(DEFAULT_CONFIG_DIR)/cryptokeys.d - $(INSTALL) -d -m 0755 $(DESTDIR)/$(sysconfdir)/logrotate.d - $(INSTALL) -m 644 kronosnetd.logrotate $(DESTDIR)/$(sysconfdir)/logrotate.d/kronosnetd - $(INSTALL) -d -m 0755 $(DESTDIR)/$(sysconfdir)/pam.d - if [ -a $(sysconfdir)/pam.d/password-auth ]; then \ - cd $(DESTDIR)/$(sysconfdir)/pam.d && \ - rm -f kronosnetd && \ - $(LN_S) password-auth kronosnetd; \ - else \ - cd $(DESTDIR)/$(sysconfdir)/pam.d && \ - rm -f kronosnetd && \ - $(LN_S) passwd kronosnetd; \ - fi - -uninstall-local: - rmdir $(DESTDIR)/$(DEFAULT_CONFIG_DIR)/cryptokeys.d || :; - rmdir $(DESTDIR)/$(DEFAULT_CONFIG_DIR)/down.d || :; - rmdir $(DESTDIR)/$(DEFAULT_CONFIG_DIR)/post-down.d || :; - rmdir $(DESTDIR)/$(DEFAULT_CONFIG_DIR)/pre-up.d || :; - rmdir $(DESTDIR)/$(DEFAULT_CONFIG_DIR)/up.d || :; - rmdir $(DESTDIR)/$(DEFAULT_CONFIG_DIR) || :; - rm -f $(DESTDIR)/$(sysconfdir)/logrotate.d/kronosnetd - rmdir $(DESTDIR)/$(sysconfdir)/logrotate.d || :; - rm -f $(DESTDIR)/$(sysconfdir)/pam.d/kronosnetd || :; - rmdir $(DESTDIR)/$(sysconfdir)/pam.d || :; - -endif diff --git a/kronosnetd/cfg.c b/kronosnetd/cfg.c deleted file mode 100644 index 4b1f3387..00000000 --- a/kronosnetd/cfg.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. - * - * Author: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+ - */ - -#include "config.h" - -#include -#include -#include -#include - -#include "cfg.h" -#include "libnozzle.h" - -struct knet_cfg *knet_get_iface(const char *name, int create) -{ - struct knet_cfg *knet_iface = knet_cfg_head.knet_cfg; - int found = 0; - - while (knet_iface != NULL) { - if (!strcmp(nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle), name)) { - found = 1; - break; - } - knet_iface = knet_iface->next; - } - - if ((!found) && (create)) { - knet_iface = malloc(sizeof(struct knet_cfg)); - if (!knet_iface) - goto out_clean; - - memset(knet_iface, 0, sizeof(struct knet_cfg)); - - knet_iface->cfg_ring.base_port = KNET_RING_DEFPORT; - - strncpy(knet_iface->knet_handle_crypto_cfg.crypto_model, - "none", - sizeof(knet_iface->knet_handle_crypto_cfg.crypto_model) - 1); - - strncpy(knet_iface->knet_handle_crypto_cfg.crypto_cipher_type, - "none", - sizeof(knet_iface->knet_handle_crypto_cfg.crypto_cipher_type) - 1); - - strncpy(knet_iface->knet_handle_crypto_cfg.crypto_hash_type, - "none", - sizeof(knet_iface->knet_handle_crypto_cfg.crypto_hash_type) - 1); - - if (knet_cfg_head.knet_cfg) { - struct knet_cfg *knet_iface_last = knet_cfg_head.knet_cfg; - - while (knet_iface_last->next != NULL) { - knet_iface_last = knet_iface_last->next; - } - knet_iface_last->next = knet_iface; - } else { - knet_cfg_head.knet_cfg = knet_iface; - } - } - -out_clean: - - return knet_iface; -} - -void knet_destroy_iface(struct knet_cfg *knet_iface) -{ - struct knet_cfg *knet_iface_tmp = knet_cfg_head.knet_cfg; - struct knet_cfg *knet_iface_prev = knet_cfg_head.knet_cfg; - - while (knet_iface_tmp != knet_iface) { - knet_iface_prev = knet_iface_tmp; - knet_iface_tmp = knet_iface_tmp->next; - } - - if (knet_iface_tmp == knet_iface) { - if (knet_iface_tmp == knet_iface_prev) { - knet_cfg_head.knet_cfg = knet_iface_tmp->next; - } else { - knet_iface_prev->next = knet_iface_tmp->next; - } - free(knet_iface); - } -} diff --git a/kronosnetd/cfg.h b/kronosnetd/cfg.h deleted file mode 100644 index db5f3c80..00000000 --- a/kronosnetd/cfg.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. - * - * Authors: Fabio M. Di Nitto - * Federico Simoncelli - * - * This software licensed under GPL-2.0+ - */ - -#ifndef __KNETD_CFG_H__ -#define __KNETD_CFG_H__ - -#include -#include - -#include "libnozzle.h" -#include "libknet.h" - -#define KNET_RING_DEFPORT 50000 - -struct knet_cfg_eth { - nozzle_t nozzle; - int auto_mtu; - knet_node_id_t node_id; -}; - -struct knet_cfg_ring { - knet_handle_t knet_h; - int data_mtu; - int base_port; -}; - -struct knet_cfg { - struct knet_cfg_eth cfg_eth; - struct knet_cfg_ring cfg_ring; - int active; - struct knet_handle_crypto_cfg knet_handle_crypto_cfg; - struct knet_cfg *next; -}; - -struct knet_cfg_top { - char *conffile; - char *logfile; - char *vty_ipv4; - char *vty_ipv6; - char *vty_port; - struct knet_cfg *knet_cfg; -}; - -struct knet_cfg *knet_get_iface(const char *name, const int create); -void knet_destroy_iface(struct knet_cfg *knet_iface); - -extern struct knet_cfg_top knet_cfg_head; - -#endif diff --git a/kronosnetd/etherfilter.c b/kronosnetd/etherfilter.c deleted file mode 100644 index fc711a8d..00000000 --- a/kronosnetd/etherfilter.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. - * - * Author: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+ - */ - -#include "config.h" - -#include -#include -#include -#include - -#include "etherfilter.h" - -/* - * stole from linux kernel/include/linux/etherdevice.h - */ - -static inline int is_zero_ether_addr(const uint8_t *addr) -{ - return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]); -} - -static inline int is_multicast_ether_addr(const uint8_t *addr) -{ - return 0x01 & addr[0]; -} - -static inline int is_broadcast_ether_addr(const uint8_t *addr) -{ - return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff; -} - -int ether_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) -{ - struct ether_header *eth_h = (struct ether_header *)outdata; - uint8_t *dst_mac = (uint8_t *)eth_h->ether_dhost; - uint16_t dst_host_id; - - if (is_zero_ether_addr(dst_mac)) - return -1; - - if (is_multicast_ether_addr(dst_mac) || - is_broadcast_ether_addr(dst_mac)) { - return 1; - } - - memmove(&dst_host_id, &dst_mac[4], 2); - - dst_host_ids[0] = ntohs(dst_host_id); - *dst_host_ids_entries = 1; - - return 0; -} diff --git a/kronosnetd/etherfilter.h b/kronosnetd/etherfilter.h deleted file mode 100644 index 700668a9..00000000 --- a/kronosnetd/etherfilter.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. - * - * Author: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+ - */ - -#ifndef __KNETD_ETHERFILTER_H__ -#define __KNETD_ETHERFILTER_H__ - -#include -#include -#include "libknet.h" - -int ether_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); - -#endif diff --git a/kronosnetd/keygen.c b/kronosnetd/keygen.c deleted file mode 100644 index 41251cff..00000000 --- a/kronosnetd/keygen.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. - * - * Author: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+ - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -static char *output_file = NULL; -static ssize_t keylen = KNET_MAX_KEY_LEN; - -static void print_usage(void) -{ - printf("\nUsage:\n\n"); - printf("knet-keygen -o [-s ]\n\n"); -}; - -#define OPTION_STRING "ho:s:" - -static int read_arguments(int argc, char **argv) -{ - int cont = 1; - int optchar; - - while (cont) { - optchar = getopt(argc, argv, OPTION_STRING); - - switch (optchar) { - - case 'o': - output_file = strdup(optarg); - if (!output_file) { - fprintf(stderr, "Error: Unable to allocate memory\n"); - return -1; - } - if (strlen(output_file) > PATH_MAX) { - fprintf(stderr, "Seriously? WTF\n"); - return -1; - } - break; - - case 's': - keylen = atoi(optarg); - if ((keylen < KNET_MIN_KEY_LEN) || (keylen > KNET_MAX_KEY_LEN)) { - fprintf(stderr, "Error: Key size should be a value between %d and %d (default) included\n", - KNET_MIN_KEY_LEN, KNET_MAX_KEY_LEN); - return -1; - } - break; - - case 'h': - print_usage(); - exit(EXIT_SUCCESS); - break; - - case EOF: - cont = 0; - break; - - default: - fprintf(stderr, "Error: unknown option: %c\n", optchar); - print_usage(); - return -1; - break; - - } - } - if (!output_file) { - fprintf(stderr, "Error: no output file specified\n"); - print_usage(); - return -1; - } - return 0; -} - -int main (int argc, char *argv[]) -{ - int ret = 0; - int fd = -1; - ssize_t res; - ssize_t bytes_read = 0; - char *keybuf = NULL; - - printf (PACKAGE " key generator.\n"); - - if (read_arguments(argc, argv) < 0) { - goto exit_error; - } - - if (geteuid() != 0) { - fprintf(stderr, "Error: Authorization key must be generated as root user.\n"); - goto exit_error; - } - - fd = open ("/dev/random", O_RDONLY); - if (fd < 0) { - fprintf(stderr, "Error: Unable to open /dev/random\n"); - goto exit_error; - } - - keybuf = malloc(keylen); - if (!keybuf) { - fprintf(stderr, "Error: Unable to allocate memory for key\n"); - goto exit_error; - } - - printf("Gathering %zd bytes for key from /dev/random.\n", keylen); - printf("This process might take a long time due the amount on entropy required\n"); - printf("Press keys on your keyboard, perform any kind of disk I/O and/or network to generate entropy faster.\n"); - -keep_reading: - res = read(fd, &keybuf[bytes_read], keylen - bytes_read); - if (res == -1) { - fprintf(stderr, "Error: Unable to read from /dev/random.\n"); - goto exit_error; - } - bytes_read += res; - if (bytes_read != keylen) { - printf("bytes read = %zd, missing = %zd.\n", bytes_read, keylen - bytes_read); - goto keep_reading; - } - close (fd); - fd = -1; - - fd = open (output_file, O_CREAT|O_WRONLY, 600); - if (fd == -1) { - fprintf(stderr, "Error: Could not create %s\n", output_file); - goto exit_error; - } - - /* - * Make sure file is owned by root and mode 0400 - */ - if (fchown(fd, 0, 0)) { - fprintf(stderr, "Error: Could not set uid 0 (root) and gid 0 (root) on keyfile %s\n", output_file); - goto exit_error; - } - if (fchmod(fd, 0400)) { - fprintf(stderr, "Error: Could not set read-only permissions on keyfile %s\n", output_file); - goto exit_error; - } - - printf("Writing private key to %s\n", output_file); - - if (write(fd, keybuf, keylen) != keylen) { - fprintf(stderr, "Error: Could not write key to file %s\n", output_file); - goto exit_error; - } - - printf("Done.\n"); - printf("Please copy this file in " DEFAULT_CONFIG_DIR "/cryptokeys.d/\n"); - printf("on all nodes participating in the same kronosnet instance\n"); - -exit_clean: - if (output_file) - free(output_file); - if (keybuf) - free(keybuf); - if (fd > -1) - close(fd); - - return ret; - -exit_error: - ret = -1; - goto exit_clean; -} diff --git a/kronosnetd/kronosnetd.logrotate.in b/kronosnetd/kronosnetd.logrotate.in deleted file mode 100644 index e78034cc..00000000 --- a/kronosnetd/kronosnetd.logrotate.in +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (C) 2012-2020 Red Hat, Inc. All rights reserved. -# -# Author: Fabio M. Di Nitto -# -# This software licensed under GPL-2.0+ -# - -@LOGDIR@kronosnetd.log { - missingok - compress - copytruncate - daily - rotate 31 - minsize 2048 - notifempty -} diff --git a/kronosnetd/logging.c b/kronosnetd/logging.c deleted file mode 100644 index ee30dd17..00000000 --- a/kronosnetd/logging.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. - * - * Authors: Fabio M. Di Nitto - * Federico Simoncelli - * - * This software licensed under GPL-2.0+ - */ - -#include "config.h" - -#include "logging.h" - -void logging_init_defaults(int debug, int daemonize, const char *logfile) -{ - int level = SYSLOGLEVEL; - int32_t filetarget; - - if (debug) { - level = LOG_DEBUG; - } - - qb_log_init(PACKAGE "d", SYSLOGFACILITY, level); - - qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE); - if (debug) { - qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_PRIORITY_BUMP, - LOG_INFO - LOG_DEBUG); - } - - /* - * initialize stderr output only if we are not forking in background - */ - if (!daemonize) { - qb_log_format_set(QB_LOG_STDERR, "%t %N [%p]: %b"); - qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE); - qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD, - QB_LOG_FILTER_FUNCTION, "*", level); - } - - filetarget = qb_log_file_open(logfile); - qb_log_ctl(filetarget, QB_LOG_CONF_ENABLED, QB_TRUE); - qb_log_format_set(filetarget, "%t %N [%p]: %b"); - qb_log_filter_ctl(filetarget, QB_LOG_FILTER_ADD, - QB_LOG_FILTER_FUNCTION, "*", level); - - qb_log_thread_start(); - qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_THREADED, QB_TRUE); - qb_log_ctl(filetarget, QB_LOG_CONF_THREADED, QB_TRUE); -} - -void logging_fini(void) -{ - qb_log_fini(); -} diff --git a/kronosnetd/logging.h b/kronosnetd/logging.h deleted file mode 100644 index a32d7277..00000000 --- a/kronosnetd/logging.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. - * - * Authors: Fabio M. Di Nitto - * Federico Simoncelli - * - * This software licensed under GPL-2.0+ - */ - -#ifndef __KNETD_LOGGING_H__ -#define __KNETD_LOGGING_H__ - -#include - -#define log_debug(fmt, args...) qb_log(LOG_DEBUG, "(%s:%i|%s): " fmt, __FILE__, __LINE__, __FUNCTION__, ##args); - -#define log_kdebug(fmt, args...) qb_log(LOG_DEBUG, fmt, ##args); - -#define log_info(fmt, args...) qb_log(LOG_INFO, fmt, ##args); - -#define log_warn(fmt, args...) qb_log(LOG_WARNING, fmt, ##args); - -#define log_error(fmt, args...) qb_log(LOG_ERR, fmt, ##args); - -void logging_init_defaults(int debug, int daemonize, const char *logfile); - -void logging_fini(void); - -#endif diff --git a/kronosnetd/main.c b/kronosnetd/main.c deleted file mode 100644 index 3a284ca1..00000000 --- a/kronosnetd/main.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. - * - * Authors: Fabio M. Di Nitto - * Federico Simoncelli - * - * This software licensed under GPL-2.0+ - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cfg.h" -#include "vty.h" -#include "logging.h" - -#define LOCKFILE_NAME RUNDIR PACKAGE "d.pid" - -#define OPTION_STRING "hdfVc:l:a:b:p:" - -static int debug = 0; -static int daemonize = 1; - -struct knet_cfg_top knet_cfg_head; - -static void print_usage(void) -{ - printf("Usage:\n\n"); - printf(PACKAGE "d [options]\n\n"); - printf("Options:\n\n"); - printf(" -a Bind management VTY to ipv6_addr (default: localhost)\n"); - printf(" -b Bind management VTY to ipv4_addr (default: localhost)\n"); - printf(" -p Bind management VTY to port (default %d)\n", - KNET_VTY_DEFAULT_PORT); - printf(" -c Use config file (default "DEFAULT_CONFIG_FILE")\n"); - printf(" -l Use log file (default "DEFAULT_LOG_FILE")\n"); - printf(" -f Do not fork in background\n"); - printf(" -d Enable debugging output\n"); - printf(" -h This help\n"); - printf(" -V Print program version information\n"); - return; -} - -static int read_arguments(int argc, char **argv) -{ - int cont = 1; - int optchar; - int int_port; - - while (cont) { - optchar = getopt(argc, argv, OPTION_STRING); - - switch (optchar) { - - case 'a': - knet_cfg_head.vty_ipv6 = strdup(optarg); - if (!knet_cfg_head.vty_ipv6) - return -1; - break; - - case 'b': - knet_cfg_head.vty_ipv4 = strdup(optarg); - if (!knet_cfg_head.vty_ipv4) - return -1; - break; - - case 'p': - int_port = atoi(optarg); - if ((int_port < 0) || (int_port > 65535)) { - errno = EINVAL; - return -1; - } - knet_cfg_head.vty_port = strdup(optarg); - if (!knet_cfg_head.vty_port) - return -1; - break; - - case 'c': - knet_cfg_head.conffile = strdup(optarg); - if (!knet_cfg_head.conffile) - return -1; - break; - - case 'l': - knet_cfg_head.logfile = strdup(optarg); - if (!knet_cfg_head.logfile) - return -1; - break; - - case 'd': - debug = 1; - break; - - case 'f': - daemonize = 0; - break; - - case 'h': - print_usage(); - exit(EXIT_SUCCESS); - break; - - case 'V': - printf(PACKAGE "d " PACKAGE_VERSION " (built " __DATE__ - " " __TIME__ ")\n"); - exit(EXIT_SUCCESS); - break; - - case EOF: - cont = 0; - break; - - default: - fprintf(stderr, "unknown option: %c\n", optchar); - print_usage(); - exit(EXIT_FAILURE); - break; - - } - } - return 0; -} - -static int set_scheduler(void) -{ - struct sched_param sched_param; - int err; - - err = sched_get_priority_max(SCHED_RR); - if (err < 0) { - log_warn("Could not get maximum scheduler priority"); - return err; - } - - sched_param.sched_priority = err; - err = sched_setscheduler(0, SCHED_RR, &sched_param); - if (err < 0) - log_warn("could not set SCHED_RR priority %d", - sched_param.sched_priority); - - return err; -} - -static void remove_lockfile(void) -{ - unlink(LOCKFILE_NAME); -} - -static int create_lockfile(const char *lockfile) -{ - int fd, value; - size_t bufferlen; - ssize_t write_out; - struct flock lock; - char buffer[50]; - - if ((fd = open(lockfile, O_CREAT | O_WRONLY, - (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0) { - fprintf(stderr, "Cannot open lockfile [%s], error was [%s]\n", - lockfile, strerror(errno)); - return -1; - } - - lock.l_type = F_WRLCK; - lock.l_start = 0; - lock.l_whence = SEEK_SET; - lock.l_len = 0; - -retry_fcntl: - - if (fcntl(fd, F_SETLKW, &lock) < 0) { - switch (errno) { - case EINTR: - goto retry_fcntl; - break; - case EACCES: - case EAGAIN: - fprintf(stderr, "Cannot lock lockfile [%s], error was [%s]\n", - lockfile, strerror(errno)); - break; - default: - fprintf(stderr, "process is already running\n"); - } - - goto fail_close; - } - - if (ftruncate(fd, 0) < 0) { - fprintf(stderr, "Cannot truncate pidfile [%s], error was [%s]\n", - lockfile, strerror(errno)); - - goto fail_close_unlink; - } - - memset(buffer, 0, sizeof(buffer)); - snprintf(buffer, sizeof(buffer)-1, "%d\n", getpid()); - - bufferlen = strlen(buffer); - write_out = write(fd, buffer, bufferlen); - - if ((write_out < 0) || (write_out == 0 && errno)) { - fprintf(stderr, "Cannot write pid to pidfile [%s], error was [%s]\n", - lockfile, strerror(errno)); - - goto fail_close_unlink; - } - - if ((write_out == 0) || ((size_t)write_out < bufferlen)) { - fprintf(stderr, "Cannot write pid to pidfile [%s], shortwrite of" - "[%zd] bytes, expected [%zu]\n", - lockfile, write_out, bufferlen); - - goto fail_close_unlink; - } - - if ((value = fcntl(fd, F_GETFD, 0)) < 0) { - fprintf(stderr, "Cannot get close-on-exec flag from pidfile [%s], " - "error was [%s]\n", lockfile, strerror(errno)); - - goto fail_close_unlink; - } - value |= FD_CLOEXEC; - if (fcntl(fd, F_SETFD, value) < 0) { - fprintf(stderr, "Cannot set close-on-exec flag from pidfile [%s], " - "error was [%s]\n", lockfile, strerror(errno)); - - goto fail_close_unlink; - } - - atexit(remove_lockfile); - - return 0; - -fail_close_unlink: - if (unlink(lockfile)) - fprintf(stderr, "Unable to unlink %s\n", lockfile); - -fail_close: - if (close(fd)) - fprintf(stderr, "Unable to close %s file descriptor\n", lockfile); - return -1; -} - -static void set_cfg_defaults(void) -{ - if (!knet_cfg_head.conffile) - knet_cfg_head.conffile = strdup(DEFAULT_CONFIG_FILE); - if (!knet_cfg_head.conffile) { - fprintf(stderr, "Unable to allocate memory for config file\n"); - exit(EXIT_FAILURE); - } - - if (!knet_cfg_head.logfile) - knet_cfg_head.logfile = strdup(DEFAULT_LOG_FILE); - if (!knet_cfg_head.conffile) { - fprintf(stderr, "Unable to allocate memory for log file\n"); - exit(EXIT_FAILURE); - } - - if (!knet_cfg_head.vty_ipv6) - knet_cfg_head.vty_ipv6 = strdup("::1"); - if (!knet_cfg_head.vty_ipv6) { - fprintf(stderr, "Unable to allocate memory for default ip address\n"); - exit(EXIT_FAILURE); - } - - if (!knet_cfg_head.vty_ipv4) - knet_cfg_head.vty_ipv4 = strdup("127.0.0.1"); - if (!knet_cfg_head.vty_ipv4) { - fprintf(stderr, "Unable to allocate memory for default ip address\n"); - exit(EXIT_FAILURE); - } - - if (!knet_cfg_head.vty_port) { - char portbuf[8]; - memset(&portbuf, 0, sizeof(portbuf)); - snprintf(portbuf, sizeof(portbuf), "%d", KNET_VTY_DEFAULT_PORT); - knet_cfg_head.vty_port = strdup(portbuf); - } - if (!knet_cfg_head.vty_port) { - fprintf(stderr, "Unable to allocate memory for default port address\n"); - exit(EXIT_FAILURE); - } -} - -int main(int argc, char **argv) -{ - int err; - - memset(&knet_cfg_head, 0, sizeof(struct knet_cfg_top)); - - if (read_arguments(argc, argv) < 0) { - fprintf(stderr, "Unable to parse options\n"); - exit(EXIT_FAILURE); - } - - set_cfg_defaults(); - - if (create_lockfile(LOCKFILE_NAME) < 0) { - fprintf(stderr, "Unable to create lockfile\n"); - exit(EXIT_FAILURE); - } - - if (daemonize) { - if (daemon(0, 0) < 0) { - perror("Unable to daemonize"); - exit(EXIT_FAILURE); - } - } - - logging_init_defaults(debug, daemonize, knet_cfg_head.logfile); - log_info(PACKAGE "d version " VERSION); - - /* - * don't fail if scheduler is not RR because systemd is - * an utter piece of shit that refuses us to set RR via init script - */ - set_scheduler(); - - err = knet_vty_main_loop(debug); - if (err < 0) - log_error("Detected fatal error in main loop"); - - if (knet_cfg_head.logfile) - free(knet_cfg_head.logfile); - if (knet_cfg_head.conffile) - free(knet_cfg_head.conffile); - if (knet_cfg_head.vty_ipv6) - free(knet_cfg_head.vty_ipv6); - if (knet_cfg_head.vty_ipv4) - free(knet_cfg_head.vty_ipv4); - if (knet_cfg_head.vty_port) - free(knet_cfg_head.vty_port); - - logging_fini(); - - return err; -} diff --git a/kronosnetd/vty.c b/kronosnetd/vty.c deleted file mode 100644 index 4e54a1fa..00000000 --- a/kronosnetd/vty.c +++ /dev/null @@ -1,504 +0,0 @@ -/* - * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. - * - * Authors: Fabio M. Di Nitto - * Federico Simoncelli - * - * This software licensed under GPL-2.0+ - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cfg.h" -#include "logging.h" -#include "netutils.h" -#include "vty.h" -#include "vty_auth.h" -#include "vty_cli.h" -#include "vty_cli_cmds.h" -#include "vty_utils.h" - -static int vty_max_connections = KNET_VTY_DEFAULT_MAX_CONN; -static int vty_current_connections = 0; -static int daemon_quit = 0; - -pthread_mutex_t knet_vty_mutex = PTHREAD_MUTEX_INITIALIZER; -int knet_vty_config = -1; -struct knet_vty knet_vtys[KNET_VTY_TOTAL_MAX_CONN]; -struct knet_vty_global_conf vty_global_conf; -pthread_t logging_thread; - -static 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; -} - -static 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; -} - -static void *_handle_logging_thread(void *data) -{ - int logfd; - int se_result = 0; - fd_set rfds; - struct timeval tv; - - memmove(&logfd, data, sizeof(int)); - - while (se_result >= 0 && !daemon_quit){ - FD_ZERO (&rfds); - FD_SET (logfd, &rfds); - - tv.tv_sec = 1; - tv.tv_usec = 0; - - se_result = select(FD_SETSIZE, &rfds, 0, 0, &tv); - - if (se_result == -1) - goto out; - - if (se_result == 0) - continue; - - if (FD_ISSET(logfd, &rfds)) { - struct knet_log_msg msg; - size_t bytes_read = 0; - size_t len; - - while (bytes_read < sizeof(struct knet_log_msg)) { - len = read(logfd, &msg + bytes_read, - sizeof(struct knet_log_msg) - bytes_read); - if (len <= 0) { - break; - } - bytes_read += len; - } - - if (bytes_read != sizeof(struct knet_log_msg)) - continue; - - switch(msg.msglevel) { - case KNET_LOG_WARN: - log_warn("(%s) %s", knet_log_get_subsystem_name(msg.subsystem), msg.msg); - break; - case KNET_LOG_INFO: - log_info("(%s) %s", knet_log_get_subsystem_name(msg.subsystem), msg.msg); - break; - case KNET_LOG_DEBUG: - log_kdebug("(%s) %s", knet_log_get_subsystem_name(msg.subsystem), msg.msg); - break; - case KNET_LOG_ERR: - default: - log_error("(%s) %s", knet_log_get_subsystem_name(msg.subsystem), msg.msg); - } - } - } - -out: - return NULL; -} - -static int knet_vty_init_listener(const char *ip_addr, const char *port) -{ - int sockfd = -1, sockopt = 1; - int socktype = SOCK_STREAM; - int err = 0; - struct sockaddr_storage ss; - - memset(&ss, 0, sizeof(struct sockaddr_storage)); - - if (knet_strtoaddr(ip_addr, port, &ss, sizeof(struct sockaddr_storage)) != 0) - return -1; - - pthread_mutex_lock(&knet_vty_mutex); - - /* handle sigpipe if we decide to use KEEPALIVE */ - - sockfd = socket(ss.ss_family, socktype, 0); - if (sockfd < 0) { - err = sockfd; - goto out_clean; - } - - if (ss.ss_family == AF_INET6) { - err = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, - (void *)&sockopt, sizeof(sockopt)); - if (err) - goto out_clean; - } - - err = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, - (void *)&sockopt, sizeof(sockopt)); - if (err) - goto out_clean; - - if (_fdset_cloexec(sockfd)) { - err = -1; - goto out_clean; - } - - err = bind(sockfd, (struct sockaddr *)&ss, sizeof(struct sockaddr_storage)); - if (err) - goto out_clean; - - err = listen(sockfd, 0); - if (err) - goto out_clean; - - pthread_mutex_unlock(&knet_vty_mutex); - - return sockfd; - -out_clean: - if (sockfd >= 0) - close(sockfd); - - pthread_mutex_unlock(&knet_vty_mutex); - - return err; -} - -static void knet_vty_close_listener(int listener_fd) -{ - pthread_mutex_lock(&knet_vty_mutex); - - if (listener_fd <= 0) - goto out_clean; - - close(listener_fd); - listener_fd = 0; - -out_clean: - - pthread_mutex_unlock(&knet_vty_mutex); - - return; -} - -static void sigterm_handler(int sig) -{ - daemon_quit = 1; -} - -static void sigpipe_handler(int sig) -{ - return; -} - -static void knet_vty_close(struct knet_vty *vty) -{ - if (knet_vty_config == vty->conn_num) - knet_vty_config = -1; - - knet_vty_free_history(vty); - vty->active = 0; - close(vty->vty_sock); - vty_current_connections--; -} - -static void *vty_accept_thread(void *arg) -{ - struct knet_vty *vty = (struct knet_vty *)&knet_vtys[*(int *)arg]; - char addr_str[KNET_MAX_HOST_LEN]; - char port_str[KNET_MAX_PORT_LEN]; - int err; - - knet_vty_print_banner(vty); - if (vty->got_epipe) - goto out_clean; - - err = knet_addrtostr(&vty->src_sa, vty->src_sa_len, - addr_str, KNET_MAX_HOST_LEN, - port_str, KNET_MAX_PORT_LEN); - - if (!err) { - strncpy(vty->ip, addr_str, sizeof(vty->ip)); - } else { - strcpy(vty->ip, "unknown"); - } - - if ((knet_vty_auth_user(vty, NULL) < 0) && (!vty->got_epipe)) { - log_info("User failed to authenticate (ip: %s)", vty->ip); - goto out_clean; - } - if (vty->got_epipe) - goto out_clean; - - log_info("User %s connected from %s", vty->username, vty->ip); - knet_vty_write(vty, "Welcome %s (%s) on vty(%d)\n\n", vty->username, vty->ip, vty->conn_num); - if (vty->got_epipe) - goto out_clean; - - if (knet_vty_set_iacs(vty) < 0) { - knet_vty_write(vty, "Unable to set telnet session preferences"); - goto out_clean; - } - if (vty->got_epipe) - goto out_clean; - - knet_vty_cli_bind(vty); - -out_clean: - pthread_mutex_lock(&knet_vty_mutex); - knet_vty_close(vty); - pthread_mutex_unlock(&knet_vty_mutex); - - return NULL; -} - -/* - * mainloop is not thread safe as there should only be one - */ -int knet_vty_main_loop(int debug) -{ - int logfd[2]; - int vty_listener6_fd; - int vty_listener4_fd; - int vty_listener_fd; - int vty_accept_fd; - struct sockaddr_storage incoming_sa; - socklen_t salen; - fd_set rfds; - int se_result = 0; - struct timeval tv; - int err = 0; - int conn_index, found; - - signal(SIGTERM, sigterm_handler); - signal(SIGINT, sigterm_handler); - signal(SIGPIPE, sigpipe_handler); - - if (pipe(logfd)) { - log_error("Unable to create logging pipe"); - return -1; - } - - if ((_fdset_cloexec(logfd[0])) || - (_fdset_nonblock(logfd[0])) || - (_fdset_cloexec(logfd[1])) || - (_fdset_nonblock(logfd[1]))) { - log_error("Unable to set FD_CLOEXEX / O_NONBLOCK on logfd pipe"); - return -1; - } - - err = pthread_create(&logging_thread, - NULL, _handle_logging_thread, - (void *)&logfd[0]); - if (err) { - log_error("Unable to create logging thread"); - return -1; - } - - memset(&knet_vtys, 0, sizeof(knet_vtys)); - memset(&vty_global_conf, 0, sizeof(struct knet_vty_global_conf)); - vty_global_conf.idle_timeout = KNET_VTY_CLI_TIMEOUT; - - for(conn_index = 0; conn_index < KNET_VTY_TOTAL_MAX_CONN; conn_index++) { - knet_vtys[conn_index].logfd = logfd[1]; - knet_vtys[conn_index].vty_global_conf = &vty_global_conf; - if (debug) { - knet_vtys[conn_index].loglevel = KNET_LOG_DEBUG; - } else { - knet_vtys[conn_index].loglevel = KNET_LOG_INFO; - } - } - - if (knet_read_conf() < 0) { - log_error("Unable to read config file %s", knet_cfg_head.conffile); - return -1; - } - - vty_listener6_fd = knet_vty_init_listener(knet_cfg_head.vty_ipv6, - knet_cfg_head.vty_port); - if (vty_listener6_fd < 0) { - log_error("Unable to setup vty listener for ipv6"); - return -1; - } - - vty_listener4_fd = knet_vty_init_listener(knet_cfg_head.vty_ipv4, - knet_cfg_head.vty_port); - - if (vty_listener4_fd < 0) { - log_error("Unable to setup vty listener for ipv4"); - goto out; - } - - while (se_result >= 0 && !daemon_quit) { - FD_ZERO (&rfds); - FD_SET (vty_listener6_fd, &rfds); - FD_SET (vty_listener4_fd, &rfds); - - tv.tv_sec = 1; - tv.tv_usec = 0; - - se_result = select(FD_SETSIZE, &rfds, 0, 0, &tv); - - if ((se_result == -1) && (daemon_quit)) { - log_info("Got a SIGTERM, requesting CLI threads to exit"); - for(conn_index = 0; conn_index < KNET_VTY_TOTAL_MAX_CONN; conn_index++) { - if (knet_vtys[conn_index].active) { - knet_vty_write(&knet_vtys[conn_index], "%s%sServer is going down..%s%s", - telnet_newline, telnet_newline, telnet_newline, telnet_newline); - knet_vty_close(&knet_vtys[conn_index]); - knet_vtys[conn_index].got_epipe = 1; - } - } - sleep(2); /* give time to all vty to exit */ - knet_close_down(); - log_info("Have a nice day! Goodbye"); - goto out; - } - - if (se_result == -1) { - err = se_result; - log_error("Unable to select on vty listener socket!"); - goto out; - } - - if (se_result == 0) { - pthread_mutex_lock(&knet_vty_mutex); - for(conn_index = 0; conn_index < KNET_VTY_TOTAL_MAX_CONN; conn_index++) { - if ((knet_vtys[conn_index].active) && - (knet_vtys[conn_index].idle_timeout)) { - knet_vtys[conn_index].idle++; - if (knet_vtys[conn_index].idle > knet_vtys[conn_index].idle_timeout) { - knet_vty_close(&knet_vtys[conn_index]); - knet_vtys[conn_index].got_epipe = 1; - } - } - } - pthread_mutex_unlock(&knet_vty_mutex); - continue; - } - - if (FD_ISSET(vty_listener6_fd, &rfds)) { - vty_listener_fd = vty_listener6_fd; - } else if (FD_ISSET(vty_listener4_fd, &rfds)) { - vty_listener_fd = vty_listener4_fd; - } else { - continue; - } - - memset(&incoming_sa, 0, sizeof(struct sockaddr_storage)); - salen = sizeof(struct sockaddr_storage); - - vty_accept_fd = accept(vty_listener_fd, (struct sockaddr *)&incoming_sa, &salen); - if (vty_accept_fd < 0) { - log_error("Unable to accept connection to vty"); - continue; - } - - // check for ip address access list here against incoming_sa - - pthread_mutex_lock(&knet_vty_mutex); - - found = 0; - for(conn_index = 0; conn_index <= vty_max_connections; conn_index++) { - if (knet_vtys[conn_index].active == 0) { - found = 1; - break; - } - } - - if ((vty_current_connections == vty_max_connections) || (!found)) { - errno = ECONNREFUSED; - log_error("Too many connections to VTY or no available slots"); - close(vty_accept_fd); - pthread_mutex_unlock(&knet_vty_mutex); - continue; - } - - vty_current_connections++; - - memset(&knet_vtys[conn_index], 0, - sizeof(struct knet_vty)); - - knet_vtys[conn_index].vty_sock = vty_accept_fd; - knet_vtys[conn_index].conn_num = conn_index; - memmove(&knet_vtys[conn_index].src_sa, &incoming_sa, salen); - knet_vtys[conn_index].src_sa_len = salen; - knet_vtys[conn_index].active = 1; - knet_vtys[conn_index].logfd = logfd[1]; - knet_vtys[conn_index].vty_global_conf = &vty_global_conf; - knet_vtys[conn_index].idle_timeout = vty_global_conf.idle_timeout; - if (debug) { - knet_vtys[conn_index].loglevel = KNET_LOG_DEBUG; - } else { - knet_vtys[conn_index].loglevel = KNET_LOG_INFO; - } - - err = pthread_create(&knet_vtys[conn_index].vty_thread, - NULL, vty_accept_thread, - (void *)&conn_index); - if (err < 0) { - log_error("Unable to spawn vty thread"); - memset(&knet_vtys[conn_index], 0, - sizeof(struct knet_vty)); - vty_current_connections--; - } - - pthread_mutex_unlock(&knet_vty_mutex); - } - -out: - pthread_cancel(logging_thread); - knet_vty_close_listener(vty_listener6_fd); - knet_vty_close_listener(vty_listener4_fd); - close(logfd[0]); - close(logfd[1]); - - return err; -} - -/* -int knet_vty_set_max_connections(const int max_connections) -{ - int err = 0; - - pthread_mutex_lock(&knet_vty_mutex); - if ((max_connections > KNET_VTY_TOTAL_MAX_CONN) || - (max_connections < 1)) { - errno = EINVAL; - err = -1; - } else { - vty_max_connections = max_connections; - } - pthread_mutex_unlock(&knet_vty_mutex); - return err; -} -*/ diff --git a/kronosnetd/vty.h b/kronosnetd/vty.h deleted file mode 100644 index fadc1f63..00000000 --- a/kronosnetd/vty.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. - * - * Authors: Fabio M. Di Nitto - * Federico Simoncelli - * - * This software licensed under GPL-2.0+ - */ - -#ifndef __KNETD_VTY_H__ -#define __KNETD_VTY_H__ - -#include -#include -#include -#include "libknet.h" - -#define KNET_VTY_DEFAULT_PORT 50000 - -#define KNET_VTY_DEFAULT_MAX_CONN 4 -#define KNET_VTY_TOTAL_MAX_CONN 16 -#define KNET_VTY_CLI_TIMEOUT 300 - -#define KNET_VTY_MAX_LINE 512 - -#define KNET_VTY_MAX_HIST 50 - -struct knet_vty_global_conf { - int idle_timeout; -}; - -struct knet_vty { - pthread_t vty_thread; /* thread struct for this vty */ - struct sockaddr_storage src_sa; /* source IP */ - socklen_t src_sa_len; /* sa len */ - char ip[KNET_MAX_HOST_LEN]; /* ip addr of source */ - char username[64]; /* username */ - char line[KNET_VTY_MAX_LINE]; /* input line */ - char *history[KNET_VTY_MAX_HIST]; /* history */ - int history_idx; /* index to history */ - int history_pos; /* position in the history */ - int insert_mode; /* add or insert */ - int line_idx; /* index on the input line */ - int cursor_pos; /* position of the cursor in the line */ - int escape; /* escape status */ - int escape_code; /* escape code buffer */ - int user_can_enable;/* user is in group kronosnetadm */ - int vty_sock; /* tcp socket for this vty */ - int conn_num; /* vty number */ - int active; /* vty is active */ - int got_epipe; /* vty_sock has been closed */ - int idle; /* idle time */ - int idle_timeout; /* in seconds or 0 to disable automatic logout */ - int node; /* node number of the menus */ - int prevnode; /* node number of the menus (used by VTY node) */ - void *param; /* pointer to cmd param */ - int paramoffset; /* required if param is set */ - int logfd; /* fd to pass to iface create */ - int loglevel; /* loglevel (debug, etc) */ - void *iface; /* pointer to iface we are working on */ - knet_node_id_t host_id; /* peer/host we are working on */ - uint8_t link_id; /* link id we are working on */ - int filemode; /* tell print_conf to add or not carriage return */ - struct knet_vty_global_conf *vty_global_conf; /* pointer to vty global config */ -}; - -extern pthread_mutex_t knet_vty_mutex; -extern int knet_vty_config; - -extern struct knet_vty knet_vtys[KNET_VTY_TOTAL_MAX_CONN]; - -int knet_vty_main_loop(int debug); - -#endif diff --git a/kronosnetd/vty_auth.c b/kronosnetd/vty_auth.c deleted file mode 100644 index d599c377..00000000 --- a/kronosnetd/vty_auth.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. - * - * Author: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+ - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "logging.h" -#include "vty_auth.h" -#include "vty_utils.h" - -static int knet_pam_misc_conv(int num_msg, const struct pam_message **msgm, - struct pam_response **response, void *appdata_ptr) -{ - int count = 0; - struct pam_response *reply; - struct knet_vty *vty = (struct knet_vty *)appdata_ptr; - - if (num_msg <= 0) - return PAM_CONV_ERR; - - reply = (struct pam_response *) calloc(num_msg, sizeof(struct pam_response)); - - if (reply == NULL) - return PAM_CONV_ERR; - - for (count=0; count < num_msg; ++count) { - unsigned char readbuf[VTY_MAX_BUFFER_SIZE]; - char *string=NULL; - int nc; - - memset(readbuf, 0, sizeof(readbuf)); - - switch (msgm[count]->msg_style) { - case PAM_PROMPT_ECHO_OFF: - if (knet_vty_set_echo(vty, 0) < 0) { - knet_vty_write(vty, "Unable to turn off terminal/telnet echo"); - goto failed_conversation; - } - knet_vty_write(vty, "%s", msgm[count]->msg); - nc = knet_vty_read(vty, readbuf, sizeof(readbuf)); - if (nc < 0) - goto failed_conversation; - if (knet_vty_set_echo(vty, 1) < 0) { - /* doesn't really make a lot of sense tho.... */ - knet_vty_write(vty, "Unable to turn on terminal/telnet echo"); - goto failed_conversation; - } - knet_vty_write(vty, "\n"); - readbuf[nc-2] = 0; - string = strdup((const char*)readbuf); - if (!string) - goto failed_conversation; - break; - case PAM_PROMPT_ECHO_ON: - knet_vty_write(vty, "\n%s", msgm[count]->msg); - nc = knet_vty_read(vty, readbuf, sizeof(readbuf)); - if (nc < 0) - goto failed_conversation; - readbuf[nc-2] = 0; - string = strdup((const char*)readbuf); - if (!string) - goto failed_conversation; - break; - case PAM_ERROR_MSG: - log_error("Received PAM error message %s", msgm[count]->msg); - knet_vty_write(vty, "%s", msgm[count]->msg); - break; - case PAM_TEXT_INFO: - log_error("Received PAM text info: %s", msgm[count]->msg); - knet_vty_write(vty, "%s", msgm[count]->msg); - break; - default: - if (!vty->got_epipe) { - log_error("Unknown PAM conversation message"); - knet_vty_write(vty, "Unknown PAM conversation message"); - } - goto failed_conversation; - } - - if (string) { - reply[count].resp_retcode = 0; - reply[count].resp = string; - string = NULL; - } - } - - *response = reply; - reply = NULL; - - return PAM_SUCCESS; - -failed_conversation: - if (!vty->got_epipe) { - log_error("PAM conversation error"); - knet_vty_write(vty, "PAM conversation error"); - } - if (reply) { - for (count=0; count < num_msg; ++count) { - if (reply[count].resp == NULL) - continue; - switch (msgm[count]->msg_style) { - case PAM_PROMPT_ECHO_ON: - case PAM_PROMPT_ECHO_OFF: - _pam_overwrite(reply[count].resp); - free(reply[count].resp); - break; - case PAM_BINARY_PROMPT: - { - void *bt_ptr = reply[count].resp; - pam_binary_handler_free(appdata_ptr, bt_ptr); - break; - } - case PAM_ERROR_MSG: - case PAM_TEXT_INFO: - free(reply[count].resp); - } - } - free(reply); - reply = NULL; - } - - return PAM_CONV_ERR; -} - -static int knet_vty_get_pam_user(struct knet_vty *vty, pam_handle_t *pamh) -{ - const void *value; - int err; - - memset(vty->username, 0, sizeof(vty->username)); - - err = pam_get_item(pamh, PAM_USER, &value); - - if (err != PAM_SUCCESS) - return err; - - strncpy(vty->username, (const char*)value, 32); - - return 0; -} - -static int knet_vty_pam_auth_user(struct knet_vty *vty, const char *user) -{ - pam_handle_t *pamh=NULL; - struct pam_conv conv; - int err; - int retry = 1; - - conv.conv = knet_pam_misc_conv; - conv.appdata_ptr = (void *)vty; - -retry_auth: - err = pam_start("kronosnetd", user, &conv, &pamh); - if (err != PAM_SUCCESS) { - errno = EINVAL; - log_error("PAM fatal error: %s", pam_strerror(pamh, err)); - knet_vty_write(vty, "PAM fatal error: %s", - pam_strerror(pamh, err)); - goto out_fatal; - } - - if (pam_set_item(pamh, PAM_USER_PROMPT, (const void *)"login: ") != PAM_SUCCESS) { - log_error("PAM fatal error: %s", pam_strerror(pamh, err)); - knet_vty_write(vty, "PAM fatal error: %s", - pam_strerror(pamh, err)); - goto out_fatal; - } - - err = pam_authenticate(pamh, 0); - if (err != PAM_SUCCESS) { - if (vty->got_epipe) { - errno = EPIPE; - goto out_fatal; - } else { - errno = EINVAL; - goto out_clean; - } - } - - if (knet_vty_get_pam_user(vty, pamh) != PAM_SUCCESS) { - log_error("PAM: unable to get PAM_USER: %s", - pam_strerror(pamh, err)); - knet_vty_write(vty, "PAM: unable to get PAM_USER: %s", - pam_strerror(pamh, err)); - goto out_clean; - } - - err = pam_acct_mgmt(pamh, 0); - if (err != PAM_SUCCESS) { - log_info("User: %s failed to authenticate on vty(%d) attempt %d", - vty->username, vty->conn_num, retry); - goto out_clean; - } - -out_clean: - if (pamh) { - pam_end(pamh, err); - pamh = NULL; - } - - if ((err != PAM_SUCCESS) && (retry < AUTH_MAX_RETRY)) { - retry++; - goto retry_auth; - } - -out_fatal: - if (pamh) { - pam_end(pamh, err); - pamh = NULL; - } - - knet_vty_write(vty, "\n"); - - return err; -} - -static int knet_vty_group_check(struct knet_vty *vty) -{ - struct group grp; - char *buf; - size_t buflen; - long int initlen; - struct group *result; - char *gr_mem; - int err, i; - - errno = 0; - initlen = sysconf(_SC_GETGR_R_SIZE_MAX); - if ((initlen < 0) && (errno == EINVAL)) - return -1; - - if (initlen < 0) - initlen = 1024; - - buflen = (size_t) initlen; - - buf = malloc(buflen); - if (!buf) - return -1; - - while ((err = getgrnam_r(DEFAULTADMGROUP, &grp, buf, buflen, &result)) == ERANGE) { - size_t newlen = 2 * buflen; - char *newbuf; - - newbuf = realloc(buf, newlen); - if (!newbuf) { - err = -1; - goto out_clean; - } - buf = newbuf; - } - if (err) - goto out_clean; - - if (result == NULL) { - errno = EACCES; - log_error("No " DEFAULTADMGROUP " group found on the system"); - knet_vty_write(vty, "No " DEFAULTADMGROUP " group found on the system\n"); - err = -1; - goto out_clean; - } - - gr_mem = *grp.gr_mem; - - i = 0; - while(gr_mem != NULL) { - if (!strcmp(vty->username, gr_mem)) { - vty->user_can_enable = 1; - break; - } - gr_mem = *(grp.gr_mem + i); - i++; - } - -out_clean: - free(buf); - - return err; -} - -int knet_vty_auth_user(struct knet_vty *vty, const char *user) -{ - int err; - - err = knet_vty_pam_auth_user(vty, user); - if (err != PAM_SUCCESS) - return -1; - - return knet_vty_group_check(vty); -} diff --git a/kronosnetd/vty_auth.h b/kronosnetd/vty_auth.h deleted file mode 100644 index c03c5a60..00000000 --- a/kronosnetd/vty_auth.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. - * - * Author: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+ - */ - -#ifndef __KNETD_VTY_AUTH_H__ -#define __KNETD_VTY_AUTH_H__ - -#include "vty.h" - -#define AUTH_MAX_RETRY 3 - -int knet_vty_auth_user(struct knet_vty *vty, const char *user); - -#endif diff --git a/kronosnetd/vty_cli.c b/kronosnetd/vty_cli.c deleted file mode 100644 index b52039a4..00000000 --- a/kronosnetd/vty_cli.c +++ /dev/null @@ -1,533 +0,0 @@ -/* - * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. - * - * Authors: Fabio M. Di Nitto - * Federico Simoncelli - * - * This software licensed under GPL-2.0+ - */ - -#include "config.h" - -#include -#include -#include -#include - -#include "logging.h" -#include "vty.h" -#include "vty_cli.h" -#include "vty_cli_cmds.h" -#include "vty_utils.h" - -static const char telnet_backward_char[] = { 0x08, 0x0 }; - -/* if this code looks like quagga lib/vty.c it is because we stole it in good part */ - -#define CONTROL(X) ((X) - '@') -#define VTY_NORMAL 0 -#define VTY_PRE_ESCAPE 1 -#define VTY_ESCAPE 2 -#define VTY_EXT_ESCAPE 3 - -static void knet_vty_reset_buf(struct knet_vty *vty) -{ - memset(vty->line, 0, sizeof(vty->line)); - vty->line_idx = 0; - vty->cursor_pos = 0; - vty->history_pos = vty->history_idx; -} - -static void knet_vty_add_to_buf(struct knet_vty *vty, unsigned char *buf, int pos) -{ - char outbuf[2]; - int i; - - if (vty->cursor_pos == vty->line_idx) { - vty->line[vty->line_idx] = buf[pos]; - vty->line_idx++; - vty->cursor_pos++; - } else { - if (!vty->insert_mode) { - memmove(&vty->line[vty->cursor_pos+1], &vty->line[vty->cursor_pos], - vty->line_idx - vty->cursor_pos); - vty->line_idx++; - } - vty->line[vty->cursor_pos] = buf[pos]; - vty->cursor_pos++; - } - - outbuf[0] = buf[pos]; - outbuf[1] = 0; - knet_vty_write(vty, "%s%s", outbuf, &vty->line[vty->cursor_pos]); - for (i = 0; i < (vty->line_idx - vty->cursor_pos); i++) - knet_vty_write(vty, "%s", telnet_backward_char); -} - -static void knet_vty_forward_char(struct knet_vty *vty) -{ - char buf[2]; - - if (vty->cursor_pos < vty->line_idx) { - buf[0] = vty->line[vty->cursor_pos]; - buf[1] = 0; - knet_vty_write(vty, "%s", buf); - vty->cursor_pos++; - } -} - -static void knet_vty_backward_char(struct knet_vty *vty) -{ - if (vty->cursor_pos > 0) { - knet_vty_write(vty, "%s", telnet_backward_char); - vty->cursor_pos--; - } -} - -static void knet_vty_kill_line(struct knet_vty *vty) -{ - int size, i; - - size = vty->line_idx - vty->cursor_pos; - - if (size == 0) - return; - - for (i = 0; i < size; i++) - knet_vty_write(vty, " "); - - for (i = 0; i < size; i++) - knet_vty_write(vty, "%s", telnet_backward_char); - - memset(&vty->line[vty->cursor_pos], 0, size); - vty->line_idx = vty->cursor_pos; -} - -static void knet_vty_newline(struct knet_vty *vty) -{ - knet_vty_write(vty, "%s", telnet_newline); - knet_vty_reset_buf(vty); - knet_vty_prompt(vty); -} - -static void knet_vty_delete_char(struct knet_vty *vty) -{ - int size, i; - - if (vty->line_idx == 0) { - knet_vty_exit_node(vty); - if (!vty->got_epipe) { - knet_vty_newline(vty); - } - return; - } - - if (vty->line_idx == vty->cursor_pos) - return; - - size = vty->line_idx - vty->cursor_pos; - - vty->line_idx--; - memmove(&vty->line[vty->cursor_pos], &vty->line[vty->cursor_pos+1], - size - 1); - vty->line[vty->line_idx] = '\0'; - - knet_vty_write(vty, "%s ", &vty->line[vty->cursor_pos]); - for (i = 0; i < size; i++) - knet_vty_write(vty, "%s", telnet_backward_char); -} - -static void knet_vty_delete_backward_char(struct knet_vty *vty) -{ - if (vty->cursor_pos == 0) - return; - - knet_vty_backward_char(vty); - knet_vty_delete_char(vty); -} - -static void knet_vty_beginning_of_line(struct knet_vty *vty) -{ - while (vty->cursor_pos != 0) - knet_vty_backward_char(vty); -} - -static void knet_vty_end_of_line(struct knet_vty *vty) -{ - while (vty->cursor_pos != vty->line_idx) - knet_vty_forward_char(vty); -} - -static void knet_vty_kill_line_from_beginning(struct knet_vty *vty) -{ - knet_vty_beginning_of_line(vty); - knet_vty_kill_line(vty); -} - -static void knet_vty_backward_word(struct knet_vty *vty) -{ - while(vty->cursor_pos > 0 && vty->line[vty->cursor_pos - 1] == ' ') - knet_vty_backward_char(vty); - - while(vty->cursor_pos > 0 && vty->line[vty->cursor_pos - 1] != ' ') - knet_vty_backward_char(vty); -} - -static void knet_vty_forward_word(struct knet_vty *vty) -{ - while(vty->cursor_pos != vty->line_idx && vty->line[vty->cursor_pos] == ' ') - knet_vty_forward_char(vty); - - while(vty->cursor_pos != vty->line_idx && vty->line[vty->cursor_pos] != ' ') - knet_vty_forward_char(vty); -} - -static void knet_vty_backward_kill_word(struct knet_vty *vty) -{ - while(vty->cursor_pos > 0 && vty->line[vty->cursor_pos - 1] == ' ') - knet_vty_delete_backward_char(vty); - - while(vty->cursor_pos > 0 && vty->line[vty->cursor_pos - 1] != ' ') - knet_vty_delete_backward_char(vty); -} - -static void knet_vty_forward_kill_word(struct knet_vty *vty) -{ - while(vty->cursor_pos != vty->line_idx && vty->line[vty->cursor_pos] == ' ') - knet_vty_delete_char(vty); - - while(vty->cursor_pos != vty->line_idx && vty->line[vty->cursor_pos] != ' ') - knet_vty_delete_backward_char(vty); -} - -static void knet_vty_transpose_chars(struct knet_vty *vty) -{ - unsigned char swap[2]; - - if (vty->line_idx < 2 || vty->cursor_pos < 2) - return; - - swap[0] = vty->line[vty->cursor_pos - 1]; - swap[1] = vty->line[vty->cursor_pos - 2]; - knet_vty_delete_backward_char(vty); - knet_vty_delete_backward_char(vty); - knet_vty_add_to_buf(vty, swap, 0); - knet_vty_add_to_buf(vty, swap, 1); -} - -static void knet_vty_history_add(struct knet_vty *vty) -{ - int idx; - - if (knet_vty_is_line_empty(vty)) - return; - - idx = vty->history_idx % KNET_VTY_MAX_HIST; - - if (vty->history[idx]) { - free(vty->history[idx]); - vty->history[idx] = NULL; - } - - vty->history[idx] = strdup(vty->line); - if (vty->history[idx] == NULL) { - log_error("Not enough memory to add history lines!"); - knet_vty_write(vty, "Not enough memory to add history lines!"); - } - - vty->history_idx++; - - if (vty->history_idx == KNET_VTY_MAX_HIST) - vty->history_idx = 0; - - vty->history_pos = vty->history_idx; -} - -static void knet_vty_history_print(struct knet_vty *vty) -{ - int len; - - knet_vty_kill_line_from_beginning(vty); - - len = strlen(vty->history[vty->history_pos]); - memmove(vty->line, vty->history[vty->history_pos], len); - vty->cursor_pos = vty->line_idx = len; - - knet_vty_write(vty, "%s", vty->line); -} - -static void knet_vty_history_prev(struct knet_vty *vty) -{ - int idx; - - idx = vty->history_pos; - - if (idx == 0) { - idx = KNET_VTY_MAX_HIST - 1; - } else { - idx--; - } - - if (vty->history[idx] == NULL) - return; - - vty->history_pos = idx; - - knet_vty_history_print(vty); -} - -static void knet_vty_history_next(struct knet_vty *vty) -{ - int idx; - - if (vty->history_pos == vty->history_idx) - return; - - idx = vty->history_pos; - - if (idx == (KNET_VTY_MAX_HIST - 1)) { - idx = 0; - } else { - idx++; - } - - if (vty->history[idx] == NULL) { - knet_vty_kill_line_from_beginning(vty); - vty->history_pos = vty->history_idx; - return; - } - - vty->history_pos = idx; - - knet_vty_history_print(vty); -} - -static int knet_vty_process_buf(struct knet_vty *vty, unsigned char *buf, int buflen) -{ - int i; - - if (vty->line_idx >= KNET_VTY_MAX_LINE) - return -1; - - for (i = 0; i < buflen; i++) { - if (vty->escape == VTY_EXT_ESCAPE) { - if (buf[i] != '~') - goto vty_ext_escape_out; - - switch (vty->escape_code) { - case ('1'): - knet_vty_beginning_of_line(vty); - break; - case ('2'): - if (!vty->insert_mode) { - vty->insert_mode = 1; - } else { - vty->insert_mode = 0; - } - break; - case ('3'): - knet_vty_delete_char(vty); - break; - case ('4'): - knet_vty_end_of_line(vty); - break; - case ('5'): - knet_vty_history_prev(vty); - break; - case ('6'): - knet_vty_history_next(vty); - break; - } - -vty_ext_escape_out: - vty->escape = VTY_NORMAL; - continue; - } - - if (vty->escape == VTY_ESCAPE) { - switch (buf[i]) { - case ('A'): - knet_vty_history_prev(vty); - break; - case ('B'): - knet_vty_history_next(vty); - break; - case ('C'): - knet_vty_forward_char(vty); - break; - case ('D'): - knet_vty_backward_char(vty); - break; - case ('H'): - knet_vty_beginning_of_line(vty); - break; - case ('F'): - knet_vty_end_of_line(vty); - break; - case ('1'): - case ('2'): - case ('3'): - case ('4'): - case ('5'): - case ('6'): - vty->escape = VTY_EXT_ESCAPE; - vty->escape_code = buf[i]; - break; - default: - break; - } - - if (vty->escape == VTY_ESCAPE) - vty->escape = VTY_NORMAL; - - continue; - } - - if (vty->escape == VTY_PRE_ESCAPE) { - switch (buf[i]) { - case 'O': - case '[': - vty->escape = VTY_ESCAPE; - break; - case 'b': - vty->escape = VTY_NORMAL; - knet_vty_backward_word(vty); - break; - case 'f': - vty->escape = VTY_NORMAL; - knet_vty_forward_word(vty); - break; - case 'd': - vty->escape = VTY_NORMAL; - knet_vty_forward_kill_word(vty); - break; - case CONTROL('H'): - case 0x7f: - vty->escape = VTY_NORMAL; - knet_vty_backward_kill_word(vty); - break; - default: - break; - } - continue; - } - - switch (buf[i]) { - case CONTROL('A'): - knet_vty_beginning_of_line(vty); - break; - case CONTROL('B'): - knet_vty_backward_char(vty); - break; - case CONTROL('C'): - knet_vty_newline(vty); - break; - case CONTROL('D'): - knet_vty_delete_char(vty); - break; - case CONTROL('E'): - knet_vty_end_of_line(vty); - break; - case CONTROL('F'): - knet_vty_forward_char(vty); - break; - case CONTROL('H'): - case 0x7f: - knet_vty_delete_backward_char(vty); - break; - case CONTROL('K'): - knet_vty_kill_line(vty); - break; - case CONTROL('N'): - knet_vty_history_next(vty); - break; - case CONTROL('P'): - knet_vty_history_prev(vty); - break; - case CONTROL('T'): - knet_vty_transpose_chars(vty); - break; - case CONTROL('U'): - knet_vty_kill_line_from_beginning(vty); - break; - case CONTROL('W'): - knet_vty_backward_kill_word(vty); - break; - case CONTROL('Z'): - vty->node = NODE_CONFIG; - knet_vty_exit_node(vty); - knet_vty_newline(vty); - break; - case '\n': - case '\r': - knet_vty_end_of_line(vty); - knet_vty_write(vty, "%s", telnet_newline); - knet_vty_history_add(vty); - knet_vty_execute_cmd(vty); - knet_vty_reset_buf(vty); - knet_vty_prompt(vty); - break; - case '\t': - knet_vty_end_of_line(vty); - knet_vty_tab_completion(vty); - break; - case '?': - knet_vty_end_of_line(vty); - knet_vty_write(vty, "%s", telnet_newline); - knet_vty_help(vty); - knet_vty_prompt(vty); - knet_vty_write(vty, "%s", vty->line); - break; - case '\033': - vty->escape = VTY_PRE_ESCAPE; - break; - default: - if (buf[i] > 31 && buf[i] < 127) - knet_vty_add_to_buf(vty, buf, i); - break; - } - } - - return 0; -} - -void knet_vty_cli_bind(struct knet_vty *vty) -{ - int se_result = 0; - fd_set rfds; - struct timeval tv; - unsigned char buf[VTY_MAX_BUFFER_SIZE]; - int readlen; - - knet_vty_prompt(vty); - - while (se_result >= 0 && !vty->got_epipe) { - FD_ZERO (&rfds); - FD_SET (vty->vty_sock, &rfds); - - tv.tv_sec = 1; - tv.tv_usec = 0; - - se_result = select((vty->vty_sock + 1), &rfds, 0, 0, &tv); - - if ((se_result == -1) || (vty->got_epipe)) - goto out_clean; - - if ((se_result == 0) || (!FD_ISSET(vty->vty_sock, &rfds))) - continue; - - memset(buf, 0 , sizeof(buf)); - readlen = knet_vty_read(vty, buf, sizeof(buf)); - if (readlen <= 0) - goto out_clean; - - if (knet_vty_process_buf(vty, buf, readlen) < 0) { - knet_vty_write(vty, "\nError processing command: command too long\n"); - knet_vty_reset_buf(vty); - } - } - -out_clean: - - return; -} diff --git a/kronosnetd/vty_cli.h b/kronosnetd/vty_cli.h deleted file mode 100644 index e972162f..00000000 --- a/kronosnetd/vty_cli.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. - * - * Author: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+ - */ - -#ifndef __KNETD_VTY_CLI_H__ -#define __KNETD_VTY_CLI_H__ - -#include "vty.h" - -static const char telnet_newline[] = { '\n', '\r', 0x0 }; - -void knet_vty_cli_bind(struct knet_vty *vty); - -#endif diff --git a/kronosnetd/vty_cli_cmds.c b/kronosnetd/vty_cli_cmds.c deleted file mode 100644 index fabb1601..00000000 --- a/kronosnetd/vty_cli_cmds.c +++ /dev/null @@ -1,2169 +0,0 @@ -/* - * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. - * - * Authors: Fabio M. Di Nitto - * Federico Simoncelli - * - * This software licensed under GPL-2.0+ - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "cfg.h" -#include "etherfilter.h" -#include "logging.h" -#include "libnozzle.h" -#include "netutils.h" -#include "vty.h" -#include "vty_cli.h" -#include "vty_cli_cmds.h" -#include "vty_utils.h" - -#define KNET_VTY_MAX_MATCHES 64 -#define KNET_VTY_MATCH_HELP 0 -#define KNET_VTY_MATCH_EXEC 1 -#define KNET_VTY_MATCH_EXPAND 2 - -#define CMDS_PARAM_NOMORE 0 -#define CMDS_PARAM_KNET 1 -#define CMDS_PARAM_IP 2 -#define CMDS_PARAM_IP_PREFIX 3 -#define CMDS_PARAM_IP_PORT 4 -#define CMDS_PARAM_BOOL 5 -#define CMDS_PARAM_INT 6 -#define CMDS_PARAM_NODEID 7 -#define CMDS_PARAM_NAME 8 -#define CMDS_PARAM_MTU 9 -#define CMDS_PARAM_CRYPTO_MODEL 10 -#define CMDS_PARAM_CRYPTO_TYPE 11 -#define CMDS_PARAM_HASH_TYPE 12 -#define CMDS_PARAM_POLICY 13 -#define CMDS_PARAM_LINK_ID 14 -#define CMDS_PARAM_LINK_PRI 15 -#define CMDS_PARAM_LINK_KEEPAL 16 -#define CMDS_PARAM_LINK_HOLDTI 17 -#define CMDS_PARAM_LINK_PONG 18 -#define CMDS_PARAM_VTY_TIMEOUT 19 -#define CMDS_PARAM_PMTU_FREQ 20 -#define CMDS_PARAM_LINK_TRANSP 21 - -static const char file_newline[] = { '\n', 0x0 }; - -/* - * CLI helper functions - menu/node stuff starts below - */ - - -/* - * return 0 if we find a command in vty->line and cmd/len/no are set - * return -1 if we cannot find a command. no can be trusted. cmd/len would be empty - */ - -static int get_command(struct knet_vty *vty, char **cmd, int *cmdlen, int *cmdoffset, int *no) -{ - int start = 0, idx; - - for (idx = 0; idx < vty->line_idx; idx++) { - if (vty->line[idx] != ' ') - break; - } - - if (!strncmp(&vty->line[idx], "no ", 3)) { - *no = 1; - idx = idx + 3; - - for (; idx < vty->line_idx; idx++) { - if (vty->line[idx] != ' ') - break; - } - } else { - *no = 0; - } - - start = idx; - if (start == vty->line_idx) - return -1; - - *cmd = &vty->line[start]; - *cmdoffset = start; - - for (idx = start; idx < vty->line_idx; idx++) { - if (vty->line[idx] == ' ') - break; - } - - *cmdlen = idx - start; - - return 0; -} - -/* - * still not sure why I need to count backwards... - */ -static void get_n_word_from_end(struct knet_vty *vty, int n, - char **word, int *wlen, int *woffset) -{ - int widx; - int idx, end, start; - - start = end = vty->line_idx; - - for (widx = 0; widx < n; widx++) { - for (idx = start - 1; idx > 0; idx--) { - if (vty->line[idx] != ' ') - break; - } - end = idx; - for (idx = end; idx > 0; idx--) { - if (vty->line[idx-1] == ' ') - break; - } - start = idx; - } - - *wlen = (end - start) + 1; - *word = &vty->line[start]; - *woffset = start; -} - -static int expected_params(const vty_param_t *params) -{ - int idx = 0; - - while(params[idx].param != CMDS_PARAM_NOMORE) - idx++; - - return idx; -} - -static int count_words(struct knet_vty *vty, - int offset) -{ - int idx, widx = 0; - int status = 0; - - for (idx = offset; idx < vty->line_idx; idx++) { - if (vty->line[idx] == ' ') { - status = 0; - continue; - } - if ((vty->line[idx] != ' ') && (!status)) { - widx++; - status = 1; - continue; - } - } - return widx; -} - -static int param_to_int(const char *param, int paramlen) -{ - char buf[KNET_VTY_MAX_LINE]; - - memset(buf, 0, sizeof(buf)); - memmove(buf, param, paramlen); - return atoi(buf); -} - -static int param_to_str(char *buf, int bufsize, const char *param, int paramlen) -{ - if (bufsize < paramlen) - return -1; - - memset(buf, 0, bufsize); - memmove(buf, param, paramlen); - return paramlen; -} - -static const vty_node_cmds_t *get_cmds(struct knet_vty *vty, char **cmd, int *cmdlen, int *cmdoffset) -{ - int no; - const vty_node_cmds_t *cmds = knet_vty_nodes[vty->node].cmds; - - get_command(vty, cmd, cmdlen, cmdoffset, &no); - - if (no) - cmds = knet_vty_nodes[vty->node].no_cmds; - - return cmds; -} - -static int check_param(struct knet_vty *vty, const int paramtype, char *param, int paramlen) -{ - int err = 0; - char buf[KNET_VTY_MAX_LINE]; - int tmp; - - memset(buf, 0, sizeof(buf)); - - switch(paramtype) { - case CMDS_PARAM_NOMORE: - break; - case CMDS_PARAM_KNET: - if (paramlen >= IFNAMSIZ) { - knet_vty_write(vty, "interface name too long%s", telnet_newline); - err = -1; - } - break; - case CMDS_PARAM_IP: - break; - case CMDS_PARAM_IP_PREFIX: - break; - case CMDS_PARAM_IP_PORT: - tmp = param_to_int(param, paramlen); - if ((tmp < 0) || (tmp > 65279)) { - knet_vty_write(vty, "port number must be a value between 0 and 65279%s", telnet_newline); - err = -1; - } - break; - case CMDS_PARAM_BOOL: - break; - case CMDS_PARAM_INT: - break; - case CMDS_PARAM_NODEID: - tmp = param_to_int(param, paramlen); - if ((tmp < 0) || (tmp > 255)) { - knet_vty_write(vty, "node id must be a value between 0 and 255%s", telnet_newline); - err = -1; - } - break; - case CMDS_PARAM_NAME: - if (paramlen >= KNET_MAX_HOST_LEN) { - knet_vty_write(vty, "name cannot exceed %d char in len%s", KNET_MAX_HOST_LEN - 1, telnet_newline); - } - break; - case CMDS_PARAM_MTU: - tmp = param_to_int(param, paramlen); - if ((tmp < 576) || (tmp > 65536)) { - knet_vty_write(vty, "mtu should be a value between 576 and 65536 (note: max value depends on the media)%s", telnet_newline); - err = -1; - } - break; - case CMDS_PARAM_PMTU_FREQ: - tmp = param_to_int(param, paramlen); - if ((tmp < 5) || (tmp > 600)) { - knet_vty_write(vty, "PMTUd frequency should be a value between 5 and 600%s", telnet_newline); - err = -1; - } - break; - case CMDS_PARAM_CRYPTO_MODEL: - param_to_str(buf, KNET_VTY_MAX_LINE, param, paramlen); - if (!strncmp("none", buf, 4)) - break; - if (!strncmp("nss", buf, 3)) - break; - knet_vty_write(vty, "unknown encryption model: %s. Supported: none/nss%s", param, telnet_newline); - err = -1; - break; - case CMDS_PARAM_CRYPTO_TYPE: - param_to_str(buf, KNET_VTY_MAX_LINE, param, paramlen); - if (!strncmp("none", buf, 4)) - break; - if (!strncmp("aes256", buf, 6)) - break; - if (!strncmp("aes192", buf, 6)) - break; - if (!strncmp("aes128", buf, 6)) - break; - if (!strncmp("3des", buf, 4)) - break; - knet_vty_write(vty, "unknown encryption method: %s. Supported: none/aes256/aes192/aes128/3des%s", param, telnet_newline); - err = -1; - break; - case CMDS_PARAM_HASH_TYPE: - param_to_str(buf, KNET_VTY_MAX_LINE, param, paramlen); - if (!strncmp("none", buf, 4)) - break; - if (!strncmp("md5", buf, 3)) - break; - if (!strncmp("sha1", buf, 4)) - break; - if (!strncmp("sha256", buf, 6)) - break; - if (!strncmp("sha384", buf, 6)) - break; - if (!strncmp("sha512", buf, 6)) - break; - knet_vty_write(vty, "unknown hash method: %s. Supported none/md5/sha1/sha256/sha384/sha512%s", param, telnet_newline); - err = -1; - break; - case CMDS_PARAM_POLICY: - param_to_str(buf, KNET_VTY_MAX_LINE, param, paramlen); - if (!strncmp("passive", buf, 7)) - break; - if (!strncmp("active", buf, 6)) - break; - if (!strncmp("round-robin", buf, 11)) - break; - knet_vty_write(vty, "unknown switching policy: %s. Supported passive/active/round-robin%s", param, telnet_newline); - err = -1; - break; - case CMDS_PARAM_LINK_ID: - tmp = param_to_int(param, paramlen); - if ((tmp < 0) || (tmp > 7)) { - knet_vty_write(vty, "link id should be a value between 0 and 7%s", telnet_newline); - err = -1; - } - break; - case CMDS_PARAM_LINK_TRANSP: - param_to_str(buf, KNET_VTY_MAX_LINE, param, paramlen); - if (knet_get_transport_id_by_name(buf) == KNET_MAX_TRANSPORTS) { - knet_vty_write(vty, "link transport is invalid%s", telnet_newline); - err = -1; - } - break; - case CMDS_PARAM_LINK_PRI: - tmp = param_to_int(param, paramlen); - if ((tmp < 0) || (tmp > 255)) { - knet_vty_write(vty, "link priority should be a value between 0 and 256%s", telnet_newline); - err = -1; - } - break; - case CMDS_PARAM_LINK_KEEPAL: - tmp = param_to_int(param, paramlen); - if ((tmp <= 0) || (tmp > 60000)) { - knet_vty_write(vty, "link keepalive should be a value between 0 and 60000 (milliseconds). Default: 1000%s", telnet_newline); - err = -1; - } - break; - case CMDS_PARAM_LINK_HOLDTI: - tmp = param_to_int(param, paramlen); - if ((tmp <= 0) || (tmp > 60000)) { - knet_vty_write(vty, "link holdtimer should be a value between 0 and 60000 (milliseconds). Default: 5000%s", telnet_newline); - err = -1; - } - break; - case CMDS_PARAM_LINK_PONG: - tmp = param_to_int(param, paramlen); - if (tmp < 1) { - knet_vty_write(vty, "pong_count must be a value between 0 and 255%s", telnet_newline); - err = -1; - } - break; - case CMDS_PARAM_VTY_TIMEOUT: - tmp = param_to_int(param, paramlen); - if ((tmp < 0) || (tmp > 3600)) { - knet_vty_write(vty, "vty logout timeout should be a value between 0 (disabled) and 3600 seconds. Default: %d%s", KNET_VTY_CLI_TIMEOUT, telnet_newline); - } - break; - default: - knet_vty_write(vty, "CLI ERROR: unknown parameter type%s", telnet_newline); - err = -1; - break; - } - return err; -} - -static void describe_param(struct knet_vty *vty, const int paramtype) -{ - switch(paramtype) { - case CMDS_PARAM_NOMORE: - knet_vty_write(vty, "no more parameters%s", telnet_newline); - break; - case CMDS_PARAM_KNET: - knet_vty_write(vty, "KNET_IFACE_NAME - interface name (max %d chars) eg: kronosnet0%s", IFNAMSIZ, telnet_newline); - break; - case CMDS_PARAM_IP: - knet_vty_write(vty, "IP address - ipv4 or ipv6 address to add/remove%s", telnet_newline); - break; - case CMDS_PARAM_IP_PREFIX: - knet_vty_write(vty, "IP prefix len (eg. 24, 64)%s", telnet_newline); - break; - case CMDS_PARAM_IP_PORT: - knet_vty_write(vty, "base port (eg: %d) %s", KNET_RING_DEFPORT, telnet_newline); - case CMDS_PARAM_BOOL: - break; - case CMDS_PARAM_INT: - break; - case CMDS_PARAM_NODEID: - knet_vty_write(vty, "NODEID - unique identifier for this interface in this kronos network (value between 0 and 255)%s", telnet_newline); - break; - case CMDS_PARAM_NAME: - knet_vty_write(vty, "NAME - unique name identifier for this entity (max %d chars)%s", KNET_MAX_HOST_LEN - 1, telnet_newline); - break; - case CMDS_PARAM_MTU: - knet_vty_write(vty, "MTU - a value between 576 and 65536 (note: max value depends on the media)%s", telnet_newline); - break; - case CMDS_PARAM_PMTU_FREQ: - knet_vty_write(vty, "PMTUd frequency - a value in seconds between 5 and 600 (default: 5)%s", telnet_newline); - break; - case CMDS_PARAM_CRYPTO_MODEL: - knet_vty_write(vty, "MODEL - define encryption backend: none or nss%s", telnet_newline); - break; - case CMDS_PARAM_CRYPTO_TYPE: - knet_vty_write(vty, "CRYPTO - define packets encryption method: none or aes256%s", telnet_newline); - break; - case CMDS_PARAM_HASH_TYPE: - knet_vty_write(vty, "HASH - define packets hashing method: none/md5/sha1/sha256/sha384/sha512%s", telnet_newline); - break; - case CMDS_PARAM_POLICY: - knet_vty_write(vty, "POLICY - define packets switching policy: passive/active/round-robin%s", telnet_newline); - break; - case CMDS_PARAM_LINK_ID: - knet_vty_write(vty, "LINKID - specify the link identification number (0-7)%s", telnet_newline); - break; - case CMDS_PARAM_LINK_TRANSP: - knet_vty_write(vty, "TRANSPORT - specify the link transport protocol (UDP/SCTP/..)%s", telnet_newline); - break; - case CMDS_PARAM_LINK_PRI: - knet_vty_write(vty, "PRIORITY - specify the link priority for passive switching (0 to 255, default is 0). The higher value is preferred over lower value%s", telnet_newline); - break; - case CMDS_PARAM_LINK_KEEPAL: - knet_vty_write(vty, "KEEPALIVE - specify the keepalive interval for this link (0 to 60000 milliseconds, default is 1000).%s", telnet_newline); - break; - case CMDS_PARAM_LINK_HOLDTI: - knet_vty_write(vty, "HOLDTIME - specify how much time has to pass without connection before a link is considered dead (0 to 60000 milliseconds, default is 5000).%s", telnet_newline); - break; - case CMDS_PARAM_VTY_TIMEOUT: - knet_vty_write(vty, "VTY_TIMEOUT - specify the number of seconds before a session is automatically closed.%s", telnet_newline); - break; - default: /* this should never happen */ - knet_vty_write(vty, "CLI ERROR: unknown parameter type%s", telnet_newline); - break; - } -} - -static void print_help(struct knet_vty *vty, const vty_node_cmds_t *cmds, int idx) -{ - if ((idx < 0) || (cmds == NULL) || (cmds[idx].cmd == NULL)) - return; - - if (cmds[idx].help != NULL) { - knet_vty_write(vty, "%s\t%s%s", - cmds[idx].cmd, - cmds[idx].help, - telnet_newline); - } else { - knet_vty_write(vty, "%s\tNo help available for this command%s", - cmds[idx].cmd, - telnet_newline); - } -} - -static int get_param(struct knet_vty *vty, int wanted_paranum, - char **param, int *paramlen, int *paramoffset) -{ - int eparams, tparams; - const vty_param_t *params = (const vty_param_t *)vty->param; - int paramstart = vty->paramoffset; - - eparams = expected_params(params); - tparams = count_words(vty, paramstart); - - if (tparams > eparams) - return -1; - - if (wanted_paranum == -1) { - get_n_word_from_end(vty, 1, param, paramlen, paramoffset); - return tparams; - } - - if (tparams < wanted_paranum) - return -1; - - get_n_word_from_end(vty, (tparams - wanted_paranum) + 1, param, paramlen, paramoffset); - return tparams - wanted_paranum; -} - - -static int match_command(struct knet_vty *vty, const vty_node_cmds_t *cmds, - char *cmd, int cmdlen, int cmdoffset, int mode) -{ - int idx = 0, found = -1, paramoffset = 0, paramlen = 0, last_param = 0; - char *param = NULL; - int paramstart = cmdlen + cmdoffset; - int matches[KNET_VTY_MAX_MATCHES]; - - memset(&matches, -1, sizeof(matches)); - - while ((cmds[idx].cmd != NULL) && (idx < KNET_VTY_MAX_MATCHES)) { - if (!strncmp(cmds[idx].cmd, cmd, cmdlen)) { - found++; - matches[found] = idx; - } - idx++; - } - - if (idx >= KNET_VTY_MAX_MATCHES) { - knet_vty_write(vty, "Too many matches for this command%s", telnet_newline); - return -1; - } - - if (found < 0) { - knet_vty_write(vty, "There is no such command%s", telnet_newline); - return -1; - } - - switch(mode) { - case KNET_VTY_MATCH_HELP: - if (found == 0) { - if ((cmdoffset <= vty->cursor_pos) && (vty->cursor_pos <= paramstart)) { - print_help(vty, cmds, matches[0]); - break; - } - if (cmds[matches[0]].params != NULL) { - vty->param = (void *)cmds[matches[0]].params; - vty->paramoffset = paramstart; - last_param = get_param(vty, -1, ¶m, ¶mlen, ¶moffset); - - if ((paramoffset <= vty->cursor_pos) && (vty->cursor_pos <= (paramoffset + paramlen))) - last_param--; - - if (last_param >= CMDS_PARAM_NOMORE) { - describe_param(vty, cmds[matches[0]].params[last_param].param); - if (paramoffset > 0) - check_param(vty, cmds[matches[0]].params[last_param].param, param, paramlen); - } - break; - } - } - if (found >= 0) { - idx = 0; - while (matches[idx] >= 0) { - print_help(vty, cmds, matches[idx]); - idx++; - } - } - break; - case KNET_VTY_MATCH_EXEC: - if (found == 0) { - int exec = 0; - if (cmds[matches[0]].params != NULL) { - int eparams, tparams; - - eparams = expected_params(cmds[matches[0]].params); - tparams = count_words(vty, paramstart); - - if (eparams != tparams) { - exec = -1; - idx = 0; - - knet_vty_write(vty, "Parameter required for this command:%s", telnet_newline); - - while(cmds[matches[0]].params[idx].param != CMDS_PARAM_NOMORE) { - describe_param(vty, cmds[matches[0]].params[idx].param); - idx++; - } - break; - } - - idx = 0; - vty->param = (void *)cmds[matches[0]].params; - vty->paramoffset = paramstart; - while(cmds[matches[0]].params[idx].param != CMDS_PARAM_NOMORE) { - get_param(vty, idx + 1, ¶m, ¶mlen, ¶moffset); - if (check_param(vty, cmds[matches[0]].params[idx].param, - param, paramlen) < 0) { - exec = -1; - if (vty->filemode) - return -1; - } - - idx++; - } - } - if (!exec) { - if (cmds[matches[0]].params != NULL) { - vty->param = (void *)cmds[matches[0]].params; - vty->paramoffset = paramstart; - } - if (cmds[matches[0]].func != NULL) { - return cmds[matches[0]].func(vty); - } else { /* this will eventually disappear */ - knet_vty_write(vty, "no fn associated to this command%s", telnet_newline); - } - } - } - if (found > 0) { - knet_vty_write(vty, "Ambiguous command.%s", telnet_newline); - } - break; - case KNET_VTY_MATCH_EXPAND: - if (found == 0) { - int cmdreallen; - - if (vty->cursor_pos > cmdoffset+cmdlen) /* complete param? */ - break; - - cmdreallen = strlen(cmds[matches[0]].cmd); - memset(vty->line + cmdoffset, 0, cmdlen); - memmove(vty->line + cmdoffset, cmds[matches[0]].cmd, cmdreallen); - vty->line[cmdreallen + cmdoffset] = ' '; - vty->line_idx = cmdreallen + cmdoffset + 1; - vty->cursor_pos = cmdreallen + cmdoffset + 1; - } - if (found > 0) { /* add completion to string base root */ - int count = 0; - idx = 0; - while (matches[idx] >= 0) { - knet_vty_write(vty, "%s\t\t", cmds[matches[idx]].cmd); - idx++; - count++; - if (count == 4) { - knet_vty_write(vty, "%s",telnet_newline); - count = 0; - } - } - knet_vty_write(vty, "%s",telnet_newline); - } - break; - default: /* this should never really happen */ - log_info("Unknown match mode"); - break; - } - return found; -} - -/* forward declarations */ - -/* common to almost all nodes */ -static int knet_cmd_logout(struct knet_vty *vty); -static int knet_cmd_who(struct knet_vty *vty); -static int knet_cmd_exit_node(struct knet_vty *vty); -static int knet_cmd_help(struct knet_vty *vty); - -/* root node */ -static int knet_cmd_config(struct knet_vty *vty); - -/* config node */ -static int knet_cmd_interface(struct knet_vty *vty); -static int knet_cmd_no_interface(struct knet_vty *vty); -static int knet_cmd_status(struct knet_vty *vty); -static int knet_cmd_show_conf(struct knet_vty *vty); -static int knet_cmd_write_conf(struct knet_vty *vty); - -/* interface node */ -static int knet_cmd_mtu(struct knet_vty *vty); -static int knet_cmd_no_mtu(struct knet_vty *vty); -static int knet_cmd_ip(struct knet_vty *vty); -static int knet_cmd_no_ip(struct knet_vty *vty); -static int knet_cmd_peer(struct knet_vty *vty); -static int knet_cmd_no_peer(struct knet_vty *vty); -static int knet_cmd_start(struct knet_vty *vty); -static int knet_cmd_stop(struct knet_vty *vty); -static int knet_cmd_crypto(struct knet_vty *vty); -static int knet_cmd_pmtufreq(struct knet_vty *vty); -static int knet_cmd_no_pmtufreq(struct knet_vty *vty); - - -/* peer node */ -static int knet_cmd_link(struct knet_vty *vty); -static int knet_cmd_no_link(struct knet_vty *vty); -static int knet_cmd_switch_policy(struct knet_vty *vty); - -/* link node */ -static int knet_cmd_link_pri(struct knet_vty *vty); -static int knet_cmd_link_pong(struct knet_vty *vty); -static int knet_cmd_link_timer(struct knet_vty *vty); - -/* vty node */ -static int knet_cmd_vty(struct knet_vty *vty); -static int knet_cmd_vty_timeout(struct knet_vty *vty); - -/* root node description */ -vty_node_cmds_t root_cmds[] = { - { "configure", "enter configuration mode", NULL, knet_cmd_config }, - { "exit", "exit from CLI", NULL, knet_cmd_logout }, - { "help", "display basic help", NULL, knet_cmd_help }, - { "logout", "exit from CLI", NULL, knet_cmd_logout }, - { "status", "display current network status", NULL, knet_cmd_status }, - { "vty", "enter vty configuration mode", NULL, knet_cmd_vty }, - { "who", "display users connected to CLI", NULL, knet_cmd_who }, - { NULL, NULL, NULL, NULL }, -}; - -/* config node description */ -vty_param_t no_int_params[] = { - { CMDS_PARAM_KNET }, - { CMDS_PARAM_NOMORE }, -}; - -vty_node_cmds_t no_config_cmds[] = { - { "interface", "destroy kronosnet interface", no_int_params, knet_cmd_no_interface }, - { NULL, NULL, NULL, NULL }, -}; - -vty_param_t int_params[] = { - { CMDS_PARAM_KNET }, - { CMDS_PARAM_NODEID }, - { CMDS_PARAM_IP_PORT }, - { CMDS_PARAM_NOMORE }, -}; - -vty_node_cmds_t config_cmds[] = { - { "exit", "exit configuration mode", NULL, knet_cmd_exit_node }, - { "interface", "configure kronosnet interface", int_params, knet_cmd_interface }, - { "show", "show running config", NULL, knet_cmd_show_conf }, - { "help", "display basic help", NULL, knet_cmd_help }, - { "logout", "exit from CLI", NULL, knet_cmd_logout }, - { "no", "revert command", NULL, NULL }, - { "status", "display current network status", NULL, knet_cmd_status }, - { "vty", "enter vty configuration mode", NULL, knet_cmd_vty }, - { "who", "display users connected to CLI", NULL, knet_cmd_who }, - { "write", "write current config to file", NULL, knet_cmd_write_conf }, - { NULL, NULL, NULL, NULL }, -}; - -/* interface node description */ - -vty_param_t ip_params[] = { - { CMDS_PARAM_IP }, - { CMDS_PARAM_IP_PREFIX }, - { CMDS_PARAM_NOMORE }, -}; - -vty_param_t peer_params[] = { - { CMDS_PARAM_NAME }, - { CMDS_PARAM_NODEID }, - { CMDS_PARAM_NOMORE }, -}; - -vty_node_cmds_t no_interface_cmds[] = { - { "ip", "remove ip address", ip_params, knet_cmd_no_ip }, - { "mtu", "revert to default MTU", NULL, knet_cmd_no_mtu }, - { "pmtudfreq", "revert to default PMTUd frequency (default: 5)", NULL, knet_cmd_no_pmtufreq }, - { "peer", "remove peer from this interface", peer_params, knet_cmd_no_peer }, - { NULL, NULL, NULL, NULL }, -}; - -vty_param_t mtu_params[] = { - { CMDS_PARAM_MTU }, - { CMDS_PARAM_NOMORE }, -}; - -vty_param_t pmtu_params[] = { - { CMDS_PARAM_PMTU_FREQ }, - { CMDS_PARAM_NOMORE }, -}; - -vty_param_t crypto_params[] = { - { CMDS_PARAM_CRYPTO_MODEL }, - { CMDS_PARAM_CRYPTO_TYPE }, - { CMDS_PARAM_HASH_TYPE }, - { CMDS_PARAM_NOMORE }, -}; - -vty_node_cmds_t interface_cmds[] = { - { "crypto", "enable crypto/hmac", crypto_params, knet_cmd_crypto }, - { "exit", "exit configuration mode", NULL, knet_cmd_exit_node }, - { "help", "display basic help", NULL, knet_cmd_help }, - { "ip", "add ip address", ip_params, knet_cmd_ip }, - { "logout", "exit from CLI", NULL, knet_cmd_logout }, - { "mtu", "set mtu (default: auto)", mtu_params, knet_cmd_mtu }, - { "pmtudfreq", "PMTUd frequency (default: 5)", pmtu_params, knet_cmd_pmtufreq }, - { "no", "revert command", NULL, NULL }, - { "peer", "add peer endpoint", peer_params, knet_cmd_peer }, - { "show", "show running config", NULL, knet_cmd_show_conf }, - { "start", "start forwarding engine", NULL, knet_cmd_start }, - { "status", "display current network status", NULL, knet_cmd_status }, - { "stop", "stop forwarding engine", NULL, knet_cmd_stop }, - { "who", "display users connected to CLI", NULL, knet_cmd_who }, - { "write", "write current config to file", NULL, knet_cmd_write_conf }, - { NULL, NULL, NULL, NULL }, -}; - -/* peer node description */ - -vty_param_t nolink_params[] = { - { CMDS_PARAM_LINK_ID }, - { CMDS_PARAM_NOMORE }, -}; - -vty_param_t link_params[] = { - { CMDS_PARAM_LINK_ID }, - { CMDS_PARAM_IP }, - { CMDS_PARAM_IP }, - { CMDS_PARAM_LINK_TRANSP }, - { CMDS_PARAM_NOMORE }, -}; - -vty_param_t switch_params[] = { - { CMDS_PARAM_POLICY }, - { CMDS_PARAM_NOMORE }, -}; - -vty_node_cmds_t no_peer_cmds[] = { - { "link", "remove peer endpoint", nolink_params, knet_cmd_no_link}, - { NULL, NULL, NULL, NULL }, -}; - -vty_node_cmds_t peer_cmds[] = { - { "exit", "exit configuration mode", NULL, knet_cmd_exit_node }, - { "help", "display basic help", NULL, knet_cmd_help }, - { "link", "add peer endpoint", link_params, knet_cmd_link }, - { "logout", "exit from CLI", NULL, knet_cmd_logout }, - { "no", "revert command", NULL, NULL }, - { "show", "show running config", NULL, knet_cmd_show_conf }, - { "status", "display current network status", NULL, knet_cmd_status }, - { "switch-policy", "configure switching policy engine", switch_params, knet_cmd_switch_policy }, - { "who", "display users connected to CLI", NULL, knet_cmd_who }, - { "write", "write current config to file", NULL, knet_cmd_write_conf }, - { NULL, NULL, NULL, NULL }, -}; - -/* link node description */ - -vty_param_t link_pri_params[] = { - { CMDS_PARAM_LINK_PRI }, - { CMDS_PARAM_NOMORE }, -}; - -vty_param_t link_timer_params[] = { - { CMDS_PARAM_LINK_KEEPAL }, - { CMDS_PARAM_LINK_HOLDTI }, - { CMDS_PARAM_NOMORE }, -}; - -vty_param_t pong_count_params[] = { - { CMDS_PARAM_LINK_PONG }, - { CMDS_PARAM_NOMORE }, -}; - -vty_node_cmds_t link_cmds[] = { - { "exit", "exit configuration mode", NULL, knet_cmd_exit_node }, - { "help", "display basic help", NULL, knet_cmd_help }, - { "logout", "exit from CLI", NULL, knet_cmd_logout }, - { "no", "revert command", NULL, NULL }, - { "pong_count", "set number of pongs to be received before a link is considered alive", pong_count_params, knet_cmd_link_pong }, - { "priority", "set priority of this link for passive switching", link_pri_params, knet_cmd_link_pri }, - { "show", "show running config", NULL, knet_cmd_show_conf }, - { "status", "display current network status", NULL, knet_cmd_status }, - { "timers", "set link keepalive and holdtime", link_timer_params, knet_cmd_link_timer }, - { "who", "display users connected to CLI", NULL, knet_cmd_who }, - { "write", "write current config to file", NULL, knet_cmd_write_conf }, - { NULL, NULL, NULL, NULL }, -}; - -vty_param_t vty_timeout_params[] = { - { CMDS_PARAM_VTY_TIMEOUT }, - { CMDS_PARAM_NOMORE }, -}; - -vty_node_cmds_t vty_cmds[] = { - { "exit", "exit configuration mode", NULL, knet_cmd_exit_node }, - { "help", "display basic help", NULL, knet_cmd_help }, - { "logout", "exit from CLI", NULL, knet_cmd_logout }, - { "show", "show running config", NULL, knet_cmd_show_conf }, - { "status", "display current network status", NULL, knet_cmd_status }, - { "timeout", "set number of seconds before session is automatically closed", vty_timeout_params, knet_cmd_vty_timeout }, - { "who", "display users connected to CLI", NULL, knet_cmd_who }, - { "write", "write current config to file", NULL, knet_cmd_write_conf }, - { NULL, NULL, NULL, NULL }, -}; - -/* nodes */ -vty_nodes_t knet_vty_nodes[] = { - { NODE_ROOT, "knet", root_cmds, NULL }, - { NODE_CONFIG, "config", config_cmds, no_config_cmds }, - { NODE_INTERFACE, "iface", interface_cmds, no_interface_cmds }, - { NODE_PEER, "peer", peer_cmds, no_peer_cmds }, - { NODE_LINK, "link", link_cmds, NULL }, - { NODE_VTY, "vty", vty_cmds, NULL }, - { -1, NULL, NULL, NULL }, -}; - -/* command execution */ - -/* vty */ -static int knet_cmd_vty_timeout(struct knet_vty *vty) -{ - int paramlen = 0, paramoffset = 0, timeout; - char *param = NULL; - - get_param(vty, 1, ¶m, ¶mlen, ¶moffset); - timeout = param_to_int(param, paramlen); - - if ((vty->filemode) || (vty->prevnode == NODE_CONFIG)) { - vty->vty_global_conf->idle_timeout = timeout; - } - vty->idle_timeout = timeout; - - return 0; -} - -static int knet_cmd_vty(struct knet_vty *vty) -{ - vty->prevnode = vty->node; - vty->node = NODE_VTY; - return 0; -} - -/* links */ - -static int knet_cmd_link_pong(struct knet_vty *vty) -{ - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - int paramlen = 0, paramoffset = 0; - char *param = NULL; - uint8_t pong_count; - - get_param(vty, 1, ¶m, ¶mlen, ¶moffset); - pong_count = param_to_int(param, paramlen); - - knet_link_set_pong_count(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, pong_count); - - return 0; -} - -static int knet_cmd_link_timer(struct knet_vty *vty) -{ - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - int paramlen = 0, paramoffset = 0; - char *param = NULL; - time_t keepalive, holdtime; - - get_param(vty, 1, ¶m, ¶mlen, ¶moffset); - keepalive = param_to_int(param, paramlen); - - get_param(vty, 2, ¶m, ¶mlen, ¶moffset); - holdtime = param_to_int(param, paramlen); - - knet_link_set_ping_timers(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, keepalive, holdtime, 2048); - - return 0; -} - -static int knet_cmd_link_pri(struct knet_vty *vty) -{ - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - int paramlen = 0, paramoffset = 0; - char *param = NULL; - uint8_t priority; - - get_param(vty, 1, ¶m, ¶mlen, ¶moffset); - priority = param_to_int(param, paramlen); - - if (knet_link_set_priority(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, priority)) { - knet_vty_write(vty, "Error: unable to update link priority%s", telnet_newline); - return -1; - } - - return 0; -} - -static int knet_cmd_no_link(struct knet_vty *vty) -{ - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - struct knet_link_status status; - int paramlen = 0, paramoffset = 0; - char *param = NULL; - - get_param(vty, 1, ¶m, ¶mlen, ¶moffset); - vty->link_id = param_to_int(param, paramlen); - - knet_link_get_status(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, &status, sizeof(status)); - - if (status.enabled) { - if (knet_link_set_enable(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, 0)) { - knet_vty_write(vty, "Error: unable to update switching cache%s", telnet_newline); - return -1; - } - knet_link_clear_config(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id); - } - - return 0; -} - -static int knet_cmd_link(struct knet_vty *vty) -{ - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - struct knet_link_status status; - int paramlen = 0, paramoffset = 0, err = 0; - char *param = NULL; - char src_ipaddr[KNET_MAX_HOST_LEN], src_port[KNET_MAX_PORT_LEN], dst_ipaddr[KNET_MAX_HOST_LEN], dst_port[KNET_MAX_PORT_LEN]; - struct sockaddr_storage src_addr; - struct sockaddr_storage dst_addr; - struct sockaddr_storage *dst = NULL; - char transport[10]; - uint8_t transport_id; - - get_param(vty, 1, ¶m, ¶mlen, ¶moffset); - vty->link_id = param_to_int(param, paramlen); - - get_param(vty, 2, ¶m, ¶mlen, ¶moffset); - param_to_str(src_ipaddr, KNET_MAX_HOST_LEN, param, paramlen); - - memset(src_port, 0, sizeof(src_port)); - snprintf(src_port, KNET_MAX_PORT_LEN, "%d", knet_iface->cfg_ring.base_port + vty->host_id); - - get_param(vty, 3, ¶m, ¶mlen, ¶moffset); - param_to_str(dst_ipaddr, KNET_MAX_HOST_LEN, param, paramlen); - - memset(dst_port, 0, sizeof(dst_port)); - snprintf(dst_port, KNET_MAX_PORT_LEN, "%d", knet_iface->cfg_ring.base_port + knet_iface->cfg_eth.node_id); - - get_param(vty, 4, ¶m, ¶mlen, ¶moffset); - param_to_str(transport, sizeof(transport), param, paramlen); - - transport_id = knet_get_transport_id_by_name(transport); - - knet_link_get_status(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, &status, sizeof(status)); - if (!status.enabled) { - if (knet_strtoaddr(src_ipaddr, src_port, &src_addr, sizeof(struct sockaddr_storage)) != 0) { - knet_vty_write(vty, "Error: unable to convert source ip addr to sockaddr!%s", telnet_newline); - err = -1; - goto out_clean; - } - - if (!strncmp(dst_ipaddr, "dynamic", 7)) { - dst = NULL; - } else { - if (knet_strtoaddr(dst_ipaddr, dst_port, &dst_addr, sizeof(struct sockaddr_storage)) != 0) { - knet_vty_write(vty, "Error: unable to convert destination ip addr to sockaddr!%s", telnet_newline); - err = -1; - goto out_clean; - } - dst = &dst_addr; - } - - knet_link_set_config(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, transport_id, &src_addr, dst, KNET_LINK_FLAG_TRAFFICHIPRIO); - - knet_link_set_ping_timers(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, 1000, 5000, 2048); - - knet_link_set_enable(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, 1); - } - - vty->node = NODE_LINK; - -out_clean: - return err; -} - -static int knet_cmd_switch_policy(struct knet_vty *vty) -{ - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - int paramlen = 0, paramoffset = 0, err = 0; - char *param = NULL; - char policystr[16]; - int policy = -1; - - get_param(vty, 1, ¶m, ¶mlen, ¶moffset); - param_to_str(policystr, sizeof(policystr), param, paramlen); - - if (!strncmp("passive", policystr, 7)) - policy = KNET_LINK_POLICY_PASSIVE; - if (!strncmp("active", policystr, 6)) - policy = KNET_LINK_POLICY_ACTIVE; - if (!strncmp("round-robin", policystr, 11)) - policy = KNET_LINK_POLICY_RR; - - if (policy < 0) { - knet_vty_write(vty, "Error: unknown switching policy method%s", telnet_newline); - return -1; - } - - err = knet_host_set_policy(knet_iface->cfg_ring.knet_h, vty->host_id, policy); - if (err) - knet_vty_write(vty, "Error: unable to set switching policy to %s%s", policystr, telnet_newline); - - return err; -} - -/* - * -1 on internal error - * 0 host does not exist - * 1 host exists - */ -static int knet_find_host(struct knet_vty *vty, const char *nodename, const knet_node_id_t requested_node_id) -{ - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - int have_nodeid, have_name; - knet_node_id_t node_id; - char name[KNET_MAX_HOST_LEN]; - - have_nodeid = knet_host_get_id_by_host_name(knet_iface->cfg_ring.knet_h, nodename, &node_id); - have_name = knet_host_get_name_by_host_id(knet_iface->cfg_ring.knet_h, requested_node_id, name); - - /* - * host does not exist without a name - */ - if (have_name < 0) { - return 0; - } - - /* - * internal error.. get out - */ - if (have_nodeid < 0) { - knet_vty_write(vty, "Error: unable to query libknet for nodeid info%s", telnet_newline); - return -1; - } - - if ((!have_name) && (!have_nodeid)) { - if (!strcmp(name, nodename) && (node_id == requested_node_id)) - return 1; - } - - knet_vty_write(vty, "Error: requested nodename or id already exists in libknet%s", telnet_newline); - - return -1; -} - -static int knet_cmd_no_peer(struct knet_vty *vty) -{ - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - int paramlen = 0, paramoffset = 0, requested_node_id = 0, err = 0; - char *param = NULL; - char nodename[KNET_MAX_HOST_LEN]; - - get_param(vty, 1, ¶m, ¶mlen, ¶moffset); - param_to_str(nodename, sizeof(nodename), param, paramlen); - - get_param(vty, 2, ¶m, ¶mlen, ¶moffset); - requested_node_id = param_to_int(param, paramlen); - - if (requested_node_id == knet_iface->cfg_eth.node_id) { - knet_vty_write(vty, "Error: remote peer id cannot be the same as local id%s", telnet_newline); - return -1; - } - - err = knet_find_host(vty, nodename, requested_node_id); - if (err < 0) - goto out_clean; - - if (err != 1) { - knet_vty_write(vty, "Error: peer not found in list%s", telnet_newline); - goto out_clean; - } - - err = knet_host_remove(knet_iface->cfg_ring.knet_h, requested_node_id); - if (err < 0) { - knet_vty_write(vty, "Error: unable to remove peer from current config%s", telnet_newline); - goto out_clean; - } - -out_clean: - return err; -} - -static int knet_cmd_peer(struct knet_vty *vty) -{ - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - int paramlen = 0, paramoffset = 0, requested_node_id = 0, err = 0, host = 0; - char *param = NULL; - char nodename[KNET_MAX_HOST_LEN]; - - get_param(vty, 1, ¶m, ¶mlen, ¶moffset); - param_to_str(nodename, sizeof(nodename), param, paramlen); - - get_param(vty, 2, ¶m, ¶mlen, ¶moffset); - requested_node_id = param_to_int(param, paramlen); - - if (requested_node_id == knet_iface->cfg_eth.node_id) { - knet_vty_write(vty, "Error: remote peer id cannot be the same as local id%s", telnet_newline); - return -1; - } - - err = knet_find_host(vty, nodename, requested_node_id); - if (err < 0) - goto out_clean; - - if (err == 0) { - err = knet_host_add(knet_iface->cfg_ring.knet_h, requested_node_id); - if (err < 0) { - knet_vty_write(vty, "Error: unable to allocate memory for host struct!%s", telnet_newline); - goto out_clean; - } - host = 1; - knet_host_set_name(knet_iface->cfg_ring.knet_h, requested_node_id, nodename); - knet_host_set_policy(knet_iface->cfg_ring.knet_h, requested_node_id, KNET_LINK_POLICY_PASSIVE); - } - - vty->host_id = requested_node_id; - vty->node = NODE_PEER; - -out_clean: - if (err < 0) { - if (host) - knet_host_remove(knet_iface->cfg_ring.knet_h, requested_node_id); - } - - return err; -} - -static int knet_cmd_no_ip(struct knet_vty *vty) -{ - int paramlen = 0, paramoffset = 0; - char *param = NULL; - char ipaddr[KNET_MAX_HOST_LEN], prefix[4]; - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - - get_param(vty, 1, ¶m, ¶mlen, ¶moffset); - param_to_str(ipaddr, sizeof(ipaddr), param, paramlen); - - get_param(vty, 2, ¶m, ¶mlen, ¶moffset); - param_to_str(prefix, sizeof(prefix), param, paramlen); - - if (nozzle_del_ip(knet_iface->cfg_eth.nozzle, ipaddr, prefix) < 0) { - knet_vty_write(vty, "Error: Unable to del ip addr %s/%s on device %s%s", - ipaddr, prefix, nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle), telnet_newline); - return -1; - } - - return 0; -} - -static int knet_cmd_ip(struct knet_vty *vty) -{ - int paramlen = 0, paramoffset = 0; - char *param = NULL; - char ipaddr[512], prefix[4]; - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - - get_param(vty, 1, ¶m, ¶mlen, ¶moffset); - param_to_str(ipaddr, sizeof(ipaddr), param, paramlen); - - get_param(vty, 2, ¶m, ¶mlen, ¶moffset); - param_to_str(prefix, sizeof(prefix), param, paramlen); - - if (nozzle_add_ip(knet_iface->cfg_eth.nozzle, ipaddr, prefix) < 0) { - knet_vty_write(vty, "Error: Unable to set ip addr %s/%s on device %s%s", - ipaddr, prefix, nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle), telnet_newline); - return -1; - } - - return 0; -} - -static void knet_cmd_auto_mtu_notify(void *private_data, - unsigned int data_mtu) -{ - struct knet_cfg *knet_iface = (struct knet_cfg *)private_data; - - /* - * 48 is the magic number! yes it is.. it's the magic number... - */ - knet_iface->cfg_ring.data_mtu = data_mtu - 48; - - if (!knet_iface->cfg_eth.auto_mtu) { - int mtu = 0; - - mtu = nozzle_get_mtu(knet_iface->cfg_eth.nozzle); - if (mtu < 0) { - log_debug("Unable to get current MTU?"); - } else { - if (data_mtu < (unsigned int)mtu) { - log_debug("Manually configured MTU (%d) is higher than automatically detected MTU (%d)", - mtu, data_mtu); - } - } - - return; - } - - if (nozzle_set_mtu(knet_iface->cfg_eth.nozzle, knet_iface->cfg_ring.data_mtu) < 0) { - log_warn("Error: Unable to set requested mtu %d on device %s via mtu notify", - knet_iface->cfg_ring.data_mtu, nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle)); - } else { - log_info("Device %s new mtu: %d (via mtu notify)", - nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle), knet_iface->cfg_ring.data_mtu); - } -} - -static int knet_cmd_no_pmtufreq(struct knet_vty *vty) -{ - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - - if (knet_handle_pmtud_setfreq(knet_iface->cfg_ring.knet_h, 5) < 0) { - knet_vty_write(vty, "Error: Unable to reset PMTUd frequency to 5 seconds on device %s%s", - nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle), telnet_newline); - return -1; - } - - return 0; -} - -static int knet_cmd_pmtufreq(struct knet_vty *vty) -{ - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - int paramlen = 0, paramoffset = 0, pmtufreq = 5; - char *param = NULL; - - get_param(vty, 1, ¶m, ¶mlen, ¶moffset); - pmtufreq = param_to_int(param, paramlen); - - if (knet_handle_pmtud_setfreq(knet_iface->cfg_ring.knet_h, pmtufreq) < 0) { - knet_vty_write(vty, "Error: Unable to set PMTUd frequency to %d seconds on device %s%s", - pmtufreq, nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle), telnet_newline); - return -1; - } - - return 0; -} - -static int knet_cmd_no_mtu(struct knet_vty *vty) -{ - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - - /* allow automatic updates of mtu */ - knet_iface->cfg_eth.auto_mtu = 1; - - if (knet_iface->cfg_ring.data_mtu > 0) { - if (nozzle_set_mtu(knet_iface->cfg_eth.nozzle, knet_iface->cfg_ring.data_mtu) < 0) { - knet_iface->cfg_eth.auto_mtu = 0; - knet_vty_write(vty, "Error: Unable to set auto detected mtu on device %s%s", - nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle), telnet_newline); - return -1; - } - } else { - if (nozzle_reset_mtu(knet_iface->cfg_eth.nozzle) < 0) { - knet_iface->cfg_eth.auto_mtu = 0; - knet_vty_write(vty, "Error: Unable to reset mtu on device %s%s", - nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle), telnet_newline); - return -1; - } - } - - return 0; -} - -static int knet_cmd_mtu(struct knet_vty *vty) -{ - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - int paramlen = 0, paramoffset = 0, expected_mtu = 0; - char *param = NULL; - - get_param(vty, 1, ¶m, ¶mlen, ¶moffset); - expected_mtu = param_to_int(param, paramlen); - - /* disable mtu auto updates */ - knet_iface->cfg_eth.auto_mtu = 0; - - if ((knet_iface->cfg_ring.data_mtu) && - (expected_mtu > knet_iface->cfg_ring.data_mtu)) { - knet_vty_write(vty, "WARNING: Manually configured MTU (%d) is higher than automatically detected MTU (%d)%s", - expected_mtu, knet_iface->cfg_ring.data_mtu, telnet_newline); - } - - if (nozzle_set_mtu(knet_iface->cfg_eth.nozzle, expected_mtu) < 0) { - knet_iface->cfg_eth.auto_mtu = 1; - knet_vty_write(vty, "Error: Unable to set requested mtu %d on device %s%s", - expected_mtu, nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle), telnet_newline); - return -1; - } - - return 0; -} - -static int knet_cmd_stop(struct knet_vty *vty) -{ - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - char *exec_str = NULL; - int err = 0; - - err = nozzle_run_updown(knet_iface->cfg_eth.nozzle, NOZZLE_DOWN, &exec_str); - if (err) { - knet_vty_write(vty, "Non-fatal Error: Unable to execute down.d script for interface %s: %s!%s", nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle), exec_str, telnet_newline); - if (exec_str) { - free(exec_str); - exec_str = NULL; - } - } - - err = nozzle_set_down(knet_iface->cfg_eth.nozzle); - if (err < 0) { - knet_vty_write(vty, "Error: Unable to set interface %s down!%s", nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle), telnet_newline); - } else { - if (knet_iface->cfg_ring.knet_h) - knet_handle_setfwd(knet_iface->cfg_ring.knet_h, 0); - knet_iface->active = 0; - } - - err = nozzle_run_updown(knet_iface->cfg_eth.nozzle, NOZZLE_POSTDOWN, &exec_str); - if (err) { - knet_vty_write(vty, "Non-fatal Error: Unable to execute post-down.d script for interface %s: %s!%s", nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle), exec_str, telnet_newline); - if (exec_str) { - free(exec_str); - exec_str = NULL; - } - } - - return err; -} - -static int knet_cmd_crypto(struct knet_vty *vty) -{ - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - int paramlen = 0, paramoffset = 0; - char *param = NULL; - int err = 0; - struct knet_handle_crypto_cfg knet_handle_crypto_cfg_new; - int fd = -1; - char keyfile[PATH_MAX]; - struct stat sb; - - if (knet_iface->active) { - knet_vty_write(vty, "Error: Unable to activate encryption while interface is active%s", telnet_newline); - return -1; - } - - memset(&knet_handle_crypto_cfg_new, 0, sizeof(struct knet_handle_crypto_cfg)); - - get_param(vty, 1, ¶m, ¶mlen, ¶moffset); - param_to_str(knet_handle_crypto_cfg_new.crypto_model, - sizeof(knet_handle_crypto_cfg_new.crypto_model), param, paramlen); - - get_param(vty, 2, ¶m, ¶mlen, ¶moffset); - param_to_str(knet_handle_crypto_cfg_new.crypto_cipher_type, - sizeof(knet_handle_crypto_cfg_new.crypto_cipher_type), param, paramlen); - - get_param(vty, 3, ¶m, ¶mlen, ¶moffset); - param_to_str(knet_handle_crypto_cfg_new.crypto_hash_type, - sizeof(knet_handle_crypto_cfg_new.crypto_hash_type), param, paramlen); - - if ((!strncmp("none", knet_handle_crypto_cfg_new.crypto_model, 4)) || - ((!strncmp("none", knet_handle_crypto_cfg_new.crypto_cipher_type, 4)) && - ((!strncmp("none", knet_handle_crypto_cfg_new.crypto_hash_type, 4))))) - goto no_key; - - memset(keyfile, 0, PATH_MAX); - snprintf(keyfile, PATH_MAX - 1, DEFAULT_CONFIG_DIR "/cryptokeys.d/%s", nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle)); - - fd = open(keyfile, O_RDONLY); - if (fd < 0) { - knet_vty_write(vty, "Error: Unable to open security key: %s%s", keyfile, telnet_newline); - err = -1; - return -1; - } - - if (fstat(fd, &sb)) { - knet_vty_write(vty, "Error: Unable to verify security key: %s%s", keyfile, telnet_newline); - goto key_error; - } - - if (!S_ISREG(sb.st_mode)) { - knet_vty_write(vty, "Error: Key %s does not appear to be a regular file%s", - keyfile, telnet_newline); - goto key_error; - } - - knet_handle_crypto_cfg_new.private_key_len = (unsigned int)sb.st_size; - if ((knet_handle_crypto_cfg_new.private_key_len < KNET_MIN_KEY_LEN) || - (knet_handle_crypto_cfg_new.private_key_len > KNET_MAX_KEY_LEN)) { - knet_vty_write(vty, "Error: Key %s is %u long. Must be %d <= key_len <= %d%s", - keyfile, knet_handle_crypto_cfg_new.private_key_len, - KNET_MIN_KEY_LEN, KNET_MAX_KEY_LEN, telnet_newline); - goto key_error; - } - - if (((sb.st_mode & S_IRWXU) != S_IRUSR) || - (sb.st_mode & S_IRWXG) || - (sb.st_mode & S_IRWXO)) { - knet_vty_write(vty, "Error: Key %s does not have the correct permission (must be user read-only)%s", - keyfile, telnet_newline); - goto key_error; - } - - if (read(fd, - &knet_handle_crypto_cfg_new.private_key, - knet_handle_crypto_cfg_new.private_key_len) != (ssize_t)knet_handle_crypto_cfg_new.private_key_len) { - knet_vty_write(vty, "Error: Unable to read key %s%s", keyfile, telnet_newline); - goto key_error; - } - - close(fd); - -no_key: - err = knet_handle_crypto(knet_iface->cfg_ring.knet_h, - &knet_handle_crypto_cfg_new); - - if (!err) { - memmove(&knet_iface->knet_handle_crypto_cfg, &knet_handle_crypto_cfg_new, sizeof(struct knet_handle_crypto_cfg)); - } else { - knet_vty_write(vty, "Error: Unable to initialize crypto module%s", telnet_newline); - } - - return err; - -key_error: - close(fd); - return -1; -} - -static int knet_cmd_start(struct knet_vty *vty) -{ - struct knet_cfg *knet_iface = (struct knet_cfg *)vty->iface; - char *exec_str = NULL; - int err = 0; - - err = nozzle_run_updown(knet_iface->cfg_eth.nozzle, NOZZLE_PREUP, &exec_str); - if (err) { - knet_vty_write(vty, "Non-fatal Error: Unable to execute pre-up.d script for interface %s: %s!%s", nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle), exec_str, telnet_newline); - if (exec_str) { - free(exec_str); - exec_str = NULL; - } - } - - err = nozzle_set_up(knet_iface->cfg_eth.nozzle); - if (err < 0) { - knet_vty_write(vty, "Error: Unable to set interface %s up!%s", nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle), telnet_newline); - knet_handle_setfwd(knet_iface->cfg_ring.knet_h, 0); - } else { - knet_handle_setfwd(knet_iface->cfg_ring.knet_h, 1); - knet_iface->active = 1; - } - - err = nozzle_run_updown(knet_iface->cfg_eth.nozzle, NOZZLE_UP, &exec_str); - if (err) { - knet_vty_write(vty, "Non-fatal Error: Unable to execute up.d script for interface %s: %s!%s", nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle), exec_str, telnet_newline); - if (exec_str) { - free(exec_str); - exec_str = NULL; - } - } - - return err; -} - -static int knet_cmd_no_interface(struct knet_vty *vty) -{ - int err = 0, paramlen = 0, paramoffset = 0; - char *param = NULL; - char device[IFNAMSIZ]; - struct knet_cfg *knet_iface = NULL; - size_t j, i; - knet_node_id_t host_ids[KNET_MAX_HOST]; - uint8_t link_ids[KNET_MAX_LINK]; - size_t host_ids_entries = 0, link_ids_entries = 0; - - get_param(vty, 1, ¶m, ¶mlen, ¶moffset); - param_to_str(device, IFNAMSIZ, param, paramlen); - - knet_iface = knet_get_iface(device, 0); - if (!knet_iface) { - knet_vty_write(vty, "Error: Unable to find requested interface%s", telnet_newline); - return -1; - } - - vty->iface = (void *)knet_iface; - - /* - * disable PTMUd notification before shutting down the tap device - */ - knet_handle_enable_pmtud_notify(knet_iface->cfg_ring.knet_h, NULL, NULL); - - knet_host_get_host_list(knet_iface->cfg_ring.knet_h, host_ids, &host_ids_entries); - for (j = 0; j < host_ids_entries; j++) { - knet_link_get_link_list(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids, &link_ids_entries); - for (i = 0; i < link_ids_entries; i++) { - knet_link_set_enable(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i], 0); - knet_link_clear_config(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i]); - } - knet_host_remove(knet_iface->cfg_ring.knet_h, host_ids[j]); - } - - knet_cmd_stop(vty); - - if (knet_iface->cfg_ring.knet_h) { - knet_handle_free(knet_iface->cfg_ring.knet_h); - knet_iface->cfg_ring.knet_h = NULL; - } - - if (knet_iface->cfg_eth.nozzle) - nozzle_close(knet_iface->cfg_eth.nozzle); - - if (knet_iface) - knet_destroy_iface(knet_iface); - - return err; -} - -static void sock_notify_fn(void *private_data, int datafd, int8_t chan, uint8_t tx_rx, int error, int errorno) -{ - struct knet_vty *vty = (struct knet_vty *)private_data; - - knet_vty_write(vty, "Error: received sock notify, datafd: %d channel: %d direction: %u error: %d errno: %d (%s)%s", - datafd, chan, tx_rx, error, errorno, strerror(errorno), telnet_newline); -} - -static int knet_cmd_interface(struct knet_vty *vty) -{ - int err = 0, paramlen = 0, paramoffset = 0, found = 0, requested_id, tapfd; - uint16_t baseport; - uint8_t *bport = (uint8_t *)&baseport; - char *param = NULL; - char device[IFNAMSIZ]; - char mac[30]; - struct knet_cfg *knet_iface = NULL; - int8_t channel = 0; - - get_param(vty, 1, ¶m, ¶mlen, ¶moffset); - param_to_str(device, IFNAMSIZ, param, paramlen); - - get_param(vty, 2, ¶m, ¶mlen, ¶moffset); - requested_id = param_to_int(param, paramlen); - - get_param(vty, 3, ¶m, ¶mlen, ¶moffset); - baseport = param_to_int(param, paramlen); - - knet_iface = knet_get_iface(device, 1); - if (!knet_iface) { - knet_vty_write(vty, "Error: Unable to allocate memory for config structures%s", - telnet_newline); - return -1; - } - - if (knet_iface->cfg_eth.nozzle) { - found = 1; - goto tap_found; - } - - if (!knet_iface->cfg_eth.nozzle) - knet_iface->cfg_eth.nozzle = nozzle_open(device, IFNAMSIZ, DEFAULT_CONFIG_DIR); - - if ((!knet_iface->cfg_eth.nozzle) && (errno == EBUSY)) { - knet_vty_write(vty, "Error: interface %s seems to exist in the system%s", - device, telnet_newline); - err = -1; - goto out_clean; - } - - if (!knet_iface->cfg_eth.nozzle) { - knet_vty_write(vty, "Error: Unable to create %s system tap device%s", - device, telnet_newline); - err = -1; - goto out_clean; - } -tap_found: - - if (knet_iface->cfg_ring.knet_h) - goto knet_found; - - knet_iface->cfg_ring.base_port = baseport; - - tapfd = nozzle_get_fd(knet_iface->cfg_eth.nozzle); - - knet_iface->cfg_ring.knet_h = knet_handle_new(requested_id, vty->logfd, vty->loglevel); - if (!knet_iface->cfg_ring.knet_h) { - knet_vty_write(vty, "Error: Unable to create ring handle for device %s%s", - device, telnet_newline); - err = -1; - goto out_clean; - } - - if (knet_handle_enable_sock_notify(knet_iface->cfg_ring.knet_h, &vty, sock_notify_fn)) { - knet_vty_write(vty, "Error: Unable to add sock notify callback to to knet_handle %s%s", - strerror(errno), telnet_newline); - err = -1; - goto out_clean; - } - - if (knet_handle_add_datafd(knet_iface->cfg_ring.knet_h, &tapfd, &channel) < 0) { - knet_vty_write(vty, "Error: Unable to add tapfd to knet_handle %s%s", - strerror(errno), telnet_newline); - err = -1; - goto out_clean; - } - - knet_handle_enable_filter(knet_iface->cfg_ring.knet_h, NULL, ether_host_filter_fn); - - if (knet_handle_enable_pmtud_notify(knet_iface->cfg_ring.knet_h, - knet_iface, - knet_cmd_auto_mtu_notify) < 0) { - knet_vty_write(vty, "Error: Unable to configure auto mtu notification for device %s%s", - device, telnet_newline); - err = -1; - goto out_clean; - } - knet_iface->cfg_eth.auto_mtu = 1; - - /* - * make this configurable - */ - knet_handle_pmtud_setfreq(knet_iface->cfg_ring.knet_h, 5); - -knet_found: - if (found) { - if (requested_id == knet_iface->cfg_eth.node_id) - goto out_found; - - knet_vty_write(vty, "Error: no interface %s with nodeid %d found%s", - device, requested_id, telnet_newline); - goto out_clean; - - } else { - knet_iface->cfg_eth.node_id = requested_id; - } - - baseport = htons(baseport); - memset(&mac, 0, sizeof(mac)); - snprintf(mac, sizeof(mac) - 1, "54:54:%x:%x:0:%x", bport[0], bport[1], knet_iface->cfg_eth.node_id); - if (nozzle_set_mac(knet_iface->cfg_eth.nozzle, mac) < 0) { - knet_vty_write(vty, "Error: Unable to set mac address %s on device %s%s", - mac, device, telnet_newline); - err = -1; - goto out_clean; - } - -out_found: - - vty->node = NODE_INTERFACE; - vty->iface = (void *)knet_iface; - -out_clean: - if (err) { - if (knet_iface->cfg_ring.knet_h) - knet_handle_free(knet_iface->cfg_ring.knet_h); - - if (knet_iface->cfg_eth.nozzle) - nozzle_close(knet_iface->cfg_eth.nozzle); - - knet_destroy_iface(knet_iface); - } - return err; -} - -static int knet_cmd_exit_node(struct knet_vty *vty) -{ - knet_vty_exit_node(vty); - return 0; -} - -static int knet_cmd_status(struct knet_vty *vty) -{ - size_t i, j; - struct knet_cfg *knet_iface = knet_cfg_head.knet_cfg; - struct knet_link_status status; - const char *nl = telnet_newline; - struct timespec now; - char nodename[KNET_MAX_HOST_LEN]; - knet_node_id_t host_ids[KNET_MAX_HOST]; - uint8_t link_ids[KNET_MAX_LINK]; - size_t host_ids_entries = 0, link_ids_entries = 0; - uint8_t policy; - - clock_gettime(CLOCK_MONOTONIC, &now); - - knet_vty_write(vty, "Current knet status%s", nl); - knet_vty_write(vty, "-------------------%s", nl); - - while (knet_iface != NULL) { - knet_vty_write(vty, "interface %s (active: %d)%s", nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle), knet_iface->active, nl); - - knet_host_get_host_list(knet_iface->cfg_ring.knet_h, host_ids, &host_ids_entries); - - for (j = 0; j < host_ids_entries; j++) { - knet_host_get_name_by_host_id(knet_iface->cfg_ring.knet_h, host_ids[j], nodename); - knet_vty_write(vty, " peer %s ", nodename); - - knet_host_get_policy(knet_iface->cfg_ring.knet_h, host_ids[j], &policy); - switch (policy) { - case KNET_LINK_POLICY_PASSIVE: - knet_vty_write(vty, "(passive)%s", nl); - break; - case KNET_LINK_POLICY_ACTIVE: - knet_vty_write(vty, "(active)%s", nl); - break; - case KNET_LINK_POLICY_RR: - knet_vty_write(vty, "(round-robin)%s", nl); - break; - } - - knet_link_get_link_list(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids, &link_ids_entries); - for (i = 0; i < link_ids_entries; i++) { - uint8_t dynamic, transport; - const char *transport_name; - struct sockaddr_storage src_addr; - struct sockaddr_storage dst_addr; - uint64_t flags; - - if (!knet_link_get_config(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i], &transport, &src_addr, &dst_addr, &dynamic, &flags)) { - transport_name = knet_get_transport_name_by_id(transport); - knet_link_get_status(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i], &status, sizeof(status)); - if (status.enabled == 1) { - if (dynamic) { - knet_vty_write(vty, " link %s dynamic (%s/connected: %d)%s", status.src_ipaddr, transport_name, status.connected, nl); - } else { - knet_vty_write(vty, " link %s %s (%s/connected: %d)%s", status.src_ipaddr, status.dst_ipaddr, transport_name, status.connected, nl); - } - if (status.connected) { - knet_vty_write(vty, " average latency: %llu us%s", status.latency, nl); - if ((dynamic) && (status.dynconnected)) { - knet_vty_write(vty, " source ip: %s%s", status.dst_ipaddr, nl); - } - } else { - knet_vty_write(vty, " last heard: "); - if (status.pong_last.tv_sec) { - knet_vty_write(vty, "%lu s ago%s", - (long unsigned int)now.tv_sec - status.pong_last.tv_sec, nl); - } else { - knet_vty_write(vty, "never%s", nl); - } - } - } - } - } - } - - knet_iface = knet_iface->next; - } - - return 0; -} - -static int knet_cmd_print_conf(struct knet_vty *vty) -{ - size_t i, j; - struct knet_cfg *knet_iface = knet_cfg_head.knet_cfg; - struct knet_link_status status; - const char *nl = telnet_newline; - struct nozzle_ip *ip_list = NULL; - knet_node_id_t host_ids[KNET_MAX_HOST]; - uint8_t link_ids[KNET_MAX_LINK]; - size_t host_ids_entries = 0, link_ids_entries = 0; - char nodename[KNET_MAX_HOST_LEN]; - uint8_t policy; - unsigned int pmtudfreq = 0; - - if (vty->filemode) - nl = file_newline; - - knet_vty_write(vty, "configure%s", nl); - - knet_vty_write(vty, " vty%s", nl); - knet_vty_write(vty, " timeout %d%s", vty->idle_timeout, nl); - knet_vty_write(vty, " exit%s", nl); - - while (knet_iface != NULL) { - knet_vty_write(vty, " interface %s %d %d%s", nozzle_get_name_by_handle(knet_iface->cfg_eth.nozzle), - knet_iface->cfg_eth.node_id, - knet_iface->cfg_ring.base_port, nl); - - if (!knet_iface->cfg_eth.auto_mtu) - knet_vty_write(vty, " mtu %d%s", nozzle_get_mtu(knet_iface->cfg_eth.nozzle), nl); - - knet_handle_pmtud_getfreq(knet_iface->cfg_ring.knet_h, &pmtudfreq); - if ((pmtudfreq > 0) && (pmtudfreq != 5)) - knet_vty_write(vty, " pmtudfreq %u%s", pmtudfreq, nl); - - nozzle_get_ips(knet_iface->cfg_eth.nozzle, &ip_list); - while (ip_list) { - knet_vty_write(vty, " ip %s %s%s", ip_list->ipaddr, ip_list->prefix, nl); - ip_list = ip_list->next; - } - - knet_vty_write(vty, " crypto %s %s %s%s", - knet_iface->knet_handle_crypto_cfg.crypto_model, - knet_iface->knet_handle_crypto_cfg.crypto_cipher_type, - knet_iface->knet_handle_crypto_cfg.crypto_hash_type, nl); - - knet_host_get_host_list(knet_iface->cfg_ring.knet_h, host_ids, &host_ids_entries); - for (j = 0; j < host_ids_entries; j++) { - knet_host_get_name_by_host_id(knet_iface->cfg_ring.knet_h, host_ids[j], nodename); - knet_vty_write(vty, " peer %s %u%s", nodename, host_ids[j], nl); - - knet_host_get_policy(knet_iface->cfg_ring.knet_h, host_ids[j], &policy); - switch (policy) { - case KNET_LINK_POLICY_PASSIVE: - knet_vty_write(vty, " switch-policy passive%s", nl); - break; - case KNET_LINK_POLICY_ACTIVE: - knet_vty_write(vty, " switch-policy active%s", nl); - break; - case KNET_LINK_POLICY_RR: - knet_vty_write(vty, " switch-policy round-robin%s", nl); - break; - } - - knet_link_get_link_list(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids, &link_ids_entries); - for (i = 0; i < link_ids_entries; i++) { - uint8_t dynamic, transport; - const char *transport_name; - struct sockaddr_storage src_addr; - struct sockaddr_storage dst_addr; - uint64_t flags; - - if (!knet_link_get_config(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i], &transport, &src_addr, &dst_addr, &dynamic, &flags)) { - transport_name = knet_get_transport_name_by_id(transport); - knet_link_get_status(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i], &status, sizeof(status)); - if (status.enabled == 1) { - uint8_t priority, pong_count; - unsigned int precision; - time_t interval, timeout; - - if (dynamic) { - knet_vty_write(vty, " link %d %s dynamic %s%s", link_ids[i], status.src_ipaddr, transport_name, nl); - } else { - knet_vty_write(vty, " link %d %s %s %s%s", link_ids[i], status.src_ipaddr, status.dst_ipaddr, transport_name, nl); - } - knet_link_get_pong_count(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i], &pong_count); - knet_vty_write(vty, " pong_count %u%s", pong_count, nl); - knet_link_get_ping_timers(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i], &interval, &timeout, &precision); - knet_vty_write(vty, " timers %llu %llu%s", (unsigned long long)interval, (unsigned long long)timeout, nl); - knet_link_get_priority(knet_iface->cfg_ring.knet_h, host_ids[j], link_ids[i], &priority); - knet_vty_write(vty, " priority %u%s", priority, nl); - /* print link properties */ - knet_vty_write(vty, " exit%s", nl); - } - } - } - knet_vty_write(vty, " exit%s", nl); - } - - if (knet_iface->active) - knet_vty_write(vty, " start%s", nl); - - knet_vty_write(vty, " exit%s", nl); - knet_iface = knet_iface->next; - } - - knet_vty_write(vty, " exit%sexit%s", nl, nl); - - return 0; -} - -static int knet_cmd_show_conf(struct knet_vty *vty) -{ - return knet_cmd_print_conf(vty); -} - -static int knet_cmd_write_conf(struct knet_vty *vty) -{ - int fd = 1, vty_sock, err = 0, backup = 1; - char tempfile[PATH_MAX]; - - memset(tempfile, 0, sizeof(tempfile)); - - snprintf(tempfile, sizeof(tempfile), "%s.sav", knet_cfg_head.conffile); - err = rename(knet_cfg_head.conffile, tempfile); - if ((err < 0) && (errno != ENOENT)) { - knet_vty_write(vty, "Unable to create backup config file %s %s", tempfile, telnet_newline); - return -1; - } - if ((err < 0) && (errno == ENOENT)) - backup = 0; - - fd = open(knet_cfg_head.conffile, - O_RDWR | O_CREAT | O_EXCL | O_TRUNC, - S_IRUSR | S_IWUSR); - if (fd < 0) { - knet_vty_write(vty, "Error unable to open file%s", telnet_newline); - return -1; - } - - vty_sock = vty->vty_sock; - vty->vty_sock = fd; - vty->filemode = 1; - knet_cmd_print_conf(vty); - vty->vty_sock = vty_sock; - vty->filemode = 0; - - close(fd); - - knet_vty_write(vty, "Configuration saved to %s%s", knet_cfg_head.conffile, telnet_newline); - if (backup) - knet_vty_write(vty, "Old configuration file has been stored in %s%s", - tempfile, telnet_newline); - - return err; -} - -static int knet_cmd_config(struct knet_vty *vty) -{ - int err = 0; - - if (!vty->user_can_enable) { - knet_vty_write(vty, "Error: user %s does not have enough privileges to perform config operations%s", vty->username, telnet_newline); - return -1; - } - - pthread_mutex_lock(&knet_vty_mutex); - if (knet_vty_config >= 0) { - knet_vty_write(vty, "Error: configuration is currently locked by user %s on vty(%d). Try again later%s", vty->username, knet_vty_config, telnet_newline); - err = -1; - goto out_clean; - } - vty->node = NODE_CONFIG; - knet_vty_config = vty->conn_num; -out_clean: - pthread_mutex_unlock(&knet_vty_mutex); - return err; -} - -static int knet_cmd_logout(struct knet_vty *vty) -{ - vty->got_epipe = 1; - return 0; -} - -static int knet_cmd_who(struct knet_vty *vty) -{ - int conn_index; - - pthread_mutex_lock(&knet_vty_mutex); - - for(conn_index = 0; conn_index < KNET_VTY_TOTAL_MAX_CONN; conn_index++) { - if (knet_vtys[conn_index].active) { - knet_vty_write(vty, "User %s connected on vty(%d) from %s%s", - knet_vtys[conn_index].username, - knet_vtys[conn_index].conn_num, - knet_vtys[conn_index].ip, - telnet_newline); - } - } - - pthread_mutex_unlock(&knet_vty_mutex); - - return 0; -} - -static int knet_cmd_help(struct knet_vty *vty) -{ - knet_vty_write(vty, PACKAGE "d VTY provides advanced help feature.%s%s" - "When you need help, anytime at the command line please press '?'.%s%s" - "If nothing matches, the help list will be empty and you must backup%s" - " until entering a '?' shows the available options.%s", - telnet_newline, telnet_newline, telnet_newline, telnet_newline, - telnet_newline, telnet_newline); - return 0; -} - -/* exported API to vty_cli.c */ - -int knet_vty_execute_cmd(struct knet_vty *vty) -{ - const vty_node_cmds_t *cmds = NULL; - char *cmd = NULL; - int cmdlen = 0; - int cmdoffset = 0; - - if (knet_vty_is_line_empty(vty)) - return 0; - - cmds = get_cmds(vty, &cmd, &cmdlen, &cmdoffset); - - /* this will eventually disappear. keep it as safeguard for now */ - if (cmds == NULL) { - knet_vty_write(vty, "No commands associated to this node%s", telnet_newline); - return 0; - } - - return match_command(vty, cmds, cmd, cmdlen, cmdoffset, KNET_VTY_MATCH_EXEC); -} - -void knet_close_down(void) -{ - struct knet_vty *vty = &knet_vtys[0]; - int err, loop = 0; - - vty->node = NODE_CONFIG; - vty->vty_sock = 1; - vty->user_can_enable = 1; - vty->filemode = 1; - vty->got_epipe = 0; - - while ((knet_cfg_head.knet_cfg) && (loop < 10)) { - memset(vty->line, 0, sizeof(vty->line)); - snprintf(vty->line, sizeof(vty->line) - 1, "no interface %s", nozzle_get_name_by_handle(knet_cfg_head.knet_cfg->cfg_eth.nozzle)); - vty->line_idx = strlen(vty->line); - err = knet_vty_execute_cmd(vty); - if (err != 0) { - log_error("error shutting down: %s", vty->line); - break; - } - loop++; - } -} - -int knet_read_conf(void) -{ - int err = 0, len = 0, line = 0; - struct knet_vty *vty = &knet_vtys[0]; - FILE *file = NULL; - - file = fopen(knet_cfg_head.conffile, "r"); - - if ((file == NULL) && (errno != ENOENT)) { - log_error("Unable to open config file for reading %s", knet_cfg_head.conffile); - return -1; - } - - if ((file == NULL) && (errno == ENOENT)) { - log_info("Configuration file %s not found, starting with default empty config", knet_cfg_head.conffile); - return 0; - } - - vty->vty_sock = 1; - vty->user_can_enable = 1; - vty->filemode = 1; - - while(fgets(vty->line, sizeof(vty->line), file) != NULL) { - line++; - len = strlen(vty->line) - 1; - memset(&vty->line[len], 0, 1); - vty->line_idx = len; - err = knet_vty_execute_cmd(vty); - if (err != 0) { - log_error("line[%d]: %s", line, vty->line); - break; - } - } - - fclose(file); - - memset(vty, 0, sizeof(*vty)); - - return err; -} - -void knet_vty_help(struct knet_vty *vty) -{ - int idx = 0; - const vty_node_cmds_t *cmds = NULL; - char *cmd = NULL; - int cmdlen = 0; - int cmdoffset = 0; - - cmds = get_cmds(vty, &cmd, &cmdlen, &cmdoffset); - - /* this will eventually disappear. keep it as safeguard for now */ - if (cmds == NULL) { - knet_vty_write(vty, "No commands associated to this node%s", telnet_newline); - return; - } - - if (knet_vty_is_line_empty(vty) || cmd == NULL) { - while (cmds[idx].cmd != NULL) { - print_help(vty, cmds, idx); - idx++; - } - return; - } - - match_command(vty, cmds, cmd, cmdlen, cmdoffset, KNET_VTY_MATCH_HELP); -} - -void knet_vty_tab_completion(struct knet_vty *vty) -{ - const vty_node_cmds_t *cmds = NULL; - char *cmd = NULL; - int cmdlen = 0; - int cmdoffset = 0; - - if (knet_vty_is_line_empty(vty)) - return; - - knet_vty_write(vty, "%s", telnet_newline); - - cmds = get_cmds(vty, &cmd, &cmdlen, &cmdoffset); - - /* this will eventually disappear. keep it as safeguard for now */ - if (cmds == NULL) { - knet_vty_write(vty, "No commands associated to this node%s", telnet_newline); - return; - } - - match_command(vty, cmds, cmd, cmdlen, cmdoffset, KNET_VTY_MATCH_EXPAND); - - knet_vty_prompt(vty); - knet_vty_write(vty, "%s", vty->line); -} diff --git a/kronosnetd/vty_cli_cmds.h b/kronosnetd/vty_cli_cmds.h deleted file mode 100644 index 89ab0ede..00000000 --- a/kronosnetd/vty_cli_cmds.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. - * - * Author: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+ - */ - -#ifndef __KNETD_VTY_CLI_CMDS_H__ -#define __KNETD_VTY_CLI_CMDS_H__ - -#include "vty.h" - -typedef struct { - const int param; -} vty_param_t; - -typedef struct { - const char *cmd; - const char *help; - const vty_param_t *params; - int (*func) (struct knet_vty *vty); -} vty_node_cmds_t; - -typedef struct { - const int node_num; - const char *prompt; - const vty_node_cmds_t *cmds; - const vty_node_cmds_t *no_cmds; -} vty_nodes_t; - -enum vty_nodes { - NODE_ROOT = 0, - NODE_CONFIG, - NODE_INTERFACE, - NODE_PEER, - NODE_LINK, - NODE_VTY -}; - -int knet_vty_execute_cmd(struct knet_vty *vty); -void knet_vty_help(struct knet_vty *vty); -void knet_vty_tab_completion(struct knet_vty *vty); - -int knet_read_conf(void); -void knet_close_down(void); - -extern vty_nodes_t knet_vty_nodes[]; - -#endif diff --git a/kronosnetd/vty_utils.c b/kronosnetd/vty_utils.c deleted file mode 100644 index 33b30e4a..00000000 --- a/kronosnetd/vty_utils.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. - * - * Author: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+ - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "logging.h" -#include "vty_cli.h" -#include "vty_cli_cmds.h" -#include "vty_utils.h" - -static int check_vty(struct knet_vty *vty) -{ - if (!vty) { - errno = EINVAL; - return -1; - } - if (vty->got_epipe) { - errno = EPIPE; - return -1; - } - return 0; -} - -/* - * TODO: implement loopy_write here - * should sock be non-blocking? - */ -static int knet_vty_loopy_write(struct knet_vty *vty, const char *buf, size_t bufsize) -{ - ssize_t writelen; - - writelen = write(vty->vty_sock, buf, bufsize); - if (writelen < 0) - vty->got_epipe = 1; - - return writelen; -} - -int knet_vty_write(struct knet_vty *vty, const char *format, ...) -{ - va_list args; - int len = 0; - char buf[VTY_MAX_BUFFER_SIZE]; - - if (check_vty(vty)) - return -1; - - va_start (args, format); - len = vsnprintf (buf, VTY_MAX_BUFFER_SIZE, format, args); - va_end (args); - - if ((len < 0) || (len > VTY_MAX_BUFFER_SIZE)) - return -1; - - return knet_vty_loopy_write(vty, buf, len); -} - -static int knet_vty_read_real(struct knet_vty *vty, unsigned char *buf, size_t bufsize, - int ignore_iac) -{ - ssize_t readlen; - -iac_retry: - readlen = recv(vty->vty_sock, buf, bufsize, 0); - if (readlen == 0) { - vty->got_epipe = 1; - goto out_clean; - } - if (readlen < 0) - goto out_clean; - - vty->idle = 0; - - /* at somepoint we have to add IAC parsing */ - if ((buf[0] == IAC) && (ignore_iac)) - goto iac_retry; - -out_clean: - return readlen; -} - -int knet_vty_read(struct knet_vty *vty, unsigned char *buf, size_t bufsize) -{ - if (check_vty(vty)) - return -1; - - if ((!buf) || (bufsize == 0)) { - errno = EINVAL; - return -1; - } - return knet_vty_read_real(vty, buf, bufsize, 1); -} - -static int knet_vty_set_echooff(struct knet_vty *vty) -{ - unsigned char cmdreply[VTY_MAX_BUFFER_SIZE]; - unsigned char cmdechooff[] = { IAC, WILL, TELOPT_ECHO, '\0' }; - unsigned char cmdechooffreply[] = { IAC, DO, TELOPT_ECHO, '\0' }; - ssize_t readlen; - - if (knet_vty_write(vty, "%s", cmdechooff) < 0) - return -1; - - readlen = knet_vty_read_real(vty, cmdreply, VTY_MAX_BUFFER_SIZE, 0); - if (readlen < 0) - return readlen; - - if (memcmp(&cmdreply, &cmdechooffreply, readlen)) - return -1; - - return 0; -} - -static int knet_vty_set_echoon(struct knet_vty *vty) -{ - unsigned char cmdreply[VTY_MAX_BUFFER_SIZE]; - unsigned char cmdechoon[] = { IAC, WONT, TELOPT_ECHO, '\0' }; - unsigned char cmdechoonreply[] = { IAC, DONT, TELOPT_ECHO, '\0' }; - ssize_t readlen; - - if (knet_vty_write(vty, "%s", cmdechoon) < 0) - return -1; - - readlen = knet_vty_read_real(vty, cmdreply, VTY_MAX_BUFFER_SIZE, 0); - if (readlen < 0) - return readlen; - - if (memcmp(&cmdreply, &cmdechoonreply, readlen)) - return -1; - - return 0; -} - -int knet_vty_set_echo(struct knet_vty *vty, int on) -{ - if (check_vty(vty)) - return -1; - - if (on) - return knet_vty_set_echoon(vty); - - return knet_vty_set_echooff(vty); -} - -void knet_vty_print_banner(struct knet_vty *vty) -{ - if (check_vty(vty)) - return; - - knet_vty_write(vty, - "Welcome to " PACKAGE "d " PACKAGE_VERSION " (built " __DATE__ - " " __TIME__ ")\n"); -} - -int knet_vty_set_iacs(struct knet_vty *vty) -{ - unsigned char cmdreply[VTY_MAX_BUFFER_SIZE]; - unsigned char cmdsga[] = { IAC, WILL, TELOPT_SGA, '\0' }; - unsigned char cmdsgareply[] = { IAC, DO, TELOPT_SGA, '\0' }; - unsigned char cmdlm[] = { IAC, DONT, TELOPT_LINEMODE, '\0' }; - ssize_t readlen; - - if (check_vty(vty)) - return -1; - - if (knet_vty_set_echo(vty, 0) < 0) - return -1; - - if (knet_vty_write(vty, "%s", cmdsga) < 0) - return -1; - - readlen = knet_vty_read_real(vty, cmdreply, VTY_MAX_BUFFER_SIZE, 0); - if (readlen < 0) - return readlen; - - if (memcmp(&cmdreply, &cmdsgareply, readlen)) - return -1; - - if (knet_vty_write(vty, "%s", cmdlm) < 0) - return -1; - - return 0; -} - -void knet_vty_free_history(struct knet_vty *vty) -{ - int i; - - if (check_vty(vty)) - return; - - for (i = 0; i < KNET_VTY_MAX_HIST; i++) { - if (vty->history[i]) { - free(vty->history[i]); - vty->history[i] = NULL; - } - } -} - -void knet_vty_exit_node(struct knet_vty *vty) -{ - switch(vty->node) { - case NODE_VTY: - vty->node = vty->prevnode; - break; - case NODE_LINK: - vty->node = NODE_PEER; - break; - case NODE_PEER: - vty->node = NODE_INTERFACE; - break; - case NODE_INTERFACE: - vty->node = NODE_CONFIG; - break; - case NODE_CONFIG: - pthread_mutex_lock(&knet_vty_mutex); - knet_vty_config = -1; - pthread_mutex_unlock(&knet_vty_mutex); - vty->node = NODE_ROOT; - break; - case NODE_ROOT: - vty->got_epipe = 1; - break; - default: - knet_vty_write(vty, "No idea where to go..%s", telnet_newline); - break; - } -} - -int knet_vty_is_line_empty(struct knet_vty *vty) -{ - int idx; - - for (idx = 0; idx < vty->line_idx; idx++) { - if (vty->line[idx] != ' ') - return 0; - } - - return 1; -} - -void knet_vty_prompt(struct knet_vty *vty) -{ - char buf[3]; - - if (vty->user_can_enable) { - buf[0] = '#'; - } else { - buf[0] = '>'; - } - buf[1] = ' '; - buf[2] = 0; - knet_vty_write(vty, "%s%s", knet_vty_nodes[vty->node].prompt, buf); -} diff --git a/kronosnetd/vty_utils.h b/kronosnetd/vty_utils.h deleted file mode 100644 index 14e7370a..00000000 --- a/kronosnetd/vty_utils.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. - * - * Author: Fabio M. Di Nitto - * - * This software licensed under GPL-2.0+ - */ - -#ifndef __KNETD_VTY_UTILS_H__ -#define __KNETD_VTY_UTILS_H__ - -#include "vty.h" - -#define VTY_MAX_BUFFER_SIZE 4096 - -int knet_vty_write(struct knet_vty *vty, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))); - -int knet_vty_read(struct knet_vty *vty, unsigned char *buf, size_t bufsize); - -int knet_vty_set_echo(struct knet_vty *vty, int on); - -void knet_vty_print_banner(struct knet_vty *vty); - -int knet_vty_set_iacs(struct knet_vty *vty); - -void knet_vty_free_history(struct knet_vty *vty); - -void knet_vty_exit_node(struct knet_vty *vty); - -int knet_vty_is_line_empty(struct knet_vty *vty); - -void knet_vty_prompt(struct knet_vty *vty); - -#endif diff --git a/libknet/libknet.h b/libknet/libknet.h index aeec6aca..b53132ab 100644 --- a/libknet/libknet.h +++ b/libknet/libknet.h @@ -1,2368 +1,2366 @@ /* * Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. * * Authors: Fabio M. Di Nitto * Federico Simoncelli * * This software licensed under LGPL-2.0+ */ #ifndef __LIBKNET_H__ #define __LIBKNET_H__ #include #include #include #include #include /** * @file libknet.h * @brief kronosnet API include file * @copyright Copyright (C) 2010-2020 Red Hat, Inc. All rights reserved. * * Kronosnet is an advanced VPN system for High Availability applications. */ #define KNET_API_VER 2 /* * 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) /* * Handle flags */ /* * Use privileged operations during socket setup. */ #define KNET_HANDLE_FLAG_PRIVILEGED (1ULL << 0) /* * threads timer resolution (see knet_handle_set_threads_timer_res below) */ #define KNET_THREADS_TIMER_RES 200000 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 UINT16_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. * It is strongly encouraged to use pipes (ex: pipe(2) or pipe2(2)) for * logging fds due to the atomic nature of writes between fds. * See also libknet test suite for reference and guidance. * * default_log_level - * If logfd is specified, it will initialize all subsystems to log * at default_log_level value. (see logging API) * * flags - bitwise OR of some of the following flags: * KNET_HANDLE_FLAG_PRIVILEGED: use privileged operations setting up the * communication sockets. If disabled, failure to acquire large * enough socket buffers is ignored but logged. Inadequate buffers * lead to poor performance. * * @return * on success, a new knet_handle_t is returned. * on failure, NULL is returned and errno is set. * knet-specific errno values: * ENAMETOOLONG - socket buffers couldn't be set big enough and KNET_HANDLE_FLAG_PRIVILEGED was specified * ERANGE - buffer size readback returned unexpected type */ knet_handle_t knet_handle_new(knet_node_id_t host_id, int log_fd, uint8_t default_log_level, uint64_t flags); /** * 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_set_threads_timer_res * * @brief Change internal thread timer resolution * * knet_h - pointer to knet_handle_t * * timeres - some threads inside knet will use usleep(timeres) * to check if any activity has to be performed, or wait * for the next cycle. 'timeres' (expressed in nano seconds) * defines this interval, with a default of KNET_THREADS_TIMER_RES * (200000). * The lower this value is, the more often knet will perform * those checks and allows a more (time) precise execution of * some operations (for example ping/pong), at the cost of higher * CPU usage. * Accepted values: * 0 - reset timer res to default * 1 - 999 invalid (as it would cause 100% CPU spinning on some * epoll operations) * 1000 or higher - valid * * Unless you know exactly what you are doing, stay away from * changing the default or seek written and notarized approval * from the knet developer team. * * @return * knet_handle_set_threads_timer_res returns * 0 on success * -1 on error and errno is set. */ int knet_handle_set_threads_timer_res(knet_handle_t knet_h, useconds_t timeres); /** * knet_handle_get_threads_timer_res * * @brief Get internal thread timer resolutions * * knet_h - pointer to knet_handle_t * * timeres - current timer res value * * @return * knet_handle_set_threads_timer_res returns * 0 on success and timerres will contain the current value * -1 on error and errno is set. */ int knet_handle_get_threads_timer_res(knet_handle_t knet_h, useconds_t *timeres); /** * 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-exec. * * *channel - This value is analogous to the tag in 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 sends 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); /** * knet_handle_enable_access_lists * * @brief Enable or disable usage of access lists (default: off) * * knet_h - pointer to knet_handle_t * * enable - set to 1 to use access lists, 0 to disable access_lists. * * @return * knet_handle_enable_access_lists returns * 0 on success * -1 on error and errno is set. * * access lists are bound to links. There are 2 types of links: * 1) point to point, where both source and destinations are well known * at configuration time. * 2) open links, where only the source is known at configuration time. * * knet will automatically generate access lists for point to point links. * * For open links, knet provides 4 API calls to manipulate access lists: * knet_link_add_acl(3), knet_link_rm_acl(3), knet_link_insert_acl(3) * and knet_link_clear_acl(3). * Those API calls will work exclusively on open links as they * are of no use on point to point links. * * knet will not enforce any access list unless specifically enabled by * knet_handle_enable_access_lists(3). * * From a security / programming perspective we recommend: * - create the knet handle * - enable access lists * - configure hosts and links * - configure access lists for open links */ int knet_handle_enable_access_lists(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_set * * @brief Set the current interface MTU * * knet_h - pointer to knet_handle_t * * iface_mtu - current interface MTU, value 0 to 65535. 0 will * re-enable automatic MTU discovery. * In a setup with multiple interfaces, please specify * the lowest MTU between the selected intefaces. * knet will automatically adjust this value for * all headers overhead and set the correct data_mtu. * data_mtu can be retrivied with knet_handle_pmtud_get(3) * or applications will receive a pmtud_nofity event * if enabled via knet_handle_enable_pmtud_notify(3). * * @return * knet_handle_pmtud_set returns * 0 on success * -1 on error and errno is set. */ int knet_handle_pmtud_set(knet_handle_t knet_h, unsigned int iface_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 128 #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_set_config * * @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: * "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. * * config_num - knet supports 2 concurrent sets of crypto configurations, * to allow runtime change of crypto config and keys. * On RX both configurations will be used sequentially * in an attempt to decrypt/validate a packet (when 2 are available). * Note that this might slow down performance during a reconfiguration. * See also knet_handle_crypto_rx_clear_traffic(3) to enable / disable * processing of clear (unencrypted) traffic. * For TX, the user needs to specify which configuration to use via * knet_handle_crypto_use_config(3). * config_num accepts 0, 1 or 2 as the value. 0 should be used when * all crypto is being disabled. * Calling knet_handle_crypto_set_config(3) twice with * the same config_num will REPLACE the configuration and * NOT activate the second key. If the configuration is currently in use * EBUSY will be returned. See also knet_handle_crypto_use_config(3). * The correct sequence to perform a runtime rekey / reconfiguration * is: * - knet_handle_crypto_set_config(..., 1). -> first time config, will use config1 * - knet_handle_crypto_use_config(..., 1). -> switch TX to config 1 * - knet_handle_crypto_set_config(..., 2). -> install config2 and use it only for RX * - knet_handle_crypto_use_config(..., 2). -> switch TX to config 2 * - knet_handle_crypto_set_config(..., 1). -> with a "none"/"none"/"none" configuration to * release the resources previously allocated * The application is responsible for synchronizing calls on the nodes * to make sure the new config is in place before switching the TX configuration. * Failure to do so will result in knet being unable to talk to some of the nodes. * * 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. * - private/public key encryption/hashing is not currently * planned. * - crypto key must be the same for all hosts in the same * knet instance / configX. * - it is safe to call knet_handle_crypto_set_config multiple times at runtime. * The last config will be used. * IMPORTANT: a call to knet_handle_crypto_set_config 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_set_config(3). * A failure in crypto init will restore the previous crypto configuration if any. * * @return * knet_handle_crypto_set_config 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_set_config(knet_handle_t knet_h, struct knet_handle_crypto_cfg *knet_handle_crypto_cfg, uint8_t config_num); #define KNET_CRYPTO_RX_ALLOW_CLEAR_TRAFFIC 0 #define KNET_CRYPTO_RX_DISALLOW_CLEAR_TRAFFIC 1 /** * knet_handle_crypto_rx_clear_traffic * * @brief enable or disable RX processing of clear (unencrypted) traffic * * knet_h - pointer to knet_handle_t * * value - KNET_CRYPTO_RX_ALLOW_CLEAR_TRAFFIC or KNET_CRYPTO_RX_DISALLOW_CLEAR_TRAFFIC * * @return * knet_handle_crypto_use_config returns: * @retval 0 on success * @retval -1 on error and errno is set. */ int knet_handle_crypto_rx_clear_traffic(knet_handle_t knet_h, uint8_t value); /** * knet_handle_crypto_use_config * * @brief specify crypto configuration to use for TX * * knet_h - pointer to knet_handle_t * * config_num - 1|2 use configuration 1 or 2, 0 for clear (unencrypted) traffic. * * @return * knet_handle_crypto_use_config returns: * @retval 0 on success * @retval -1 on error and errno is set. */ int knet_handle_crypto_use_config(knet_handle_t knet_h, uint8_t config_num); #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 contains the model name. * See "compress_level" for the list of accepted values. * Setting the value to "none" disables 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 is the "level" parameter for most models: * 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) * depending on the version of lz4hc libknet was built with. * lzma: 0 (minimal) .. 9 (max compression) * bzip2: 1 (minimal) .. 9 (max compression) * For lzo2 it selects the algorithm to use: * 1 : lzo1x_1_compress (default) * 11 : lzo1x_1_11_compress * 12 : lzo1x_1_12_compress * 15 : lzo1x_1_15_compress * 999: lzo1x_999_compress * Other values select the default algorithm. * Please refer to the documentation of the respective * compression library for guidance about setting this * value. * * 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 tx_failed_to_compress; uint64_t tx_unable_to_compress; 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; uint64_t rx_failed_to_decompress; /* 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 * * @brief Set the switching policy for a host's links * * knet_h - pointer to knet_handle_t * * 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 highest * priority (highest number) 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_get_status * * @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); /* * Access lists management for open links * see also knet_handle_enable_access_lists(3) */ /** * check_type_t * @brief address type enum for knet access lists * * CHECK_TYPE_ADDRESS is the equivalent of a single entry / IP address. * for example: 10.1.9.3 * and the entry is stored in ss1. ss2 can be NULL. * * CHECK_TYPE_MASK is used to configure network/netmask. * for example: 192.168.0.0/24 * the network is stored in ss1 and the netmask in ss2. * * CHECK_TYPE_RANGE defines a value / range of ip addresses. * for example: 172.16.0.1-172.16.0.10 * the start is stored in ss1 and the end in ss2. * * Please be aware that the above examples refer only to IP based protocols. * Other protocols might use ss1 and ss2 in slightly different ways. * At the moment knet only supports IP based protocol, though that might change * in the future. */ typedef enum { CHECK_TYPE_ADDRESS, CHECK_TYPE_MASK, CHECK_TYPE_RANGE } check_type_t; /** * check_acceptreject_t * * @brief enum for accept/reject in knet access lists * * accept or reject incoming packets defined in the access list entry */ typedef enum { CHECK_ACCEPT, CHECK_REJECT } check_acceptreject_t; /** * knet_link_add_acl * * @brief Add access list entry to an open link * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * link_id - see knet_link_set_config(3) * * ss1 / ss2 / type / acceptreject - see typedef definitions for details * * IMPORTANT: the order in which access lists are added is critical and it * is left to the user to add them in the right order. knet * will not attempt to logically sort them. * * For example: * 1 - accept from 10.0.0.0/8 * 2 - reject from 10.0.0.1/32 * * is not the same as: * * 1 - reject from 10.0.0.1/32 * 2 - accept from 10.0.0.0/8 * * In the first example, rule number 2 will never match because * packets from 10.0.0.1 will be accepted by rule number 1. * * @return * knet_link_add_acl returns * 0 on success. * -1 on error and errno is set. */ int knet_link_add_acl(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id, struct sockaddr_storage *ss1, struct sockaddr_storage *ss2, check_type_t type, check_acceptreject_t acceptreject); /** * knet_link_insert_acl * * @brief Insert access list entry to an open link at given index * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * link_id - see knet_link_set_config(3) * * index - insert at position "index" where 0 is the first entry and -1 * appends to the current list. * * ss1 / ss2 / type / acceptreject - see typedef definitions for details * * @return * knet_link_insert_acl returns * 0 on success. * -1 on error and errno is set. */ int knet_link_insert_acl(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id, int index, struct sockaddr_storage *ss1, struct sockaddr_storage *ss2, check_type_t type, check_acceptreject_t acceptreject); /** * knet_link_rm_acl * * @brief Remove access list entry from an open link * * knet_h - pointer to knet_handle_t * * host_id - see knet_host_add(3) * * link_id - see knet_link_set_config(3) * * ss1 / ss2 / type / acceptreject - see typedef definitions for details * * IMPORTANT: the data passed to this API call must match exactly that passed * to knet_link_add_acl(3). * * @return * knet_link_rm_acl returns * 0 on success. * -1 on error and errno is set. */ int knet_link_rm_acl(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id, struct sockaddr_storage *ss1, struct sockaddr_storage *ss2, check_type_t type, check_acceptreject_t acceptreject); /** * knet_link_clear_acl * * @brief Remove all access list entries from an open 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_acl returns * 0 on success. * -1 on error and errno is set. */ int knet_link_clear_acl(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. * * 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 */ 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); /** * knet_link_enable_status_change_notify * * @brief Install a callback to get a link 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 a link status. * host status is identified by: * - connected, 0 if the link has been disconnected, 1 if the link * is connected. * - 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_link_enable_status_change_notify(knet_handle_t knet_h, void *link_status_change_notify_fn_private_data, void (*link_status_change_notify_fn) ( void *private_data, knet_node_id_t host_id, uint8_t link_id, uint8_t connected, uint8_t remote, uint8_t external)); /* * 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_ZSTDCOMP 76 /* compress_zstd.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 * 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 254 #if KNET_MAX_LOG_MSG_SIZE > PIPE_BUF #error KNET_MAX_LOG_MSG_SIZE cannot be bigger than PIPE_BUF for guaranteed system atomic writes #endif struct knet_log_msg { char msg[KNET_MAX_LOG_MSG_SIZE]; uint8_t subsystem; /* KNET_SUB_* */ uint8_t msglevel; /* KNET_LOG_* */ knet_handle_t knet_h; /* pointer to the handle generating the log */ }; /** * knet_log_set_loglevel * * @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_loglevel * * @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/man/Makefile.am b/man/Makefile.am index 9db8d7a8..29a59714 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -1,153 +1,148 @@ # # Copyright (C) 2017-2020 Red Hat, Inc. All rights reserved. # # Authors: Fabio M. Di Nitto # Federico Simoncelli # # This software licensed under GPL-2.0+ # MAINTAINERCLEANFILES = Makefile.in include $(top_srcdir)/build-aux/check.mk EXTRA_DIST = \ - kronosnetd.8 knet-keygen.8 \ api-to-man-page-coverage if BUILD_MAN -if BUILD_KRONOSNETD -man8_MANS = kronosnetd.8 knet-keygen.8 -endif - knet_man3_MANS = \ knet_addrtostr.3 \ knet_handle_add_datafd.3 \ knet_handle_clear_stats.3 \ knet_handle_compress.3 \ knet_handle_enable_filter.3 \ knet_handle_enable_pmtud_notify.3 \ knet_handle_enable_sock_notify.3 \ knet_handle_free.3 \ knet_handle_get_channel.3 \ knet_get_compress_list.3 \ knet_get_crypto_list.3 \ knet_handle_get_datafd.3 \ knet_handle_get_stats.3 \ knet_get_transport_id_by_name.3 \ knet_get_transport_list.3 \ knet_get_transport_name_by_id.3 \ knet_handle_get_transport_reconnect_interval.3 \ knet_handle_new.3 \ knet_handle_pmtud_get.3 \ knet_handle_pmtud_set.3 \ knet_handle_pmtud_getfreq.3 \ knet_handle_pmtud_setfreq.3 \ knet_handle_remove_datafd.3 \ knet_handle_setfwd.3 \ knet_handle_set_transport_reconnect_interval.3 \ knet_host_add.3 \ knet_host_enable_status_change_notify.3 \ knet_host_get_host_list.3 \ knet_host_get_id_by_host_name.3 \ knet_host_get_name_by_host_id.3 \ knet_host_get_policy.3 \ knet_host_get_status.3 \ knet_host_remove.3 \ knet_host_set_name.3 \ knet_host_set_policy.3 \ knet_link_clear_config.3 \ knet_link_get_config.3 \ knet_link_get_enable.3 \ knet_link_get_link_list.3 \ knet_link_get_ping_timers.3 \ knet_link_get_pong_count.3 \ knet_link_get_priority.3 \ knet_link_get_status.3 \ knet_link_set_config.3 \ knet_link_set_enable.3 \ knet_link_set_ping_timers.3 \ knet_link_set_pong_count.3 \ knet_link_set_priority.3 \ knet_log_get_loglevel.3 \ knet_log_get_loglevel_id.3 \ knet_log_get_loglevel_name.3 \ knet_log_get_subsystem_id.3 \ knet_log_get_subsystem_name.3 \ knet_log_set_loglevel.3 \ knet_recv.3 \ knet_send.3 \ knet_send_sync.3 \ knet_strtoaddr.3 \ knet_handle_set_threads_timer_res.3 \ knet_handle_get_threads_timer_res.3 \ knet_link_enable_status_change_notify.3 \ knet_handle_enable_access_lists.3 \ knet_link_add_acl.3 \ knet_link_insert_acl.3 \ knet_link_rm_acl.3 \ knet_link_clear_acl.3 \ knet_handle_crypto_set_config.3 \ knet_handle_crypto_use_config.3 \ knet_handle_crypto_rx_clear_traffic.3 if BUILD_LIBNOZZLE nozzle_man3_MANS = \ nozzle_add_ip.3 \ nozzle_close.3 \ nozzle_del_ip.3 \ nozzle_get_fd.3 \ nozzle_get_handle_by_name.3 \ nozzle_get_ips.3 \ nozzle_get_mac.3 \ nozzle_get_mtu.3 \ nozzle_get_name_by_handle.3 \ nozzle_open.3 \ nozzle_reset_mac.3 \ nozzle_reset_mtu.3 \ nozzle_run_updown.3 \ nozzle_set_down.3 \ nozzle_set_mac.3 \ nozzle_set_mtu.3 \ nozzle_set_up.3 endif man3_MANS = $(knet_man3_MANS) $(nozzle_man3_MANS) $(MANS): doxyfile-knet.stamp doxyfile-nozzle.stamp # export LSAN_OPTIONS unconditionally for now. # there is no urgency to fix doxygen2man for leaks or bad memory access # since it's a one-shot tool and doesn't affect runtime. doxyfile-knet.stamp: Doxyfile-knet $(top_srcdir)/libknet/libknet.h $(DOXYGEN) Doxyfile-knet LSAN_OPTIONS="exitcode=0" $(DOXYGEN2MAN) -m -P -o $(builddir) -s 3 -p @PACKAGE_NAME@ -H "Kronosnet Programmer's Manual" \ $$($(UTC_DATE_AT)$(SOURCE_EPOCH) +"-D %F -Y %Y") -d $(builddir)/xml-knet/ libknet_8h.xml touch doxyfile-knet.stamp doxyfile-nozzle.stamp: Doxyfile-nozzle $(top_srcdir)/libnozzle/libnozzle.h if BUILD_LIBNOZZLE $(DOXYGEN) Doxyfile-nozzle LSAN_OPTIONS="exitcode=0" $(DOXYGEN2MAN) -m -P -o $(builddir) -s 3 -p @PACKAGE_NAME@ -H "Kronosnet Programmer's Manual" \ $$($(UTC_DATE_AT)$(SOURCE_EPOCH) +"-D %F -Y %Y") -d $(builddir)/xml-nozzle/ libnozzle_8h.xml endif touch doxyfile-nozzle.stamp noinst_SCRIPTS = api-to-man-page-coverage check-local: check-api-to-man-page-coverage-libknet check-api-to-man-page-coverage-libnozzle check-api-to-man-page-coverage-libnozzle: if BUILD_LIBNOZZLE $(srcdir)/api-to-man-page-coverage $(top_srcdir) nozzle endif check-api-to-man-page-coverage-libknet: $(srcdir)/api-to-man-page-coverage $(top_srcdir) knet endif clean-local: rm -rf doxyfile*.stamp xml* *.3 diff --git a/man/knet-keygen.8 b/man/knet-keygen.8 deleted file mode 100644 index 4dca73ad..00000000 --- a/man/knet-keygen.8 +++ /dev/null @@ -1,28 +0,0 @@ -.\"/* -.\" * Copyright (C) 2012-2020 Red Hat, Inc. -.\" * -.\" * All rights reserved. -.\" * -.\" * Author: Fabio M. Di Nitto -.\" * -.\" * This software licensed under GPL-2.0+ -.\" */ -.TH "KRONOSNETD" "8" "November 2012" "kronosnetd key generator." "System Administration Utilities" - -.SH "NAME" -knet\-keygen \- Tool to generate keys for kronosnetd. - -.SH "SYNOPSIS" -.B knet\-keygen -\fB\-o\fR [\-s ] - -.SH "OPTIONS" -.TP -\fB\-o\fR -Output file -.TP -\fB\-s\fR -Key size (value between 1024 and 4096 included) - -.SH "SEE ALSO" -kronosnetd(8) diff --git a/man/kronosnetd.8 b/man/kronosnetd.8 deleted file mode 100644 index 58959904..00000000 --- a/man/kronosnetd.8 +++ /dev/null @@ -1,51 +0,0 @@ -.\"/* -.\" * Copyright (C) 2012-2020 Red Hat, Inc. -.\" * -.\" * All rights reserved. -.\" * -.\" * Author: Fabio M. Di Nitto -.\" * -.\" * This software licensed under GPL-2.0+ -.\" */ -.TH "KRONOSNETD" "8" "November 2012" "kronosnetd Usage:" "System Administration Utilities" - -.SH "NAME" -kronosnetd \- libknet management daemon - -.SH "DESCRIPTION" -Usage: -.PP -kronosnetd [options] - -.SH "OPTIONS" - -.TP -\fB\-a\fR -Bind management VTY to ipv6_addr (default: localhost) -.TP -\fB\-b\fR -Bind management VTY to ipv4_addr (default: localhost) -.TP -\fB\-p\fR -Bind management VTY to port (default 50000) -.TP -\fB\-c\fR -Use config file (default /etc/kronosnet/kronosnetd.conf) -.TP -\fB\-l\fR -Use log file (default /var/log//kronosnetd.log) -.TP -\fB\-f\fR -Do not fork in background -.TP -\fB\-d\fR -Enable debugging output -.TP -\fB\-h\fR -This help -.TP -\fB\-V\fR -Print program version information - -.SH "SEE ALSO" -knet-keygen(8)