new upstream 2.8.0
This commit is contained in:
parent
fc7f4b43c1
commit
b2b0c9995a
836 changed files with 137090 additions and 30018 deletions
|
|
@ -1,5 +1,10 @@
|
|||
# Network UPS Tools: server
|
||||
|
||||
# Make sure out-of-dir dependencies exist (especially when dev-building parts):
|
||||
$(top_builddir)/common/libcommon.la \
|
||||
$(top_builddir)/common/libparseconf.la: dummy
|
||||
@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F)
|
||||
|
||||
# Avoid per-target CFLAGS, because this will prevent re-use of object
|
||||
# files. In any case, CFLAGS are only -I options, so there is no harm,
|
||||
# but only add them if we really use the target.
|
||||
|
|
@ -10,7 +15,7 @@ endif
|
|||
if WITH_SSL
|
||||
AM_CFLAGS += $(LIBSSL_CFLAGS)
|
||||
endif
|
||||
LDADD = ../common/libcommon.la ../common/libparseconf.la $(NETLIBS)
|
||||
LDADD = $(top_builddir)/common/libcommon.la $(top_builddir)/common/libparseconf.la $(NETLIBS)
|
||||
if WITH_WRAP
|
||||
LDADD += $(LIBWRAP_LIBS)
|
||||
endif
|
||||
|
|
@ -28,3 +33,12 @@ upsd_SOURCES = upsd.c user.c conf.c netssl.c sstate.c desc.c \
|
|||
upstype.h user-data.h user.h
|
||||
|
||||
sockdebug_SOURCES = sockdebug.c
|
||||
|
||||
dummy:
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in .dirstamp
|
||||
|
||||
# NOTE: Do not clean ".deps" in SUBDIRS of the main project,
|
||||
# the root Makefile.am takes care of that!
|
||||
#clean-local:
|
||||
# rm -rf $(builddir)/.deps
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Makefile.in generated by automake 1.14.1 from Makefile.am.
|
||||
# Makefile.in generated by automake 1.16.3 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
|
@ -17,7 +17,17 @@
|
|||
# Network UPS Tools: server
|
||||
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
|
||||
am__is_gnu_make = { \
|
||||
if test -z '$(MAKELEVEL)'; then \
|
||||
false; \
|
||||
elif test -n '$(MAKE_HOST)'; then \
|
||||
true; \
|
||||
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||
true; \
|
||||
else \
|
||||
false; \
|
||||
fi; \
|
||||
}
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
|
|
@ -88,19 +98,24 @@ target_triplet = @target@
|
|||
sbin_PROGRAMS = upsd$(EXEEXT)
|
||||
EXTRA_PROGRAMS = sockdebug$(EXEEXT)
|
||||
subdir = server
|
||||
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
|
||||
$(top_srcdir)/depcomp
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_c___attribute__.m4 \
|
||||
$(top_srcdir)/m4/ax_c_pragmas.m4 \
|
||||
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
|
||||
$(top_srcdir)/m4/ax_compare_version.m4 \
|
||||
$(top_srcdir)/m4/ax_run_or_link_ifelse.m4 \
|
||||
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
|
||||
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
|
||||
$(top_srcdir)/m4/lt~obsolete.m4 \
|
||||
$(top_srcdir)/m4/nut_arg_with.m4 \
|
||||
$(top_srcdir)/m4/nut_check_asciidoc.m4 \
|
||||
$(top_srcdir)/m4/nut_check_cppcheck.m4 \
|
||||
$(top_srcdir)/m4/nut_check_headers_windows.m4 \
|
||||
$(top_srcdir)/m4/nut_check_libavahi.m4 \
|
||||
$(top_srcdir)/m4/nut_check_libfreeipmi.m4 \
|
||||
$(top_srcdir)/m4/nut_check_libgd.m4 \
|
||||
$(top_srcdir)/m4/nut_check_libltdl.m4 \
|
||||
$(top_srcdir)/m4/nut_check_libmodbus.m4 \
|
||||
$(top_srcdir)/m4/nut_check_libneon.m4 \
|
||||
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
|
||||
$(top_srcdir)/m4/nut_check_libnss.m4 \
|
||||
|
|
@ -109,11 +124,17 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
|
|||
$(top_srcdir)/m4/nut_check_libusb.m4 \
|
||||
$(top_srcdir)/m4/nut_check_libwrap.m4 \
|
||||
$(top_srcdir)/m4/nut_check_os.m4 \
|
||||
$(top_srcdir)/m4/nut_check_pkgconfig.m4 \
|
||||
$(top_srcdir)/m4/nut_check_python.m4 \
|
||||
$(top_srcdir)/m4/nut_compiler_family.m4 \
|
||||
$(top_srcdir)/m4/nut_func_getnameinfo_argtypes.m4 \
|
||||
$(top_srcdir)/m4/nut_report_feature.m4 \
|
||||
$(top_srcdir)/m4/nut_stash_warnings.m4 \
|
||||
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
|
||||
$(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/include/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
|
|
@ -126,8 +147,8 @@ sockdebug_LDADD = $(LDADD)
|
|||
am__DEPENDENCIES_1 =
|
||||
@WITH_WRAP_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
|
||||
@WITH_SSL_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
|
||||
sockdebug_DEPENDENCIES = ../common/libcommon.la \
|
||||
../common/libparseconf.la $(am__DEPENDENCIES_1) \
|
||||
sockdebug_DEPENDENCIES = $(top_builddir)/common/libcommon.la \
|
||||
$(top_builddir)/common/libparseconf.la $(am__DEPENDENCIES_1) \
|
||||
$(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3)
|
||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||
|
|
@ -139,9 +160,9 @@ am_upsd_OBJECTS = upsd.$(OBJEXT) user.$(OBJEXT) conf.$(OBJEXT) \
|
|||
netuser.$(OBJEXT) netset.$(OBJEXT) netinstcmd.$(OBJEXT)
|
||||
upsd_OBJECTS = $(am_upsd_OBJECTS)
|
||||
upsd_LDADD = $(LDADD)
|
||||
upsd_DEPENDENCIES = ../common/libcommon.la ../common/libparseconf.la \
|
||||
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
|
||||
$(am__DEPENDENCIES_3)
|
||||
upsd_DEPENDENCIES = $(top_builddir)/common/libcommon.la \
|
||||
$(top_builddir)/common/libparseconf.la $(am__DEPENDENCIES_1) \
|
||||
$(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3)
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
|
|
@ -156,7 +177,13 @@ am__v_at_0 = @
|
|||
am__v_at_1 =
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__maybe_remake_depfiles = depfiles
|
||||
am__depfiles_remade = ./$(DEPDIR)/conf.Po ./$(DEPDIR)/desc.Po \
|
||||
./$(DEPDIR)/netget.Po ./$(DEPDIR)/netinstcmd.Po \
|
||||
./$(DEPDIR)/netlist.Po ./$(DEPDIR)/netmisc.Po \
|
||||
./$(DEPDIR)/netset.Po ./$(DEPDIR)/netssl.Po \
|
||||
./$(DEPDIR)/netuser.Po ./$(DEPDIR)/sockdebug.Po \
|
||||
./$(DEPDIR)/sstate.Po ./$(DEPDIR)/upsd.Po ./$(DEPDIR)/user.Po
|
||||
am__mv = mv -f
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
|
|
@ -202,6 +229,7 @@ am__define_uniq_tagged_files = \
|
|||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
A2X = @A2X@
|
||||
ACLOCAL = @ACLOCAL@
|
||||
|
|
@ -210,6 +238,7 @@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
|||
AR = @AR@
|
||||
ASCIIDOC = @ASCIIDOC@
|
||||
ASPELL = @ASPELL@
|
||||
AUGPARSE = @AUGPARSE@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
|
|
@ -220,6 +249,7 @@ CCDEPMODE = @CCDEPMODE@
|
|||
CFLAGS = @CFLAGS@
|
||||
CONFPATH = @CONFPATH@
|
||||
CPP = @CPP@
|
||||
CPPCHECK = @CPPCHECK@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@
|
||||
CPPUNIT_LIBS = @CPPUNIT_LIBS@
|
||||
|
|
@ -233,6 +263,7 @@ DEFS = @DEFS@
|
|||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DOC_BUILD_LIST = @DOC_BUILD_LIST@
|
||||
DOC_CHECK_LIST = @DOC_CHECK_LIST@
|
||||
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
|
||||
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
|
||||
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
|
||||
|
|
@ -245,6 +276,7 @@ ECHO_T = @ECHO_T@
|
|||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GDLIB_CONFIG = @GDLIB_CONFIG@
|
||||
GREP = @GREP@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
|
@ -262,6 +294,8 @@ LIBIPMI_CFLAGS = @LIBIPMI_CFLAGS@
|
|||
LIBIPMI_LIBS = @LIBIPMI_LIBS@
|
||||
LIBLTDL_CFLAGS = @LIBLTDL_CFLAGS@
|
||||
LIBLTDL_LIBS = @LIBLTDL_LIBS@
|
||||
LIBMODBUS_CFLAGS = @LIBMODBUS_CFLAGS@
|
||||
LIBMODBUS_LIBS = @LIBMODBUS_LIBS@
|
||||
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
|
||||
LIBNEON_LIBS = @LIBNEON_LIBS@
|
||||
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
|
||||
|
|
@ -272,21 +306,29 @@ LIBPOWERMAN_LIBS = @LIBPOWERMAN_LIBS@
|
|||
LIBS = @LIBS@
|
||||
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
|
||||
LIBSSL_LIBS = @LIBSSL_LIBS@
|
||||
LIBSSL_REQUIRES = @LIBSSL_REQUIRES@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIBTOOL_DEPS = @LIBTOOL_DEPS@
|
||||
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
|
||||
LIBUSB_CONFIG = @LIBUSB_CONFIG@
|
||||
LIBUSB_LIBS = @LIBUSB_LIBS@
|
||||
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
|
||||
LIBWRAP_LIBS = @LIBWRAP_LIBS@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LN_S_R = @LN_S_R@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
|
||||
MAINT = @MAINT@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NETLIBS = @NETLIBS@
|
||||
NET_SNMP_CONFIG = @NET_SNMP_CONFIG@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
NUT_DATADIR = @NUT_DATADIR@
|
||||
NUT_LIBEXECDIR = @NUT_LIBEXECDIR@
|
||||
NUT_NETVERSION = @NUT_NETVERSION@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
|
|
@ -306,6 +348,9 @@ PKG_CONFIG = @PKG_CONFIG@
|
|||
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
||||
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||
PORT = @PORT@
|
||||
PYTHON = @PYTHON@
|
||||
PYTHON2 = @PYTHON2@
|
||||
PYTHON3 = @PYTHON3@
|
||||
RANLIB = @RANLIB@
|
||||
RUN_AS_GROUP = @RUN_AS_GROUP@
|
||||
RUN_AS_USER = @RUN_AS_USER@
|
||||
|
|
@ -319,6 +364,7 @@ STATEPATH = @STATEPATH@
|
|||
STRIP = @STRIP@
|
||||
SUN_LIBUSB = @SUN_LIBUSB@
|
||||
TREE_VERSION = @TREE_VERSION@
|
||||
VALGRIND = @VALGRIND@
|
||||
VERSION = @VERSION@
|
||||
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
|
||||
XMLLINT = @XMLLINT@
|
||||
|
|
@ -336,6 +382,7 @@ am__leading_dot = @am__leading_dot@
|
|||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
auglensdir = @auglensdir@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
|
|
@ -349,6 +396,9 @@ datarootdir = @datarootdir@
|
|||
devddir = @devddir@
|
||||
docdir = @docdir@
|
||||
driverexecdir = @driverexecdir@
|
||||
dummy_PKG_CONFIG = @dummy_PKG_CONFIG@
|
||||
dummy_PKG_CONFIG_CFLAGS = @dummy_PKG_CONFIG_CFLAGS@
|
||||
dummy_PKG_CONFIG_LIBS = @dummy_PKG_CONFIG_LIBS@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
|
|
@ -374,12 +424,14 @@ pkgconfigdir = @pkgconfigdir@
|
|||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
runstatedir = @runstatedir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
systemdsystemshutdowndir = @systemdsystemshutdowndir@
|
||||
systemdshutdowndir = @systemdshutdowndir@
|
||||
systemdsystemunitdir = @systemdsystemunitdir@
|
||||
systemdtmpfilesdir = @systemdtmpfilesdir@
|
||||
target = @target@
|
||||
target_alias = @target_alias@
|
||||
target_cpu = @target_cpu@
|
||||
|
|
@ -394,7 +446,8 @@ udevdir = @udevdir@
|
|||
# files. In any case, CFLAGS are only -I options, so there is no harm,
|
||||
# but only add them if we really use the target.
|
||||
AM_CFLAGS = -I$(top_srcdir)/include $(am__append_1) $(am__append_2)
|
||||
LDADD = ../common/libcommon.la ../common/libparseconf.la $(NETLIBS) \
|
||||
LDADD = $(top_builddir)/common/libcommon.la \
|
||||
$(top_builddir)/common/libparseconf.la $(NETLIBS) \
|
||||
$(am__append_3) $(am__append_4)
|
||||
upsd_SOURCES = upsd.c user.c conf.c netssl.c sstate.c desc.c \
|
||||
netget.c netmisc.c netlist.c netuser.c netset.c netinstcmd.c \
|
||||
|
|
@ -403,6 +456,7 @@ upsd_SOURCES = upsd.c user.c conf.c netssl.c sstate.c desc.c \
|
|||
upstype.h user-data.h user.h
|
||||
|
||||
sockdebug_SOURCES = sockdebug.c
|
||||
MAINTAINERCLEANFILES = Makefile.in .dirstamp
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
|
|
@ -419,14 +473,13 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
|
|||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu server/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu server/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
|
|
@ -501,19 +554,25 @@ mostlyclean-compile:
|
|||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/desc.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netget.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netinstcmd.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netlist.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netmisc.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netset.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netssl.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netuser.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sockdebug.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sstate.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsd.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/user.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/desc.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netget.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netinstcmd.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netlist.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netmisc.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netset.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netssl.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netuser.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sockdebug.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sstate.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsd.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/user.Po@am__quote@ # am--include-marker
|
||||
|
||||
$(am__depfiles_remade):
|
||||
@$(MKDIR_P) $(@D)
|
||||
@echo '# dummy' >$@-t && $(am__mv) $@-t $@
|
||||
|
||||
am--depfiles: $(am__depfiles_remade)
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
|
||||
|
|
@ -597,7 +656,10 @@ cscopelist-am: $(am__tagged_files)
|
|||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
distdir-am: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
|
|
@ -664,13 +726,26 @@ distclean-generic:
|
|||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \
|
||||
mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f ./$(DEPDIR)/conf.Po
|
||||
-rm -f ./$(DEPDIR)/desc.Po
|
||||
-rm -f ./$(DEPDIR)/netget.Po
|
||||
-rm -f ./$(DEPDIR)/netinstcmd.Po
|
||||
-rm -f ./$(DEPDIR)/netlist.Po
|
||||
-rm -f ./$(DEPDIR)/netmisc.Po
|
||||
-rm -f ./$(DEPDIR)/netset.Po
|
||||
-rm -f ./$(DEPDIR)/netssl.Po
|
||||
-rm -f ./$(DEPDIR)/netuser.Po
|
||||
-rm -f ./$(DEPDIR)/sockdebug.Po
|
||||
-rm -f ./$(DEPDIR)/sstate.Po
|
||||
-rm -f ./$(DEPDIR)/upsd.Po
|
||||
-rm -f ./$(DEPDIR)/user.Po
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
|
@ -716,7 +791,19 @@ install-ps-am:
|
|||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f ./$(DEPDIR)/conf.Po
|
||||
-rm -f ./$(DEPDIR)/desc.Po
|
||||
-rm -f ./$(DEPDIR)/netget.Po
|
||||
-rm -f ./$(DEPDIR)/netinstcmd.Po
|
||||
-rm -f ./$(DEPDIR)/netlist.Po
|
||||
-rm -f ./$(DEPDIR)/netmisc.Po
|
||||
-rm -f ./$(DEPDIR)/netset.Po
|
||||
-rm -f ./$(DEPDIR)/netssl.Po
|
||||
-rm -f ./$(DEPDIR)/netuser.Po
|
||||
-rm -f ./$(DEPDIR)/sockdebug.Po
|
||||
-rm -f ./$(DEPDIR)/sstate.Po
|
||||
-rm -f ./$(DEPDIR)/upsd.Po
|
||||
-rm -f ./$(DEPDIR)/user.Po
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
|
|
@ -737,9 +824,9 @@ uninstall-am: uninstall-sbinPROGRAMS
|
|||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
|
||||
clean-libtool clean-sbinPROGRAMS cscopelist-am ctags ctags-am \
|
||||
distclean distclean-compile distclean-generic \
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
|
||||
clean-generic clean-libtool clean-sbinPROGRAMS cscopelist-am \
|
||||
ctags ctags-am distclean distclean-compile distclean-generic \
|
||||
distclean-libtool distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-data \
|
||||
install-data-am install-dvi install-dvi-am install-exec \
|
||||
|
|
@ -751,6 +838,20 @@ uninstall-am: uninstall-sbinPROGRAMS
|
|||
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||
tags tags-am uninstall uninstall-am uninstall-sbinPROGRAMS
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
# Make sure out-of-dir dependencies exist (especially when dev-building parts):
|
||||
$(top_builddir)/common/libcommon.la \
|
||||
$(top_builddir)/common/libparseconf.la: dummy
|
||||
@cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F)
|
||||
|
||||
dummy:
|
||||
|
||||
# NOTE: Do not clean ".deps" in SUBDIRS of the main project,
|
||||
# the root Makefile.am takes care of that!
|
||||
#clean-local:
|
||||
# rm -rf $(builddir)/.deps
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
|
|
|
|||
143
server/conf.c
143
server/conf.c
|
|
@ -23,9 +23,19 @@
|
|||
#include "sstate.h"
|
||||
#include "user.h"
|
||||
#include "netssl.h"
|
||||
#include "nut_stdint.h"
|
||||
#include <ctype.h>
|
||||
|
||||
ups_t *upstable = NULL;
|
||||
int num_ups = 0;
|
||||
static ups_t *upstable = NULL;
|
||||
int num_ups = 0;
|
||||
|
||||
/* Users can pass a -D[...] option to enable debugging.
|
||||
* For the service tracing purposes, also the upsd.conf
|
||||
* can define a debug_min value in the global section,
|
||||
* to set the minimal debug level (CLI provided value less
|
||||
* than that would not have effect, can only have more).
|
||||
*/
|
||||
int nut_debug_level_global = -1;
|
||||
|
||||
/* add another UPS for monitoring from ups.conf */
|
||||
static void ups_create(const char *fn, const char *name, const char *desc)
|
||||
|
|
@ -110,25 +120,91 @@ static void ups_update(const char *fn, const char *name, const char *desc)
|
|||
|
||||
/* always set this on reload */
|
||||
temp->retain = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* returns 1 if "arg" was usable as a boolean value, 0 if not
|
||||
* saves converted meaning of "arg" into referenced "result"
|
||||
*/
|
||||
static int parse_boolean(char *arg, int *result)
|
||||
{
|
||||
if ( (!strcasecmp(arg, "true")) || (!strcasecmp(arg, "on")) || (!strcasecmp(arg, "yes")) || (!strcasecmp(arg, "1"))) {
|
||||
*result = 1;
|
||||
return 1;
|
||||
}
|
||||
if ( (!strcasecmp(arg, "false")) || (!strcasecmp(arg, "off")) || (!strcasecmp(arg, "no")) || (!strcasecmp(arg, "0"))) {
|
||||
*result = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return 1 if usable, 0 if not */
|
||||
static int parse_upsd_conf_args(int numargs, char **arg)
|
||||
static int parse_upsd_conf_args(size_t numargs, char **arg)
|
||||
{
|
||||
/* everything below here uses up through arg[1] */
|
||||
if (numargs < 2)
|
||||
return 0;
|
||||
|
||||
/* DEBUG_MIN (NUM) */
|
||||
/* debug_min (NUM) also acceptable, to be on par with ups.conf */
|
||||
if (!strcasecmp(arg[0], "DEBUG_MIN")) {
|
||||
int lvl = -1; // typeof common/common.c: int nut_debug_level
|
||||
if ( str_to_int (arg[1], &lvl, 10) && lvl >= 0 ) {
|
||||
nut_debug_level_global = lvl;
|
||||
} else {
|
||||
upslogx(LOG_INFO, "DEBUG_MIN has non numeric or negative value in upsd.conf");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* MAXAGE <seconds> */
|
||||
if (!strcmp(arg[0], "MAXAGE")) {
|
||||
maxage = atoi(arg[1]);
|
||||
return 1;
|
||||
if (isdigit((size_t)arg[1][0])) {
|
||||
maxage = atoi(arg[1]);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
upslogx(LOG_ERR, "MAXAGE has non numeric value (%s)!", arg[1]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* TRACKINGDELAY <seconds> */
|
||||
if (!strcmp(arg[0], "TRACKINGDELAY")) {
|
||||
if (isdigit((size_t)arg[1][0])) {
|
||||
tracking_delay = atoi(arg[1]);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
upslogx(LOG_ERR, "TRACKINGDELAY has non numeric value (%s)!", arg[1]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ALLOW_NO_DEVICE <seconds> */
|
||||
if (!strcmp(arg[0], "ALLOW_NO_DEVICE")) {
|
||||
if (isdigit((size_t)arg[1][0])) {
|
||||
allow_no_device = (atoi(arg[1]) != 0); /* non-zero arg is true here */
|
||||
return 1;
|
||||
}
|
||||
if (parse_boolean(arg[1], &allow_no_device))
|
||||
return 1;
|
||||
|
||||
upslogx(LOG_ERR, "ALLOW_NO_DEVICE has non numeric and non boolean value (%s)!", arg[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* MAXCONN <connections> */
|
||||
if (!strcmp(arg[0], "MAXCONN")) {
|
||||
maxconn = atoi(arg[1]);
|
||||
return 1;
|
||||
if (isdigit((size_t)arg[1][0])) {
|
||||
/* FIXME: Check for overflows (and int size of nfds_t vs. long) - see get_max_pid_t() for example */
|
||||
maxconn = (nfds_t)atol(arg[1]);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
upslogx(LOG_ERR, "MAXCONN has non numeric value (%s)!", arg[1]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* STATEPATH <dir> */
|
||||
|
|
@ -162,12 +238,29 @@ static int parse_upsd_conf_args(int numargs, char **arg)
|
|||
#ifdef WITH_CLIENT_CERTIFICATE_VALIDATION
|
||||
/* CERTREQUEST (0 | 1 | 2) */
|
||||
if (!strcmp(arg[0], "CERTREQUEST")) {
|
||||
certrequest = atoi(arg[1]);
|
||||
return 1;
|
||||
if (isdigit((size_t)arg[1][0])) {
|
||||
certrequest = atoi(arg[1]);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
upslogx(LOG_ERR, "CERTREQUEST has non numeric value (%s)!", arg[1]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif /* WITH_CLIENT_CERTIFICATE_VALIDATION */
|
||||
#endif /* WITH_OPENSSL | WITH_NSS */
|
||||
|
||||
|
||||
#if defined(WITH_OPENSSL) || defined(WITH_NSS)
|
||||
/* DISABLE_WEAK_SSL <bool> */
|
||||
if (!strcmp(arg[0], "DISABLE_WEAK_SSL")) {
|
||||
if (parse_boolean(arg[1], &disable_weak_ssl))
|
||||
return 1;
|
||||
|
||||
upslogx(LOG_ERR, "DISABLE_WEAK_SSL has non boolean value (%s)!", arg[1]);
|
||||
return 0;
|
||||
}
|
||||
#endif /* WITH_OPENSSL | WITH_NSS */
|
||||
|
||||
/* ACCEPT <aclname> [<aclname>...] */
|
||||
if (!strcmp(arg[0], "ACCEPT")) {
|
||||
upslogx(LOG_WARNING, "ACCEPT in upsd.conf is no longer supported - switch to LISTEN");
|
||||
|
|
@ -198,7 +291,7 @@ static int parse_upsd_conf_args(int numargs, char **arg)
|
|||
upslogx(LOG_WARNING, "ACL in upsd.conf is no longer supported - switch to LISTEN");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WITH_NSS
|
||||
/* CERTIDENT <name> <passwd> */
|
||||
if (!strcmp(arg[0], "CERTIDENT")) {
|
||||
|
|
@ -241,6 +334,13 @@ void load_upsdconf(int reloading)
|
|||
return;
|
||||
}
|
||||
|
||||
if (reloading) {
|
||||
/* if upsd.conf added or changed
|
||||
* (or commented away) the debug_min
|
||||
* setting, detect that */
|
||||
nut_debug_level_global = -1;
|
||||
}
|
||||
|
||||
while (pconf_file_next(&ctx)) {
|
||||
if (pconf_parse_error(&ctx)) {
|
||||
upslogx(LOG_ERR, "Parse error: %s:%d: %s",
|
||||
|
|
@ -255,11 +355,11 @@ void load_upsdconf(int reloading)
|
|||
unsigned int i;
|
||||
char errmsg[SMALLBUF];
|
||||
|
||||
snprintf(errmsg, sizeof(errmsg),
|
||||
snprintf(errmsg, sizeof(errmsg),
|
||||
"upsd.conf: invalid directive");
|
||||
|
||||
for (i = 0; i < ctx.numargs; i++)
|
||||
snprintfcat(errmsg, sizeof(errmsg), " %s",
|
||||
snprintfcat(errmsg, sizeof(errmsg), " %s",
|
||||
ctx.arglist[i]);
|
||||
|
||||
upslogx(LOG_WARNING, "%s", errmsg);
|
||||
|
|
@ -267,7 +367,16 @@ void load_upsdconf(int reloading)
|
|||
|
||||
}
|
||||
|
||||
pconf_finish(&ctx);
|
||||
if (reloading) {
|
||||
if (nut_debug_level_global > -1) {
|
||||
upslogx(LOG_INFO,
|
||||
"Applying debug_min=%d from upsd.conf",
|
||||
nut_debug_level_global);
|
||||
nut_debug_level = nut_debug_level_global;
|
||||
}
|
||||
}
|
||||
|
||||
pconf_finish(&ctx);
|
||||
}
|
||||
|
||||
/* callback during parsing of ups.conf */
|
||||
|
|
@ -331,7 +440,7 @@ void upsconf_add(int reloading)
|
|||
|
||||
/* don't accept an entry that's missing items */
|
||||
if ((!tmp->driver) || (!tmp->port)) {
|
||||
upslogx(LOG_WARNING, "Warning: ignoring incomplete configuration for UPS [%s]\n",
|
||||
upslogx(LOG_WARNING, "Warning: ignoring incomplete configuration for UPS [%s]\n",
|
||||
tmp->upsname);
|
||||
} else {
|
||||
snprintf(statefn, sizeof(statefn), "%s-%s",
|
||||
|
|
@ -404,7 +513,7 @@ static void delete_ups(upstype_t *target)
|
|||
|
||||
/* shouldn't happen */
|
||||
upslogx(LOG_ERR, "delete_ups: UPS not found");
|
||||
}
|
||||
}
|
||||
|
||||
/* see if we can open a file */
|
||||
static int check_file(const char *fn)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
Copyright (C)
|
||||
2001 Russell Kroll <rkroll@exploits.org>
|
||||
2008 Arjen de Korte <adkorte-guest@alioth.debian.org>
|
||||
2020 Jim Klimov <jimklimov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -19,6 +20,9 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef NUT_CONF_H_SEEN
|
||||
#define NUT_CONF_H_SEEN 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
extern "C" {
|
||||
|
|
@ -47,6 +51,7 @@ void delete_acls(void);
|
|||
void delete_access(void);
|
||||
|
||||
extern int num_ups;
|
||||
extern int nut_debug_level_global;
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
|
|
@ -54,3 +59,4 @@ extern int num_ups;
|
|||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#endif /* NUT_CONF_H_SEEN */
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h" /* must be the first header */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "common.h"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,28 @@
|
|||
/* desc.h - variable/command description handling for upsd
|
||||
|
||||
Copyright (C)
|
||||
2003 Russell Kroll <rkroll@exploits.org>
|
||||
2005 Arnaud Quette <arnaud.quette@free.fr>
|
||||
2013 Emilien Kia <kiae.dev@gmail.com>
|
||||
2020 Jim Klimov <jimklimov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef NUT_DESC_H_SEEN
|
||||
#define NUT_DESC_H_SEEN 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
|
|
@ -16,3 +41,4 @@ const char *desc_get_var(const char *name);
|
|||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#endif /* NUT_DESC_H_SEEN */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
/* netcmds.h - upsd support structure details
|
||||
|
||||
Copyright (C) 2001 Russell Kroll <rkroll@exploits.org>
|
||||
2005 Arnaud Quette <arnaud.quette@free.fr>
|
||||
2007 Peter Selinger <selinger@users.sourceforge.net>
|
||||
2010 Arjen de Korte <adkorte-guest@alioth.debian.org>
|
||||
2012 Emilien Kia <kiae.dev@gmail.com>
|
||||
2020 Jim Klimov <jimklimov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -17,6 +22,9 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef NUT_NETCMDS_H_SEEN
|
||||
#define NUT_NETCMDS_H_SEEN 1
|
||||
|
||||
#include "nut_ctype.h"
|
||||
|
||||
#include "netssl.h"
|
||||
|
|
@ -35,13 +43,14 @@ extern "C" {
|
|||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
struct {
|
||||
static struct {
|
||||
const char *name;
|
||||
void (*func)(nut_ctype_t *client, int numargs, const char **arg);
|
||||
void (*func)(nut_ctype_t *client, size_t numargs, const char **arg);
|
||||
int flags;
|
||||
} netcmds[] = {
|
||||
{ "VER", net_ver, 0 },
|
||||
{ "NETVER", net_netver, 0 },
|
||||
{ "PROTVER", net_netver, 0 }, /* aliased since NUT 2.8.0 */
|
||||
{ "HELP", net_help, 0 },
|
||||
{ "STARTTLS", net_starttls, 0 },
|
||||
|
||||
|
|
@ -53,6 +62,10 @@ struct {
|
|||
|
||||
{ "LOGIN", net_login, FLAG_USER },
|
||||
{ "LOGOUT", net_logout, 0 },
|
||||
/* NOTE: Protocol in NUT 2.8.0 allows to handle
|
||||
* master/primary to rename/alias the routine.
|
||||
*/
|
||||
{ "PRIMARY", net_primary, FLAG_USER },
|
||||
{ "MASTER", net_master, FLAG_USER },
|
||||
|
||||
{ "FSD", net_fsd, FLAG_USER },
|
||||
|
|
@ -60,7 +73,7 @@ struct {
|
|||
{ "SET", net_set, FLAG_USER },
|
||||
{ "INSTCMD", net_instcmd, FLAG_USER },
|
||||
|
||||
{ NULL, (void(*)())(NULL), 0 }
|
||||
{ NULL, (void(*)(struct nut_ctype_s *, size_t, const char **))(NULL), 0 }
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -69,3 +82,4 @@ struct {
|
|||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#endif /* NUT_NETCMDS_H_SEEN */
|
||||
|
|
|
|||
|
|
@ -1,3 +1,35 @@
|
|||
/* neterr.h - network error definitions for NUT
|
||||
|
||||
Copyright (C)
|
||||
2003 Russell Kroll <rkroll@exploits.org>
|
||||
2005 Arnaud Quette <arnaud.quette@free.fr>
|
||||
2013 Emilien Kia <kiae.dev@gmail.com>
|
||||
2020 Jim Klimov <jimklimov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef NUT_NETERR_H_SEEN
|
||||
#define NUT_NETERR_H_SEEN 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
extern "C" {
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
/* network error definitions for consistency */
|
||||
|
||||
#define NUT_ERR_ACCESS_DENIED "ACCESS-DENIED"
|
||||
|
|
@ -33,3 +65,11 @@
|
|||
#define NUT_ERR_UNKNOWN_INSTCMD "UNKNOWN-INSTCMD"
|
||||
#define NUT_ERR_MISSING_ARGUMENT "MISSING-ARGUMENT"
|
||||
#define NUT_ERR_INVALID_VALUE "INVALID-VALUE"
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
}
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#endif /* NUT_NETERR_H_SEEN */
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ static void get_cmddesc(nut_ctype_t *client, const char *upsname, const char *cm
|
|||
if (desc)
|
||||
sendback(client, "CMDDESC %s %s \"%s\"\n", upsname, cmd, desc);
|
||||
else
|
||||
sendback(client, "CMDDESC %s %s \"Description unavailable\"\n",
|
||||
sendback(client, "CMDDESC %s %s \"Description unavailable\"\n",
|
||||
upsname, cmd);
|
||||
}
|
||||
|
||||
|
|
@ -142,38 +142,36 @@ static void get_type(nut_ctype_t *client, const char *upsname, const char *var)
|
|||
snprintfcat(buf, sizeof(buf), " RW");
|
||||
|
||||
if (node->enum_list) {
|
||||
sendback(client, "%s ENUM\n", buf);
|
||||
return;
|
||||
snprintfcat(buf, sizeof(buf), " ENUM");
|
||||
}
|
||||
|
||||
if (node->range_list) {
|
||||
sendback(client, "%s RANGE\n", buf);
|
||||
return;
|
||||
snprintfcat(buf, sizeof(buf), " RANGE");
|
||||
}
|
||||
|
||||
if (node->flags & ST_FLAG_STRING) {
|
||||
sendback(client, "%s STRING:%d\n", buf, node->aux);
|
||||
sendback(client, "%s STRING:%ld\n", buf, node->aux);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Any variable that is not string | range | enum is just a simple
|
||||
* numeric value */
|
||||
|
||||
sendback(client, "TYPE %s %s NUMBER\n", upsname, var);
|
||||
}
|
||||
sendback(client, "%s NUMBER\n", buf);
|
||||
}
|
||||
|
||||
static void get_var_server(nut_ctype_t *client, const char *upsname, const char *var)
|
||||
{
|
||||
if (!strcasecmp(var, "server.info")) {
|
||||
sendback(client, "VAR %s server.info "
|
||||
"\"Network UPS Tools upsd %s - "
|
||||
"http://www.networkupstools.org/\"\n",
|
||||
"http://www.networkupstools.org/\"\n",
|
||||
upsname, UPS_VERSION);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcasecmp(var, "server.version")) {
|
||||
sendback(client, "VAR %s server.version \"%s\"\n",
|
||||
sendback(client, "VAR %s server.version \"%s\"\n",
|
||||
upsname, UPS_VERSION);
|
||||
return;
|
||||
}
|
||||
|
|
@ -216,8 +214,27 @@ static void get_var(nut_ctype_t *client, const char *upsname, const char *var)
|
|||
sendback(client, "VAR %s %s \"%s\"\n", upsname, var, val);
|
||||
}
|
||||
|
||||
void net_get(nut_ctype_t *client, int numarg, const char **arg)
|
||||
void net_get(nut_ctype_t *client, size_t numarg, const char **arg)
|
||||
{
|
||||
if (numarg < 1) {
|
||||
send_err(client, NUT_ERR_INVALID_ARGUMENT);
|
||||
return;
|
||||
}
|
||||
|
||||
/* GET TRACKING [ID] */
|
||||
if (!strcasecmp(arg[0], "TRACKING")) {
|
||||
if (numarg < 2) {
|
||||
sendback(client, "%s\n", (client->tracking) ? "ON" : "OFF");
|
||||
}
|
||||
else {
|
||||
if (client->tracking)
|
||||
sendback(client, "%s\n", tracking_get(arg[1]));
|
||||
else
|
||||
send_err(client, NUT_ERR_FEATURE_NOT_CONFIGURED);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (numarg < 2) {
|
||||
send_err(client, NUT_ERR_INVALID_ARGUMENT);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,37 @@
|
|||
/* netget.h - GET handlers for upsd
|
||||
|
||||
Copyright (C)
|
||||
2003 Russell Kroll <rkroll@exploits.org>
|
||||
2005 Arnaud Quette <arnaud.quette@free.fr>
|
||||
2007 Peter Selinger <selinger@users.sourceforge.net>
|
||||
2013 Emilien Kia <kiae.dev@gmail.com>
|
||||
2020 Jim Klimov <jimklimov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef NUT_NETGET_H_SEEN
|
||||
#define NUT_NETGET_H_SEEN 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
extern "C" {
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
void net_get(nut_ctype_t *client, int numarg, const char **arg);
|
||||
void net_get(nut_ctype_t *client, size_t numarg, const char **arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
|
|
@ -12,3 +39,4 @@ void net_get(nut_ctype_t *client, int numarg, const char **arg);
|
|||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#endif /* NUT_NETGET_H_SEEN */
|
||||
|
|
|
|||
|
|
@ -28,10 +28,10 @@
|
|||
|
||||
#include "netinstcmd.h"
|
||||
|
||||
static void send_instcmd(nut_ctype_t *client, const char *upsname,
|
||||
const char *cmdname, const char *value)
|
||||
static void send_instcmd(nut_ctype_t *client, const char *upsname,
|
||||
const char *cmdname, const char *value, const char *tracking_id)
|
||||
{
|
||||
int found;
|
||||
int found, have_tracking_id = 0;
|
||||
upstype_t *ups;
|
||||
const cmdlist_t *ctmp;
|
||||
char sockcmd[SMALLBUF], esc[SMALLBUF];
|
||||
|
|
@ -70,20 +70,30 @@ static void send_instcmd(nut_ctype_t *client, const char *upsname,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Format the base command */
|
||||
snprintf(sockcmd, sizeof(sockcmd), "INSTCMD %s", cmdname);
|
||||
|
||||
/* see if the user has also passed a value for this command */
|
||||
if (value != NULL) {
|
||||
upslogx(LOG_INFO, "Instant command: %s@%s did %s with value \"%s\" on %s",
|
||||
client->username, client->addr, cmdname, value, ups->name);
|
||||
if (value != NULL)
|
||||
snprintfcat(sockcmd, sizeof(sockcmd), " %s", pconf_encode(value, esc, sizeof(esc)));
|
||||
|
||||
snprintf(sockcmd, sizeof(sockcmd), "INSTCMD %s %s\n",
|
||||
cmdname, pconf_encode(value, esc, sizeof(esc)));
|
||||
/* see if the user want execution tracking for this command */
|
||||
if (tracking_id && *tracking_id) {
|
||||
snprintfcat(sockcmd, sizeof(sockcmd), " TRACKING %s", tracking_id);
|
||||
/* Add an entry in the tracking structure */
|
||||
tracking_add(tracking_id);
|
||||
have_tracking_id = 1;
|
||||
}
|
||||
else {
|
||||
upslogx(LOG_INFO, "Instant command: %s@%s did %s on %s",
|
||||
client->username, client->addr, cmdname, ups->name);
|
||||
|
||||
snprintf(sockcmd, sizeof(sockcmd), "INSTCMD %s\n", cmdname);
|
||||
}
|
||||
/* add EOL */
|
||||
snprintfcat(sockcmd, sizeof(sockcmd), "\n");
|
||||
|
||||
upslogx(LOG_INFO, "Instant command: %s@%s did %s%s%s on %s (tracking ID: %s)",
|
||||
client->username, client->addr, cmdname,
|
||||
(value != NULL)?" with value ":"",
|
||||
(value != NULL)?value:"",
|
||||
ups->name,
|
||||
(have_tracking_id) ? tracking_id : "disabled");
|
||||
|
||||
if (!sstate_sendline(ups, sockcmd)) {
|
||||
upslogx(LOG_INFO, "Set command send failed");
|
||||
|
|
@ -91,18 +101,38 @@ static void send_instcmd(nut_ctype_t *client, const char *upsname,
|
|||
return;
|
||||
}
|
||||
|
||||
/* FIXME: need to retrieve the cookie number */
|
||||
sendback(client, "OK\n");
|
||||
/* return the result, possibly including tracking_id */
|
||||
if (have_tracking_id)
|
||||
sendback(client, "OK TRACKING %s\n", tracking_id);
|
||||
else
|
||||
sendback(client, "OK\n");
|
||||
}
|
||||
|
||||
void net_instcmd(nut_ctype_t *client, int numarg, const char **arg)
|
||||
void net_instcmd(nut_ctype_t *client, size_t numarg, const char **arg)
|
||||
{
|
||||
const char *devname = NULL;
|
||||
const char *cmdname = NULL;
|
||||
const char *cmdparam = NULL;
|
||||
char tracking_id[UUID4_LEN] = "";
|
||||
|
||||
if (numarg < 2) {
|
||||
send_err(client, NUT_ERR_INVALID_ARGUMENT);
|
||||
return;
|
||||
}
|
||||
|
||||
/* INSTCMD <ups> <cmdname> [<extra>]*/
|
||||
send_instcmd(client, arg[0], arg[1], (numarg == 3)?arg[2]:NULL);
|
||||
|
||||
/* INSTCMD <ups> <cmdname> [cmdparam] */
|
||||
/* Check arguments */
|
||||
devname = arg[0];
|
||||
cmdname = arg[1];
|
||||
if (numarg == 3)
|
||||
cmdparam = arg[2];
|
||||
|
||||
if (client->tracking) {
|
||||
/* Generate a tracking ID, if client requested status tracking */
|
||||
nut_uuid_v4(tracking_id);
|
||||
}
|
||||
|
||||
send_instcmd(client, devname, cmdname, cmdparam, tracking_id);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,37 @@
|
|||
/* netinstcmd.h - network instand command definitions for NUT
|
||||
|
||||
Copyright (C)
|
||||
2003 Russell Kroll <rkroll@exploits.org>
|
||||
2005 Arnaud Quette <arnaud.quette@free.fr>
|
||||
2007 Peter Selinger <selinger@users.sourceforge.net>
|
||||
2013 Emilien Kia <kiae.dev@gmail.com>
|
||||
2020 Jim Klimov <jimklimov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef NUT_NETINSTCMD_H_SEEN
|
||||
#define NUT_NETINSTCMD_H_SEEN 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
extern "C" {
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
void net_instcmd(nut_ctype_t *client, int numarg, const char **arg);
|
||||
void net_instcmd(nut_ctype_t *client, size_t numarg, const char **arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
|
|
@ -12,3 +39,4 @@ void net_instcmd(nut_ctype_t *client, int numarg, const char **arg);
|
|||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#endif /* NUT_NETINSTCMD_H_SEEN */
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ static int tree_dump(st_tree_t *node, nut_ctype_t *client, const char *ups,
|
|||
if (node->flags & ST_FLAG_RW) {
|
||||
ret = sendback(client, "RW %s %s \"%s\"\n",
|
||||
ups, node->var, node->val);
|
||||
|
||||
|
||||
} else {
|
||||
ret = 1; /* dummy */
|
||||
}
|
||||
|
|
@ -240,7 +240,7 @@ static void list_ups(nut_ctype_t *client)
|
|||
pconf_encode(utmp->desc, esc, sizeof(esc));
|
||||
ret = sendback(client, "UPS %s \"%s\"\n",
|
||||
utmp->name, esc);
|
||||
|
||||
|
||||
} else {
|
||||
ret = sendback(client, "UPS %s \"Description unavailable\"\n",
|
||||
utmp->name);
|
||||
|
|
@ -253,7 +253,7 @@ static void list_ups(nut_ctype_t *client)
|
|||
}
|
||||
|
||||
sendback(client, "END LIST UPS\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void list_clients(nut_ctype_t *client, const char *upsname)
|
||||
{
|
||||
|
|
@ -285,7 +285,7 @@ static void list_clients(nut_ctype_t *client, const char *upsname)
|
|||
sendback(client, "END LIST CLIENT %s\n", upsname);
|
||||
}
|
||||
|
||||
void net_list(nut_ctype_t *client, int numarg, const char **arg)
|
||||
void net_list(nut_ctype_t *client, size_t numarg, const char **arg)
|
||||
{
|
||||
if (numarg < 1) {
|
||||
send_err(client, NUT_ERR_INVALID_ARGUMENT);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,37 @@
|
|||
/* netlist.h - LIST handlers for upsd
|
||||
|
||||
Copyright (C)
|
||||
2003 Russell Kroll <rkroll@exploits.org>
|
||||
2005 Arnaud Quette <arnaud.quette@free.fr>
|
||||
2007 Peter Selinger <selinger@users.sourceforge.net>
|
||||
2013 Emilien Kia <kiae.dev@gmail.com>
|
||||
2020 Jim Klimov <jimklimov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef NUT_NETLIST_H_SEEN
|
||||
#define NUT_NETLIST_H_SEEN 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
extern "C" {
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
void net_list(nut_ctype_t *client, int numarg, const char **arg);
|
||||
void net_list(nut_ctype_t *client, size_t numarg, const char **arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
|
|
@ -12,3 +39,4 @@ void net_list(nut_ctype_t *client, int numarg, const char **arg);
|
|||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#endif /* NUT_NETLIST_H_SEEN */
|
||||
|
|
|
|||
|
|
@ -22,15 +22,16 @@
|
|||
#include "common.h"
|
||||
|
||||
#include "upsd.h"
|
||||
#include "sstate.h"
|
||||
#include "sstate.h"
|
||||
#include "state.h"
|
||||
#include "user.h" /* for user_checkaction */
|
||||
#include "neterr.h"
|
||||
|
||||
#include "netmisc.h"
|
||||
|
||||
void net_ver(nut_ctype_t *client, int numarg, const char **arg)
|
||||
void net_ver(nut_ctype_t *client, size_t numarg, const char **arg)
|
||||
{
|
||||
NUT_UNUSED_VARIABLE(arg);
|
||||
if (numarg != 0) {
|
||||
send_err(client, NUT_ERR_INVALID_ARGUMENT);
|
||||
return;
|
||||
|
|
@ -40,8 +41,9 @@ void net_ver(nut_ctype_t *client, int numarg, const char **arg)
|
|||
UPS_VERSION);
|
||||
}
|
||||
|
||||
void net_netver(nut_ctype_t *client, int numarg, const char **arg)
|
||||
void net_netver(nut_ctype_t *client, size_t numarg, const char **arg)
|
||||
{
|
||||
NUT_UNUSED_VARIABLE(arg);
|
||||
if (numarg != 0) {
|
||||
send_err(client, NUT_ERR_INVALID_ARGUMENT);
|
||||
return;
|
||||
|
|
@ -50,8 +52,9 @@ void net_netver(nut_ctype_t *client, int numarg, const char **arg)
|
|||
sendback(client, "%s\n", NUT_NETVERSION);
|
||||
}
|
||||
|
||||
void net_help(nut_ctype_t *client, int numarg, const char **arg)
|
||||
void net_help(nut_ctype_t *client, size_t numarg, const char **arg)
|
||||
{
|
||||
NUT_UNUSED_VARIABLE(arg);
|
||||
if (numarg != 0) {
|
||||
send_err(client, NUT_ERR_INVALID_ARGUMENT);
|
||||
return;
|
||||
|
|
@ -61,7 +64,7 @@ void net_help(nut_ctype_t *client, int numarg, const char **arg)
|
|||
" USERNAME PASSWORD STARTTLS\n");
|
||||
}
|
||||
|
||||
void net_fsd(nut_ctype_t *client, int numarg, const char **arg)
|
||||
void net_fsd(nut_ctype_t *client, size_t numarg, const char **arg)
|
||||
{
|
||||
upstype_t *ups;
|
||||
|
||||
|
|
@ -77,13 +80,13 @@ void net_fsd(nut_ctype_t *client, int numarg, const char **arg)
|
|||
return;
|
||||
}
|
||||
|
||||
/* make sure this user is allowed to do FSD */
|
||||
/* make sure this user is allowed to do FSD */
|
||||
if (!user_checkaction(client->username, client->password, "FSD")) {
|
||||
send_err(client, NUT_ERR_ACCESS_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
upslogx(LOG_INFO, "Client %s@%s set FSD on UPS [%s]",
|
||||
upslogx(LOG_INFO, "Client %s@%s set FSD on UPS [%s]",
|
||||
client->username, client->addr, ups->name);
|
||||
|
||||
ups->fsd = 1;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,40 @@
|
|||
/* netmisc.h - miscellaneous network handlers for upsd (VER, HELP, FSD)
|
||||
|
||||
Copyright (C)
|
||||
2003 Russell Kroll <rkroll@exploits.org>
|
||||
2007 Peter Selinger <selinger@users.sourceforge.net>
|
||||
2012 Arnaud Quette <arnaud.quette.free.fr>
|
||||
2013 Emilien Kia <kiae.dev@gmail.com>
|
||||
2020 Jim Klimov <jimklimov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef NUT_NETMISC_H_SEEN
|
||||
#define NUT_NETMISC_H_SEEN 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
extern "C" {
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
void net_ver(nut_ctype_t *client, int numarg, const char **arg);
|
||||
void net_netver(nut_ctype_t *client, int numarg, const char **arg);
|
||||
void net_help(nut_ctype_t *client, int numarg, const char **arg);
|
||||
void net_fsd(nut_ctype_t *client, int numarg, const char **arg);
|
||||
void net_ver(nut_ctype_t *client, size_t numarg, const char **arg);
|
||||
void net_netver(nut_ctype_t *client, size_t numarg, const char **arg);
|
||||
void net_help(nut_ctype_t *client, size_t numarg, const char **arg);
|
||||
void net_fsd(nut_ctype_t *client, size_t numarg, const char **arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
|
|
@ -15,3 +42,4 @@ void net_fsd(nut_ctype_t *client, int numarg, const char **arg);
|
|||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#endif /* NUT_NETMISC_H_SEEN */
|
||||
|
|
|
|||
|
|
@ -28,13 +28,14 @@
|
|||
#include "netset.h"
|
||||
|
||||
static void set_var(nut_ctype_t *client, const char *upsname, const char *var,
|
||||
const char *newval)
|
||||
const char *newval, const char *tracking_id)
|
||||
{
|
||||
upstype_t *ups;
|
||||
const char *val;
|
||||
const enum_t *etmp;
|
||||
const range_t *rtmp;
|
||||
char cmd[SMALLBUF], esc[SMALLBUF];
|
||||
int have_tracking_id = 0;
|
||||
|
||||
ups = get_ups_ptr(upsname);
|
||||
|
||||
|
|
@ -68,7 +69,7 @@ static void set_var(nut_ctype_t *client, const char *upsname, const char *var,
|
|||
/* see if the new value is allowed for this variable */
|
||||
|
||||
if (sstate_getflags(ups, var) & ST_FLAG_STRING) {
|
||||
int aux;
|
||||
long aux;
|
||||
|
||||
aux = sstate_getaux(ups, var);
|
||||
|
||||
|
|
@ -81,6 +82,10 @@ static void set_var(nut_ctype_t *client, const char *upsname, const char *var,
|
|||
return;
|
||||
}
|
||||
|
||||
/* FIXME? Should this cast to "long"?
|
||||
* An int-size string is quite a lot already,
|
||||
* even on architectures with a moderate INTMAX
|
||||
*/
|
||||
if (aux < (int) strlen(newval)) {
|
||||
send_err(client, NUT_ERR_TOO_LONG);
|
||||
return;
|
||||
|
|
@ -134,31 +139,92 @@ static void set_var(nut_ctype_t *client, const char *upsname, const char *var,
|
|||
|
||||
/* must be OK now */
|
||||
|
||||
upslogx(LOG_INFO, "Set variable: %s@%s set %s on %s to %s",
|
||||
client->username, client->addr, var, ups->name, newval);
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "SET %s \"%s\"\n",
|
||||
snprintf(cmd, sizeof(cmd), "SET %s \"%s\"",
|
||||
var, pconf_encode(newval, esc, sizeof(esc)));
|
||||
|
||||
/* see if the user want execution tracking for this command */
|
||||
if (tracking_id && *tracking_id) {
|
||||
snprintfcat(cmd, sizeof(cmd), " TRACKING %s", tracking_id);
|
||||
/* Add an entry in the tracking structure */
|
||||
tracking_add(tracking_id);
|
||||
have_tracking_id = 1;
|
||||
}
|
||||
|
||||
/* add EOL */
|
||||
snprintfcat(cmd, sizeof(cmd), "\n");
|
||||
|
||||
upslogx(LOG_INFO, "Set variable: %s@%s set %s on %s to %s (tracking ID: %s)",
|
||||
client->username, client->addr, var, ups->name, newval,
|
||||
(have_tracking_id) ? tracking_id : "disabled");
|
||||
|
||||
if (!sstate_sendline(ups, cmd)) {
|
||||
upslogx(LOG_INFO, "Set command send failed");
|
||||
send_err(client, NUT_ERR_SET_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
sendback(client, "OK\n");
|
||||
/* return the result, possibly including tracking_id */
|
||||
if (have_tracking_id)
|
||||
sendback(client, "OK TRACKING %s\n", tracking_id);
|
||||
else
|
||||
sendback(client, "OK\n");
|
||||
}
|
||||
|
||||
void net_set(nut_ctype_t *client, int numarg, const char **arg)
|
||||
void net_set(nut_ctype_t *client, size_t numarg, const char **arg)
|
||||
{
|
||||
if (numarg < 4) {
|
||||
char tracking_id[UUID4_LEN] = "";
|
||||
|
||||
/* Base verification, to ensure that we have at least the SET parameter */
|
||||
if (numarg < 2) {
|
||||
send_err(client, NUT_ERR_INVALID_ARGUMENT);
|
||||
return;
|
||||
}
|
||||
|
||||
/* SET VAR UPS VARNAME VALUE */
|
||||
if (!strcasecmp(arg[0], "VAR")) {
|
||||
set_var(client, arg[1], arg[2], arg[3]);
|
||||
if (numarg < 4) {
|
||||
send_err(client, NUT_ERR_INVALID_ARGUMENT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (client->tracking) {
|
||||
/* Generate a tracking ID, if client requested status tracking */
|
||||
nut_uuid_v4(tracking_id);
|
||||
}
|
||||
|
||||
set_var(client, arg[1], arg[2], arg[3], tracking_id);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* SET TRACKING VALUE */
|
||||
if (!strcasecmp(arg[0], "TRACKING")) {
|
||||
if (!strcasecmp(arg[1], "ON")) {
|
||||
/* general enablement along with for this client */
|
||||
client->tracking = tracking_enable();
|
||||
}
|
||||
else if (!strcasecmp(arg[1], "OFF")) {
|
||||
/* disable status tracking for this client first */
|
||||
client->tracking = 0;
|
||||
/* then only disable the general one if no other clients use it!
|
||||
* Note: don't call tracking_free() since we want info to
|
||||
* persist, and tracking_cleanup() takes care of cleaning */
|
||||
if (tracking_disable()) {
|
||||
upsdebugx(2, "%s: TRACKING disabled for one client, more remain.", __func__);
|
||||
} else {
|
||||
upsdebugx(2, "%s: TRACKING disabled for last client.", __func__);
|
||||
}
|
||||
}
|
||||
else {
|
||||
send_err(client, NUT_ERR_INVALID_ARGUMENT);
|
||||
return;
|
||||
}
|
||||
upsdebugx(1, "%s: TRACKING general %s, client %s.", __func__,
|
||||
tracking_is_enabled() ? "enabled" : "disabled",
|
||||
client->tracking ? "enabled" : "disabled");
|
||||
|
||||
sendback(client, "OK\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,37 @@
|
|||
/* netset.h - SET handler for upsd
|
||||
|
||||
Copyright (C)
|
||||
2003 Russell Kroll <rkroll@exploits.org>
|
||||
2005 Arnaud Quette <arnaud.quette@free.fr>
|
||||
2007 Peter Selinger <selinger@users.sourceforge.net>
|
||||
2013 Emilien Kia <kiae.dev@gmail.com>
|
||||
2020 Jim Klimov <jimklimov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef NUT_NETSET_H_SEEN
|
||||
#define NUT_NETSET_H_SEEN 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
extern "C" {
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
void net_set(nut_ctype_t *client, int numarg, const char **arg);
|
||||
void net_set(nut_ctype_t *client, size_t numarg, const char **arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
|
|
@ -12,3 +39,4 @@ void net_set(nut_ctype_t *client, int numarg, const char **arg);
|
|||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#endif /* NUT_NETSET_H_SEEN */
|
||||
|
|
|
|||
277
server/netssl.c
277
server/netssl.c
|
|
@ -30,21 +30,35 @@
|
|||
#include "upsd.h"
|
||||
#include "neterr.h"
|
||||
#include "netssl.h"
|
||||
#include "nut_stdint.h"
|
||||
|
||||
#ifdef WITH_NSS
|
||||
#include <pk11pub.h>
|
||||
#include <prinit.h>
|
||||
#include <private/pprio.h>
|
||||
#if defined(NSS_VMAJOR) && (NSS_VMAJOR > 3 || (NSS_VMAJOR == 3 && defined(NSS_VMINOR) && NSS_VMINOR >= 39))
|
||||
#include <keyhi.h>
|
||||
#include <keythi.h>
|
||||
#else
|
||||
#include <key.h>
|
||||
#include <keyt.h>
|
||||
#endif /* NSS before 3.39 */
|
||||
#include <secerr.h>
|
||||
#include <sslerr.h>
|
||||
#include <sslproto.h>
|
||||
#endif /* WITH_NSS */
|
||||
|
||||
char *certfile = NULL;
|
||||
char *certname = NULL;
|
||||
char *certpasswd = NULL;
|
||||
|
||||
/* Warning: in this release of NUT, this feature is disabled by default
|
||||
* in order to retain compatibility with "least surprise" for earlier
|
||||
* existing deployments. Over time it can become enabled by default.
|
||||
* See upsd.conf option DISABLE_WEAK_SSL to toggle this in-vivo.
|
||||
*/
|
||||
int disable_weak_ssl = 0;
|
||||
|
||||
#ifdef WITH_CLIENT_CERTIFICATE_VALIDATION
|
||||
int certrequest = 0;
|
||||
#endif /* WITH_CLIENT_CERTIFICATE_VALIDATION */
|
||||
|
|
@ -54,20 +68,32 @@ static int ssl_initialized = 0;
|
|||
#ifndef WITH_SSL
|
||||
|
||||
/* stubs for non-ssl compiles */
|
||||
void net_starttls(nut_ctype_t *client, int numarg, const char **arg)
|
||||
void net_starttls(nut_ctype_t *client, size_t numarg, const char **arg)
|
||||
{
|
||||
NUT_UNUSED_VARIABLE(client);
|
||||
NUT_UNUSED_VARIABLE(numarg);
|
||||
NUT_UNUSED_VARIABLE(arg);
|
||||
|
||||
send_err(client, NUT_ERR_FEATURE_NOT_SUPPORTED);
|
||||
return;
|
||||
}
|
||||
|
||||
int ssl_write(nut_ctype_t *client, const char *buf, size_t buflen)
|
||||
ssize_t ssl_write(nut_ctype_t *client, const char *buf, size_t buflen)
|
||||
{
|
||||
NUT_UNUSED_VARIABLE(client);
|
||||
NUT_UNUSED_VARIABLE(buf);
|
||||
NUT_UNUSED_VARIABLE(buflen);
|
||||
|
||||
upslogx(LOG_ERR, "ssl_write called but SSL wasn't compiled in");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ssl_read(nut_ctype_t *client, char *buf, size_t buflen)
|
||||
ssize_t ssl_read(nut_ctype_t *client, char *buf, size_t buflen)
|
||||
{
|
||||
NUT_UNUSED_VARIABLE(client);
|
||||
NUT_UNUSED_VARIABLE(buf);
|
||||
NUT_UNUSED_VARIABLE(buflen);
|
||||
|
||||
upslogx(LOG_ERR, "ssl_read called but SSL wasn't compiled in");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -96,7 +122,7 @@ static SSL_CTX *ssl_ctx = NULL;
|
|||
|
||||
static void ssl_debug(void)
|
||||
{
|
||||
int e;
|
||||
unsigned long e;
|
||||
char errmsg[SMALLBUF];
|
||||
|
||||
while ((e = ERR_get_error()) != 0) {
|
||||
|
|
@ -105,32 +131,36 @@ static void ssl_debug(void)
|
|||
}
|
||||
}
|
||||
|
||||
static int ssl_error(SSL *ssl, int ret)
|
||||
static int ssl_error(SSL *ssl, ssize_t ret)
|
||||
{
|
||||
int e;
|
||||
|
||||
e = SSL_get_error(ssl, ret);
|
||||
if (ret >= INT_MAX) {
|
||||
upslogx(LOG_ERR, "ssl_error() ret=%zd would not fit in an int", ret);
|
||||
return -1;
|
||||
}
|
||||
e = SSL_get_error(ssl, (int)ret);
|
||||
|
||||
switch (e)
|
||||
{
|
||||
case SSL_ERROR_WANT_READ:
|
||||
upsdebugx(1, "ssl_error() ret=%d SSL_ERROR_WANT_READ", ret);
|
||||
upsdebugx(1, "ssl_error() ret=%zd SSL_ERROR_WANT_READ", ret);
|
||||
break;
|
||||
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
upsdebugx(1, "ssl_error() ret=%d SSL_ERROR_WANT_WRITE", ret);
|
||||
upsdebugx(1, "ssl_error() ret=%zd SSL_ERROR_WANT_WRITE", ret);
|
||||
break;
|
||||
|
||||
case SSL_ERROR_SYSCALL:
|
||||
if (ret == 0 && ERR_peek_error() == 0) {
|
||||
upsdebugx(1, "ssl_error() EOF from client");
|
||||
} else {
|
||||
upsdebugx(1, "ssl_error() ret=%d SSL_ERROR_SYSCALL", ret);
|
||||
upsdebugx(1, "ssl_error() ret=%zd SSL_ERROR_SYSCALL", ret);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
upsdebugx(1, "ssl_error() ret=%d SSL_ERROR %d", ret, e);
|
||||
upsdebugx(1, "ssl_error() ret=%zd SSL_ERROR %d", ret, e);
|
||||
ssl_debug();
|
||||
}
|
||||
|
||||
|
|
@ -142,9 +172,11 @@ static int ssl_error(SSL *ssl, int ret)
|
|||
static CERTCertificate *cert;
|
||||
static SECKEYPrivateKey *privKey;
|
||||
|
||||
static char *nss_password_callback(PK11SlotInfo *slot, PRBool retry,
|
||||
static char *nss_password_callback(PK11SlotInfo *slot, PRBool retry,
|
||||
void *arg)
|
||||
{
|
||||
NUT_UNUSED_VARIABLE(arg);
|
||||
|
||||
if (retry) {
|
||||
/* Force not inted to retrieve password many times. */
|
||||
return NULL;
|
||||
|
|
@ -165,12 +197,14 @@ static void nss_error(const char* text)
|
|||
}
|
||||
}
|
||||
|
||||
static int ssl_error(PRFileDesc *ssl, int ret)
|
||||
static int ssl_error(PRFileDesc *ssl, ssize_t ret)
|
||||
{
|
||||
char buffer[256];
|
||||
PRInt32 length;
|
||||
PRErrorCode e;
|
||||
|
||||
NUT_UNUSED_VARIABLE(ssl);
|
||||
NUT_UNUSED_VARIABLE(ret);
|
||||
|
||||
e = PR_GetError();
|
||||
length = PR_GetErrorText(buffer);
|
||||
if (length > 0 && length < 256) {
|
||||
|
|
@ -195,13 +229,15 @@ static SECStatus AuthCertificate(CERTCertDBHandle *arg, PRFileDesc *fd,
|
|||
|
||||
static SECStatus BadCertHandler(nut_ctype_t *arg, PRFileDesc *fd)
|
||||
{
|
||||
NUT_UNUSED_VARIABLE(fd);
|
||||
|
||||
upslogx(LOG_WARNING, "Certificate validation failed for %s",
|
||||
(arg&&arg->addr)?arg->addr:"<unnamed>");
|
||||
#ifdef WITH_CLIENT_CERTIFICATE_VALIDATION
|
||||
/* BadCertHandler is called when the NSS certificate validation is failed.
|
||||
* If the certificate verification (user conf) is mandatory, reject authentication
|
||||
* else accept it.
|
||||
*/
|
||||
*/
|
||||
return certrequest==NETSSL_CERTREQ_REQUIRE?SECFailure:SECSuccess;
|
||||
#else /* WITH_CLIENT_CERTIFICATE_VALIDATION */
|
||||
/* Always accept clients. */
|
||||
|
|
@ -211,6 +247,8 @@ static SECStatus BadCertHandler(nut_ctype_t *arg, PRFileDesc *fd)
|
|||
|
||||
static void HandshakeCallback(PRFileDesc *fd, nut_ctype_t *client_data)
|
||||
{
|
||||
NUT_UNUSED_VARIABLE(fd);
|
||||
|
||||
upslogx(LOG_INFO, "SSL handshake done successfully with client %s",
|
||||
client_data->addr);
|
||||
}
|
||||
|
|
@ -218,7 +256,7 @@ static void HandshakeCallback(PRFileDesc *fd, nut_ctype_t *client_data)
|
|||
|
||||
#endif /* WITH_OPENSSL | WITH_NSS */
|
||||
|
||||
void net_starttls(nut_ctype_t *client, int numarg, const char **arg)
|
||||
void net_starttls(nut_ctype_t *client, size_t numarg, const char **arg)
|
||||
{
|
||||
#ifdef WITH_OPENSSL
|
||||
int ret;
|
||||
|
|
@ -226,7 +264,10 @@ void net_starttls(nut_ctype_t *client, int numarg, const char **arg)
|
|||
SECStatus status;
|
||||
PRFileDesc *socket;
|
||||
#endif /* WITH_OPENSSL | WITH_NSS */
|
||||
|
||||
|
||||
NUT_UNUSED_VARIABLE(numarg);
|
||||
NUT_UNUSED_VARIABLE(arg);
|
||||
|
||||
if (client->ssl) {
|
||||
send_err(client, NUT_ERR_ALREADY_SSL_MODE);
|
||||
return;
|
||||
|
|
@ -238,22 +279,23 @@ void net_starttls(nut_ctype_t *client, int numarg, const char **arg)
|
|||
send_err(client, NUT_ERR_FEATURE_NOT_CONFIGURED);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
if (!ssl_ctx) {
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
if (!ssl_ctx)
|
||||
#elif defined(WITH_NSS) /* WITH_OPENSSL */
|
||||
if (!NSS_IsInitialized()) {
|
||||
if (!NSS_IsInitialized())
|
||||
#endif /* WITH_OPENSSL | WITH_NSS */
|
||||
{
|
||||
send_err(client, NUT_ERR_FEATURE_NOT_CONFIGURED);
|
||||
ssl_initialized = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!sendback(client, "OK STARTTLS\n")) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
#ifdef WITH_OPENSSL
|
||||
|
||||
client->ssl = SSL_new(ssl_ctx);
|
||||
|
||||
|
|
@ -268,15 +310,15 @@ void net_starttls(nut_ctype_t *client, int numarg, const char **arg)
|
|||
ssl_debug();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ret = SSL_accept(client->ssl);
|
||||
switch (ret)
|
||||
{
|
||||
case 1:
|
||||
client->ssl_connected = 1;
|
||||
upsdebugx(3, "SSL connected");
|
||||
upsdebugx(3, "SSL connected (%s)", SSL_get_version(client->ssl));
|
||||
break;
|
||||
|
||||
|
||||
case 0:
|
||||
upslog_with_errno(LOG_ERR, "SSL_accept do not accept handshake.");
|
||||
ssl_error(client->ssl, ret);
|
||||
|
|
@ -286,7 +328,7 @@ void net_starttls(nut_ctype_t *client, int numarg, const char **arg)
|
|||
ssl_error(client->ssl, ret);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
#elif defined(WITH_NSS) /* WITH_OPENSSL */
|
||||
|
||||
socket = PR_ImportTCPSocket(client->sock_fd);
|
||||
|
|
@ -302,13 +344,13 @@ void net_starttls(nut_ctype_t *client, int numarg, const char **arg)
|
|||
nss_error("net_starttls / SSL_ImportFD");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (SSL_SetPKCS11PinArg(client->ssl, client) == -1){
|
||||
upslogx(LOG_ERR, "Can not inialize SSL connection");
|
||||
nss_error("net_starttls / SSL_SetPKCS11PinArg");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Note cast to SSLAuthCertificate to prevent warning due to
|
||||
* bad function prototype in NSS.
|
||||
*/
|
||||
|
|
@ -318,21 +360,21 @@ void net_starttls(nut_ctype_t *client, int numarg, const char **arg)
|
|||
nss_error("net_starttls / SSL_AuthCertificateHook");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
status = SSL_BadCertHook(client->ssl, (SSLBadCertHandler)BadCertHandler, client);
|
||||
if (status != SECSuccess) {
|
||||
upslogx(LOG_ERR, "Can not inialize SSL connection");
|
||||
nss_error("net_starttls / SSL_BadCertHook");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
status = SSL_HandshakeCallback(client->ssl, (SSLHandshakeCallback)HandshakeCallback, client);
|
||||
if (status != SECSuccess) {
|
||||
upslogx(LOG_ERR, "Can not inialize SSL connection");
|
||||
nss_error("net_starttls / SSL_HandshakeCallback");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
status = SSL_ConfigSecureServer(client->ssl, cert, privKey, NSS_FindCertKEAType(cert));
|
||||
if (status != SECSuccess) {
|
||||
upslogx(LOG_ERR, "Can not inialize SSL connection");
|
||||
|
|
@ -370,35 +412,53 @@ void ssl_init(void)
|
|||
{
|
||||
#ifdef WITH_NSS
|
||||
SECStatus status;
|
||||
#elif defined(WITH_OPENSSL)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||||
const SSL_METHOD *ssl_method;
|
||||
#else
|
||||
SSL_METHOD *ssl_method;
|
||||
#if defined(NSS_VMAJOR) && (NSS_VMAJOR > 3 || (NSS_VMAJOR == 3 && defined(NSS_VMINOR) && NSS_VMINOR >= 14))
|
||||
SSLVersionRange range;
|
||||
#endif
|
||||
#endif /* WITH_NSS|WITH_OPENSSL */
|
||||
#endif /* WITH_NSS */
|
||||
|
||||
if (!certfile) {
|
||||
return;
|
||||
}
|
||||
|
||||
check_perms(certfile);
|
||||
if (!disable_weak_ssl)
|
||||
upslogx(LOG_WARNING, "Warning: DISABLE_WEAK_SSL is not enabled. Please consider enabling to improve network security.");
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
SSL_load_error_strings();
|
||||
SSL_library_init();
|
||||
|
||||
if ((ssl_method = TLSv1_server_method()) == NULL) {
|
||||
ssl_debug();
|
||||
fatalx(EXIT_FAILURE, "TLSv1_server_method failed");
|
||||
}
|
||||
ssl_ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
#else
|
||||
ssl_ctx = SSL_CTX_new(TLS_server_method());
|
||||
#endif
|
||||
|
||||
if ((ssl_ctx = SSL_CTX_new(ssl_method)) == NULL) {
|
||||
if (!ssl_ctx) {
|
||||
ssl_debug();
|
||||
fatalx(EXIT_FAILURE, "SSL_CTX_new failed");
|
||||
}
|
||||
|
||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
/* set minimum protocol TLSv1 */
|
||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
|
||||
if (disable_weak_ssl) {
|
||||
#if defined(SSL_OP_NO_TLSv1_2)
|
||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1);
|
||||
#elif defined(SSL_OP_NO_TLSv1_1)
|
||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
if (SSL_CTX_set_min_proto_version(ssl_ctx, disable_weak_ssl ? TLS1_2_VERSION : TLS1_VERSION) != 1) {
|
||||
ssl_debug();
|
||||
fatalx(EXIT_FAILURE, "SSL_CTX_set_min_proto_version(TLS1_VERSION)");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (SSL_CTX_use_certificate_chain_file(ssl_ctx, certfile) != 1) {
|
||||
ssl_debug();
|
||||
fatalx(EXIT_FAILURE, "SSL_CTX_use_certificate_chain_file(%s) failed", certfile);
|
||||
|
|
@ -422,7 +482,7 @@ void ssl_init(void)
|
|||
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL);
|
||||
|
||||
ssl_initialized = 1;
|
||||
|
||||
|
||||
#elif defined(WITH_NSS) /* WITH_OPENSSL */
|
||||
|
||||
if (!certname || certname[0]==0 ) {
|
||||
|
|
@ -431,9 +491,9 @@ void ssl_init(void)
|
|||
}
|
||||
|
||||
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
|
||||
|
||||
|
||||
PK11_SetPasswordFunc(nss_password_callback);
|
||||
|
||||
|
||||
if (certfile)
|
||||
/* Note: this call can generate memory leaks not resolvable
|
||||
* by any release function.
|
||||
|
|
@ -444,10 +504,10 @@ void ssl_init(void)
|
|||
status = NSS_NoDB_Init(NULL);
|
||||
if (status != SECSuccess) {
|
||||
upslogx(LOG_ERR, "Can not initialize SSL context");
|
||||
nss_error("upscli_init / NSS_[NoDB]_Init");
|
||||
nss_error("upscli_init / NSS_[NoDB]_Init");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
status = NSS_SetDomesticPolicy();
|
||||
if (status != SECSuccess) {
|
||||
upslogx(LOG_ERR, "Can not initialize SSL policy");
|
||||
|
|
@ -462,18 +522,57 @@ void ssl_init(void)
|
|||
nss_error("upscli_init / SSL_ConfigServerSessionIDCache");
|
||||
return;
|
||||
}
|
||||
|
||||
status = SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_TRUE);
|
||||
if (status != SECSuccess) {
|
||||
upslogx(LOG_ERR, "Can not enable SSLv3");
|
||||
nss_error("upscli_init / SSL_OptionSetDefault(SSL_ENABLE_SSL3)");
|
||||
return;
|
||||
}
|
||||
status = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE);
|
||||
if (status != SECSuccess) {
|
||||
upslogx(LOG_ERR, "Can not enable TLSv1");
|
||||
nss_error("upscli_init / SSL_OptionSetDefault(SSL_ENABLE_TLS)");
|
||||
return;
|
||||
|
||||
if (!disable_weak_ssl) {
|
||||
status = SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_TRUE);
|
||||
if (status != SECSuccess) {
|
||||
upslogx(LOG_ERR, "Can not enable SSLv3");
|
||||
nss_error("upscli_init / SSL_OptionSetDefault(SSL_ENABLE_SSL3)");
|
||||
return;
|
||||
}
|
||||
status = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE);
|
||||
if (status != SECSuccess) {
|
||||
upslogx(LOG_ERR, "Can not enable TLSv1");
|
||||
nss_error("upscli_init / SSL_OptionSetDefault(SSL_ENABLE_TLS)");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
#if defined(NSS_VMAJOR) && (NSS_VMAJOR > 3 || (NSS_VMAJOR == 3 && defined(NSS_VMINOR) && NSS_VMINOR >= 14))
|
||||
status = SSL_VersionRangeGetSupported(ssl_variant_stream, &range);
|
||||
if (status != SECSuccess) {
|
||||
upslogx(LOG_ERR, "Can not get versions supported");
|
||||
nss_error("upscli_init / SSL_VersionRangeGetSupported");
|
||||
return;
|
||||
}
|
||||
range.min = SSL_LIBRARY_VERSION_TLS_1_1;
|
||||
#ifdef SSL_LIBRARY_VERSION_TLS_1_2
|
||||
range.min = SSL_LIBRARY_VERSION_TLS_1_2;
|
||||
#endif
|
||||
status = SSL_VersionRangeSetDefault(ssl_variant_stream, &range);
|
||||
if (status != SECSuccess) {
|
||||
upslogx(LOG_ERR, "Can not set versions supported");
|
||||
nss_error("upscli_init / SSL_VersionRangeSetDefault");
|
||||
return;
|
||||
}
|
||||
/* Disable old/weak ciphers */
|
||||
SSL_CipherPrefSetDefault(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, PR_FALSE);
|
||||
SSL_CipherPrefSetDefault(TLS_RSA_WITH_3DES_EDE_CBC_SHA, PR_FALSE);
|
||||
SSL_CipherPrefSetDefault(TLS_RSA_WITH_RC4_128_SHA, PR_FALSE);
|
||||
SSL_CipherPrefSetDefault(TLS_RSA_WITH_RC4_128_MD5, PR_FALSE);
|
||||
#else
|
||||
status = SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_FALSE);
|
||||
if (status != SECSuccess) {
|
||||
upslogx(LOG_ERR, "Can not disable SSLv3");
|
||||
nss_error("upscli_init / SSL_OptionSetDefault(SSL_DISABLE_SSL3)");
|
||||
return;
|
||||
}
|
||||
status = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE);
|
||||
if (status != SECSuccess) {
|
||||
upslogx(LOG_ERR, "Can not enable TLSv1");
|
||||
nss_error("upscli_init / SSL_OptionSetDefault(SSL_ENABLE_TLS)");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WITH_CLIENT_CERTIFICATE_VALIDATION
|
||||
|
|
@ -483,7 +582,7 @@ void ssl_init(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (certrequest == NETSSL_CERTREQ_REQUEST ||
|
||||
if (certrequest == NETSSL_CERTREQ_REQUEST ||
|
||||
certrequest == NETSSL_CERTREQ_REQUIRE ) {
|
||||
status = SSL_OptionSetDefault(SSL_REQUEST_CERTIFICATE, PR_TRUE);
|
||||
if (status != SECSuccess) {
|
||||
|
|
@ -502,39 +601,59 @@ void ssl_init(void)
|
|||
}
|
||||
}
|
||||
#endif /* WITH_CLIENT_CERTIFICATE_VALIDATION */
|
||||
|
||||
|
||||
cert = PK11_FindCertFromNickname(certname, NULL);
|
||||
if(cert==NULL) {
|
||||
upslogx(LOG_ERR, "Can not find server certificate");
|
||||
nss_error("upscli_init / PK11_FindCertFromNickname");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
privKey = PK11_FindKeyByAnyCert(cert, NULL);
|
||||
if(privKey==NULL){
|
||||
upslogx(LOG_ERR, "Can not find private key associate to server certificate");
|
||||
nss_error("upscli_init / PK11_FindKeyByAnyCert");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ssl_initialized = 1;
|
||||
#else /* WITH_OPENSSL | WITH_NSS */
|
||||
upslogx(LOG_ERR, "ssl_init called but SSL wasn't compiled in");
|
||||
#endif /* WITH_OPENSSL | WITH_NSS */
|
||||
}
|
||||
|
||||
int ssl_read(nut_ctype_t *client, char *buf, size_t buflen)
|
||||
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) )
|
||||
# pragma GCC diagnostic push
|
||||
#endif
|
||||
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC
|
||||
# pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
#endif
|
||||
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC
|
||||
# pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
|
||||
#endif
|
||||
ssize_t ssl_read(nut_ctype_t *client, char *buf, size_t buflen)
|
||||
{
|
||||
int ret;
|
||||
ssize_t ret = -1;
|
||||
|
||||
if (!client->ssl_connected) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
ret = SSL_read(client->ssl, buf, buflen);
|
||||
/* SSL_* routines deal with int type for return and buflen
|
||||
* We might need to window our I/O if we exceed 2GB (in
|
||||
* 32-bit builds)... Not likely to exceed in 64-bit builds,
|
||||
* but smaller systems with 16-bits might be endangered :)
|
||||
*/
|
||||
assert(buflen <= INT_MAX);
|
||||
int iret = SSL_read(client->ssl, buf, (int)buflen);
|
||||
assert(iret <= SSIZE_MAX);
|
||||
ret = (ssize_t)iret;
|
||||
#elif defined(WITH_NSS) /* WITH_OPENSSL */
|
||||
ret = PR_Read(client->ssl, buf, buflen);
|
||||
/* PR_* routines deal in PRInt32 type
|
||||
* We might need to window our I/O if we exceed 2GB :) */
|
||||
assert(buflen <= PR_INT32_MAX);
|
||||
ret = PR_Read(client->ssl, buf, (PRInt32)buflen);
|
||||
#endif /* WITH_OPENSSL | WITH_NSS */
|
||||
|
||||
if (ret < 1) {
|
||||
|
|
@ -545,24 +664,38 @@ int ssl_read(nut_ctype_t *client, char *buf, size_t buflen)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int ssl_write(nut_ctype_t *client, const char *buf, size_t buflen)
|
||||
ssize_t ssl_write(nut_ctype_t *client, const char *buf, size_t buflen)
|
||||
{
|
||||
int ret;
|
||||
ssize_t ret = -1;
|
||||
|
||||
if (!client->ssl_connected) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
ret = SSL_write(client->ssl, buf, buflen);
|
||||
/* SSL_* routines deal with int type for return and buflen
|
||||
* We might need to window our I/O if we exceed 2GB (in
|
||||
* 32-bit builds)... Not likely to exceed in 64-bit builds,
|
||||
* but smaller systems with 16-bits might be endangered :)
|
||||
*/
|
||||
assert(buflen <= INT_MAX);
|
||||
int iret = SSL_write(client->ssl, buf, (int)buflen);
|
||||
assert(iret <= SSIZE_MAX);
|
||||
ret = (ssize_t)iret;
|
||||
#elif defined(WITH_NSS) /* WITH_OPENSSL */
|
||||
ret = PR_Write(client->ssl, buf, buflen);
|
||||
/* PR_* routines deal in PRInt32 type
|
||||
* We might need to window our I/O if we exceed 2GB :) */
|
||||
assert(buflen <= PR_INT32_MAX);
|
||||
ret = PR_Write(client->ssl, buf, (PRInt32)buflen);
|
||||
#endif /* WITH_OPENSSL | WITH_NSS */
|
||||
|
||||
upsdebugx(5, "ssl_write ret=%d", ret);
|
||||
upsdebugx(5, "ssl_write ret=%zd", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP_BESIDEFUNC) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TYPE_LIMITS_BESIDEFUNC) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_TAUTOLOGICAL_CONSTANT_OUT_OF_RANGE_COMPARE_BESIDEFUNC) )
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
void ssl_finish(nut_ctype_t *client)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef NETSSL_H_SEEN
|
||||
#define NETSSL_H_SEEN 1
|
||||
#ifndef NUT_NETSSL_H_SEEN
|
||||
#define NUT_NETSSL_H_SEEN 1
|
||||
|
||||
#include "nut_ctype.h"
|
||||
|
||||
|
|
@ -31,6 +31,7 @@ extern "C" {
|
|||
extern char *certfile;
|
||||
extern char *certname;
|
||||
extern char *certpasswd;
|
||||
extern int disable_weak_ssl;
|
||||
#ifdef WITH_CLIENT_CERTIFICATE_VALIDATION
|
||||
extern int certrequest;
|
||||
#endif /* WITH_CLIENT_CERTIFICATE_VALIDATION */
|
||||
|
|
@ -48,10 +49,10 @@ void ssl_init(void);
|
|||
void ssl_finish(nut_ctype_t *client);
|
||||
void ssl_cleanup(void);
|
||||
|
||||
int ssl_read(nut_ctype_t *client, char *buf, size_t buflen);
|
||||
int ssl_write(nut_ctype_t *client, const char *buf, size_t buflen);
|
||||
ssize_t ssl_read(nut_ctype_t *client, char *buf, size_t buflen);
|
||||
ssize_t ssl_write(nut_ctype_t *client, const char *buf, size_t buflen);
|
||||
|
||||
void net_starttls(nut_ctype_t *client, int numarg, const char **arg);
|
||||
void net_starttls(nut_ctype_t *client, size_t numarg, const char **arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
|
|
@ -59,4 +60,4 @@ void net_starttls(nut_ctype_t *client, int numarg, const char **arg);
|
|||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#endif /* NETSSL_H_SEEN */
|
||||
#endif /* NUT_NETSSL_H_SEEN */
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* netuser.c - LOGIN/LOGOUT/USERNAME/PASSWORD/MASTER handlers for upsd
|
||||
/* netuser.c - LOGIN/LOGOUT/USERNAME/PASSWORD/MASTER[PRIMARY] handlers for upsd
|
||||
|
||||
Copyright (C) 2003 Russell Kroll <rkroll@exploits.org>
|
||||
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
#include "netuser.h"
|
||||
|
||||
/* LOGIN <ups> */
|
||||
void net_login(nut_ctype_t *client, int numarg, const char **arg)
|
||||
void net_login(nut_ctype_t *client, size_t numarg, const char **arg)
|
||||
{
|
||||
upstype_t *ups;
|
||||
|
||||
|
|
@ -53,6 +53,8 @@ void net_login(nut_ctype_t *client, int numarg, const char **arg)
|
|||
|
||||
/* make sure this is a valid user */
|
||||
if (!user_checkaction(client->username, client->password, "LOGIN")) {
|
||||
upsdebugx(3, "%s: not a valid user: %s",
|
||||
__func__, client->username);
|
||||
send_err(client, NUT_ERR_ACCESS_DENIED);
|
||||
return;
|
||||
}
|
||||
|
|
@ -65,8 +67,9 @@ void net_login(nut_ctype_t *client, int numarg, const char **arg)
|
|||
sendback(client, "OK\n");
|
||||
}
|
||||
|
||||
void net_logout(nut_ctype_t *client, int numarg, const char **arg)
|
||||
void net_logout(nut_ctype_t *client, size_t numarg, const char **arg)
|
||||
{
|
||||
NUT_UNUSED_VARIABLE(arg);
|
||||
if (numarg != 0) {
|
||||
send_err(client, NUT_ERR_INVALID_ARGUMENT);
|
||||
return;
|
||||
|
|
@ -82,35 +85,64 @@ void net_logout(nut_ctype_t *client, int numarg, const char **arg)
|
|||
client->last_heard = 0;
|
||||
}
|
||||
|
||||
/* MASTER <upsname> */
|
||||
void net_master(nut_ctype_t *client, int numarg, const char **arg)
|
||||
/* NOTE: Protocol updated since NUT 2.8.0 to handle master/primary
|
||||
* and API bumped, to rename/alias the routine.
|
||||
*/
|
||||
static int do_net_primary(nut_ctype_t *client, size_t numarg, const char **arg)
|
||||
{
|
||||
upstype_t *ups;
|
||||
|
||||
if (numarg != 1) {
|
||||
send_err(client, NUT_ERR_INVALID_ARGUMENT);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ups = get_ups_ptr(arg[0]);
|
||||
|
||||
if (!ups) {
|
||||
send_err(client, NUT_ERR_UNKNOWN_UPS);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* make sure this user is allowed to do MASTER */
|
||||
if (!user_checkaction(client->username, client->password, "MASTER")) {
|
||||
/* make sure this user is allowed to do PRIMARY or MASTER */
|
||||
if (!user_checkaction(client->username, client->password, "PRIMARY")
|
||||
&& !user_checkaction(client->username, client->password, "MASTER")
|
||||
) {
|
||||
send_err(client, NUT_ERR_ACCESS_DENIED);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* this is just an access level check */
|
||||
sendback(client, "OK MASTER-GRANTED\n");
|
||||
/* sendback() will be worded by caller below */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* MASTER <upsname> (deprecated) */
|
||||
void net_master(nut_ctype_t *client, size_t numarg, const char **arg) {
|
||||
/* Allow existing binaries linked against this file to still work */
|
||||
upsdebugx(1,
|
||||
"WARNING: Client %s@%s "
|
||||
"requested MASTER level for device %s - "
|
||||
"which is deprecated in favor of PRIMARY "
|
||||
"since NUT 2.8.0",
|
||||
client->username, client->addr,
|
||||
(numarg > 0) ? arg[0] : "<null>");
|
||||
|
||||
if (0 == do_net_primary(client, numarg, arg)) {
|
||||
sendback(client, "OK MASTER-GRANTED\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* PRIMARY <upsname> (since NUT 2.8.0) */
|
||||
void net_primary(nut_ctype_t *client, size_t numarg, const char **arg)
|
||||
{
|
||||
if (0 == do_net_primary(client, numarg, arg)) {
|
||||
sendback(client, "OK PRIMARY-GRANTED\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* USERNAME <username> */
|
||||
void net_username(nut_ctype_t *client, int numarg, const char **arg)
|
||||
void net_username(nut_ctype_t *client, size_t numarg, const char **arg)
|
||||
{
|
||||
if (numarg != 1) {
|
||||
send_err(client, NUT_ERR_INVALID_ARGUMENT);
|
||||
|
|
@ -130,7 +162,7 @@ void net_username(nut_ctype_t *client, int numarg, const char **arg)
|
|||
}
|
||||
|
||||
/* PASSWORD <password> */
|
||||
void net_password(nut_ctype_t *client, int numarg, const char **arg)
|
||||
void net_password(nut_ctype_t *client, size_t numarg, const char **arg)
|
||||
{
|
||||
if (numarg != 1) {
|
||||
send_err(client, NUT_ERR_INVALID_ARGUMENT);
|
||||
|
|
|
|||
|
|
@ -1,14 +1,48 @@
|
|||
/* netuser.c - LOGIN/LOGOUT/USERNAME/PASSWORD/MASTER[PRIMARY] handlers for upsd
|
||||
|
||||
Copyright (C)
|
||||
2003 Russell Kroll <rkroll@exploits.org>
|
||||
2005 Arnaud Quette <arnaud.quette@free.fr>
|
||||
2007 Peter Selinger <selinger@users.sourceforge.net>
|
||||
2013 Emilien Kia <kiae.dev@gmail.com>
|
||||
2020-2021 Jim Klimov <jimklimov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef NUT_NETUSER_H_SEEN
|
||||
#define NUT_NETUSER_H_SEEN 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
extern "C" {
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
void net_login(nut_ctype_t *client, int numarg, const char **arg);
|
||||
void net_logout(nut_ctype_t *client, int numarg, const char **arg);
|
||||
void net_master(nut_ctype_t *client, int numarg, const char **arg);
|
||||
void net_username(nut_ctype_t *client, int numarg, const char **arg);
|
||||
void net_password(nut_ctype_t *client, int numarg, const char **arg);
|
||||
void net_login(nut_ctype_t *client, size_t numarg, const char **arg);
|
||||
void net_logout(nut_ctype_t *client, size_t numarg, const char **arg);
|
||||
|
||||
/* NOTE: Since NUT 2.8.0 we handle master as alias for primary
|
||||
* Header keyword kept for building older consumers, but
|
||||
* the implementation will warn that it is deprecated.
|
||||
*/
|
||||
void net_master(nut_ctype_t *client, size_t numarg, const char **arg);
|
||||
void net_primary(nut_ctype_t *client, size_t numarg, const char **arg);
|
||||
|
||||
void net_username(nut_ctype_t *client, size_t numarg, const char **arg);
|
||||
void net_password(nut_ctype_t *client, size_t numarg, const char **arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
|
|
@ -16,3 +50,4 @@ void net_password(nut_ctype_t *client, int numarg, const char **arg);
|
|||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#endif /* NUT_NETUSER_H_SEEN */
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
2002 Russell Kroll <rkroll@exploits.org>
|
||||
2008 Arjen de Korte <adkorte-guest@alioth.debian.org>
|
||||
2011 Arnaud Quette <arnaud.quette@free.fr>
|
||||
2013 Emilien Kia <kiae.dev@gmail.com>
|
||||
2020 Jim Klimov <jimklimov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -37,6 +39,12 @@
|
|||
|
||||
#include "parseconf.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
extern "C" {
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
/* client structure */
|
||||
typedef struct nut_ctype_s {
|
||||
char *addr;
|
||||
|
|
@ -45,6 +53,9 @@ typedef struct nut_ctype_s {
|
|||
char *loginups;
|
||||
char *password;
|
||||
char *username;
|
||||
/* per client status info for commands and settings
|
||||
* (disabled by default) */
|
||||
int tracking;
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
SSL *ssl;
|
||||
|
|
@ -62,4 +73,10 @@ typedef struct nut_ctype_s {
|
|||
struct nut_ctype_s *next;
|
||||
} nut_ctype_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
}
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#endif /* NUT_CTYPE_H_SEEN */
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
|
@ -31,11 +31,11 @@
|
|||
|
||||
PCONF_CTX_t sock_ctx;
|
||||
|
||||
static void sock_arg(int numarg, char **arg)
|
||||
static void sock_arg(size_t numarg, char **arg)
|
||||
{
|
||||
int i;
|
||||
size_t i;
|
||||
|
||||
printf("numarg=%d : ", numarg);
|
||||
printf("numarg=%zu : ", numarg);
|
||||
|
||||
for (i = 0; i < numarg; i++)
|
||||
printf("[%s] ", arg[i]);
|
||||
|
|
@ -48,6 +48,8 @@ static int socket_connect(const char *sockfn)
|
|||
int ret, fd;
|
||||
struct sockaddr_un sa;
|
||||
|
||||
check_unix_socket_filename(sockfn);
|
||||
|
||||
memset(&sa, '\0', sizeof(sa));
|
||||
sa.sun_family = AF_UNIX;
|
||||
snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", sockfn);
|
||||
|
|
@ -98,7 +100,7 @@ static void read_sock(int fd)
|
|||
}
|
||||
|
||||
if (ret < 0) {
|
||||
perror("read sockfd");
|
||||
perror("read sockfd");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@
|
|||
#include "timehead.h"
|
||||
|
||||
#include "sstate.h"
|
||||
#include "upsd.h"
|
||||
#include "upstype.h"
|
||||
#include "nut_stdint.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
|
|
@ -33,9 +35,9 @@
|
|||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
static int parse_args(upstype_t *ups, int numargs, char **arg)
|
||||
static int parse_args(upstype_t *ups, size_t numargs, char **arg)
|
||||
{
|
||||
if (numargs < 1)
|
||||
return 0;
|
||||
|
|
@ -104,48 +106,63 @@ static int parse_args(upstype_t *ups, int numargs, char **arg)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* ADDRANGE <varname> <minvalue> <maxvalue> */
|
||||
if (!strcasecmp(arg[0], "ADDRANGE")) {
|
||||
state_addrange(ups->inforoot, arg[1], atoi(arg[2]), atoi(arg[3]));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* DELENUM <varname> <enumval> */
|
||||
if (!strcasecmp(arg[0], "DELENUM")) {
|
||||
state_delenum(ups->inforoot, arg[1], arg[2]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* DELRANGE <varname> <minvalue> <maxvalue> */
|
||||
if (!strcasecmp(arg[0], "DELRANGE")) {
|
||||
state_delrange(ups->inforoot, arg[1], atoi(arg[2]), atoi(arg[3]));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* SETAUX <varname> <auxval> */
|
||||
if (!strcasecmp(arg[0], "SETAUX")) {
|
||||
state_setaux(ups->inforoot, arg[1], arg[2]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* TRACKING <id> <status> */
|
||||
if (!strcasecmp(arg[0], "TRACKING")) {
|
||||
tracking_set(arg[1], arg[2]);
|
||||
upsdebugx(1, "TRACKING: ID %s status %s", arg[1], arg[2]);
|
||||
|
||||
/* log actual result of instcmd / setvar */
|
||||
if (strncmp(arg[2], "PENDING", 7) != 0) {
|
||||
upslogx(LOG_INFO, "tracking ID: %s\tresult: %s", arg[1], tracking_get(arg[1]));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (numargs < 4)
|
||||
return 0;
|
||||
|
||||
/* ADDRANGE <varname> <minvalue> <maxvalue> */
|
||||
if (!strcasecmp(arg[0], "ADDRANGE")) {
|
||||
state_addrange(ups->inforoot, arg[1], atoi(arg[2]), atoi(arg[3]));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* DELRANGE <varname> <minvalue> <maxvalue> */
|
||||
if (!strcasecmp(arg[0], "DELRANGE")) {
|
||||
state_delrange(ups->inforoot, arg[1], atoi(arg[2]), atoi(arg[3]));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* nothing fancy - just make the driver say something back to us */
|
||||
static void sendping(upstype_t *ups)
|
||||
{
|
||||
int ret;
|
||||
ssize_t ret;
|
||||
const char *cmd = "PING\n";
|
||||
size_t cmdlen = strlen(cmd);
|
||||
|
||||
if ((!ups) || (ups->sock_fd < 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
upsdebugx(3, "Pinging UPS [%s]", ups->name);
|
||||
ret = write(ups->sock_fd, cmd, cmdlen);
|
||||
|
||||
ret = write(ups->sock_fd, cmd, strlen(cmd));
|
||||
|
||||
if (ret != (int)strlen(cmd)) {
|
||||
if ((ret < 1) || (ret != (ssize_t)cmdlen)) {
|
||||
upslog_with_errno(LOG_NOTICE, "Send ping to UPS [%s] failed", ups->name);
|
||||
sstate_disconnect(ups);
|
||||
return;
|
||||
|
|
@ -158,10 +175,14 @@ static void sendping(upstype_t *ups)
|
|||
|
||||
int sstate_connect(upstype_t *ups)
|
||||
{
|
||||
int ret, fd;
|
||||
int fd;
|
||||
const char *dumpcmd = "DUMPALL\n";
|
||||
size_t dumpcmdlen = strlen(dumpcmd);
|
||||
ssize_t ret;
|
||||
struct sockaddr_un sa;
|
||||
|
||||
check_unix_socket_filename(ups->fn);
|
||||
|
||||
memset(&sa, '\0', sizeof(sa));
|
||||
sa.sun_family = AF_UNIX;
|
||||
snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", ups->fn);
|
||||
|
|
@ -186,7 +207,7 @@ int sstate_connect(upstype_t *ups)
|
|||
return -1;
|
||||
|
||||
ups->last_connfail = now;
|
||||
upslog_with_errno(LOG_ERR, "Can't connect to UPS [%s] (%s)",
|
||||
upslog_with_errno(LOG_ERR, "Can't connect to UPS [%s] (%s)",
|
||||
ups->name, ups->fn);
|
||||
|
||||
return -1;
|
||||
|
|
@ -209,9 +230,9 @@ int sstate_connect(upstype_t *ups)
|
|||
}
|
||||
|
||||
/* get a dump started so we have a fresh set of data */
|
||||
ret = write(fd, dumpcmd, strlen(dumpcmd));
|
||||
ret = write(fd, dumpcmd, dumpcmdlen);
|
||||
|
||||
if (ret != (int)strlen(dumpcmd)) {
|
||||
if ((ret < 1) || (ret != (ssize_t)dumpcmdlen)) {
|
||||
upslog_with_errno(LOG_ERR, "Initial write to UPS [%s] failed", ups->name);
|
||||
close(fd);
|
||||
return -1;
|
||||
|
|
@ -250,7 +271,7 @@ void sstate_disconnect(upstype_t *ups)
|
|||
|
||||
void sstate_readline(upstype_t *ups)
|
||||
{
|
||||
int i, ret;
|
||||
ssize_t i, ret;
|
||||
char buf[SMALLBUF];
|
||||
|
||||
if ((!ups) || (ups->sock_fd < 0)) {
|
||||
|
|
@ -280,7 +301,7 @@ void sstate_readline(upstype_t *ups)
|
|||
case 1:
|
||||
/* set the 'last heard' time to now for later staleness checks */
|
||||
if (parse_args(ups, ups->sock_ctx.numargs, ups->sock_ctx.arglist)) {
|
||||
time(&ups->last_heard);
|
||||
time(&ups->last_heard);
|
||||
}
|
||||
continue;
|
||||
|
||||
|
|
@ -303,12 +324,12 @@ const char *sstate_getinfo(const upstype_t *ups, const char *var)
|
|||
int sstate_getflags(const upstype_t *ups, const char *var)
|
||||
{
|
||||
return state_getflags(ups->inforoot, var);
|
||||
}
|
||||
}
|
||||
|
||||
int sstate_getaux(const upstype_t *ups, const char *var)
|
||||
long sstate_getaux(const upstype_t *ups, const char *var)
|
||||
{
|
||||
return state_getaux(ups->inforoot, var);
|
||||
}
|
||||
}
|
||||
|
||||
const enum_t *sstate_getenumlist(const upstype_t *ups, const char *var)
|
||||
{
|
||||
|
|
@ -325,7 +346,7 @@ const cmdlist_t *sstate_getcmdlist(const upstype_t *ups)
|
|||
return ups->cmdlist;
|
||||
}
|
||||
|
||||
int sstate_dead(upstype_t *ups, int maxage)
|
||||
int sstate_dead(upstype_t *ups, int arg_maxage)
|
||||
{
|
||||
time_t now;
|
||||
double elapsed;
|
||||
|
|
@ -347,12 +368,12 @@ int sstate_dead(upstype_t *ups, int maxage)
|
|||
elapsed = difftime(now, ups->last_heard);
|
||||
|
||||
/* somewhere beyond a third of the maximum time - prod it to make it talk */
|
||||
if ((elapsed > (maxage / 3)) && (difftime(now, ups->last_ping) > (maxage / 3)))
|
||||
if ((elapsed > (arg_maxage / 3)) && (difftime(now, ups->last_ping) > (arg_maxage / 3)))
|
||||
sendping(ups);
|
||||
|
||||
if (elapsed > maxage) {
|
||||
if (elapsed > arg_maxage) {
|
||||
upsdebugx(3, "sstate_dead: didn't hear from driver for UPS [%s] for %g seconds (max %d)",
|
||||
ups->name, elapsed, maxage);
|
||||
ups->name, elapsed, arg_maxage);
|
||||
return 1; /* dead */
|
||||
}
|
||||
|
||||
|
|
@ -376,16 +397,24 @@ void sstate_cmdfree(upstype_t *ups)
|
|||
|
||||
int sstate_sendline(upstype_t *ups, const char *buf)
|
||||
{
|
||||
int ret;
|
||||
ssize_t ret;
|
||||
size_t buflen;
|
||||
|
||||
if ((!ups) ||(ups->sock_fd < 0)) {
|
||||
return 0; /* failed */
|
||||
}
|
||||
|
||||
ret = write(ups->sock_fd, buf, strlen(buf));
|
||||
buflen = strlen(buf);
|
||||
if (buflen >= SSIZE_MAX) {
|
||||
/* Can't compare buflen to ret... */
|
||||
upslog_with_errno(LOG_NOTICE, "Send ping to UPS [%s] failed: buffered message too large", ups->name);
|
||||
return 0; /* failed */
|
||||
}
|
||||
|
||||
if (ret == (int)strlen(buf)) {
|
||||
return 1;
|
||||
ret = write(ups->sock_fd, buf, buflen);
|
||||
|
||||
if (ret == (ssize_t)buflen) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
upslog_with_errno(LOG_NOTICE, "Send to UPS [%s] failed", ups->name);
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef SSTATE_H_SEEN
|
||||
#define SSTATE_H_SEEN
|
||||
#ifndef NUT_SSTATE_H_SEEN
|
||||
#define NUT_SSTATE_H_SEEN 1
|
||||
|
||||
#include "state.h"
|
||||
#include "upstype.h"
|
||||
|
|
@ -40,7 +40,7 @@ void sstate_disconnect(upstype_t *ups);
|
|||
void sstate_readline(upstype_t *ups);
|
||||
const char *sstate_getinfo(const upstype_t *ups, const char *var);
|
||||
int sstate_getflags(const upstype_t *ups, const char *var);
|
||||
int sstate_getaux(const upstype_t *ups, const char *var);
|
||||
long sstate_getaux(const upstype_t *ups, const char *var);
|
||||
const enum_t *sstate_getenumlist(const upstype_t *ups, const char *var);
|
||||
const range_t *sstate_getrangelist(const upstype_t *ups, const char *var);
|
||||
const cmdlist_t *sstate_getcmdlist(const upstype_t *ups);
|
||||
|
|
@ -59,4 +59,4 @@ const st_tree_t *sstate_getnode(const upstype_t *ups, const char *varname);
|
|||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#endif /* SSTATE_H_SEEN */
|
||||
#endif /* NUT_SSTATE_H_SEEN */
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef STYPE_H_SEEN
|
||||
#define STYPE_H_SEEN 1
|
||||
#ifndef NUT_STYPE_H_SEEN
|
||||
#define NUT_STYPE_H_SEEN 1
|
||||
|
||||
#include <netdb.h>
|
||||
|
||||
|
|
@ -50,4 +50,4 @@ typedef struct stype_s {
|
|||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#endif /* STYPE_H_SEEN */
|
||||
#endif /* NUT_STYPE_H_SEEN */
|
||||
|
|
|
|||
588
server/upsd.c
588
server/upsd.c
|
|
@ -1,9 +1,10 @@
|
|||
/* upsd.c - watches ups state files and answers queries
|
||||
/* upsd.c - watches ups state files and answers queries
|
||||
|
||||
Copyright (C)
|
||||
1999 Russell Kroll <rkroll@exploits.org>
|
||||
2008 Arjen de Korte <adkorte-guest@alioth.debian.org>
|
||||
2011 - 2012 Arnaud Quette <arnaud.quette.free.fr>
|
||||
2019 Eaton (author: Arnaud Quette <ArnaudQuette@eaton.com>)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -20,6 +21,8 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h" /* must be the first header */
|
||||
|
||||
#include "upsd.h"
|
||||
#include "upstype.h"
|
||||
#include "conf.h"
|
||||
|
|
@ -30,10 +33,17 @@
|
|||
#include <sys/un.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <poll.h>
|
||||
|
||||
#ifdef HAVE_SYS_SIGNAL_H
|
||||
#include <sys/signal.h>
|
||||
#endif
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include "user.h"
|
||||
#include "nut_ctype.h"
|
||||
#include "nut_stdint.h"
|
||||
#include "stype.h"
|
||||
#include "netssl.h"
|
||||
#include "sstate.h"
|
||||
|
|
@ -46,29 +56,38 @@ int allow_severity = LOG_INFO;
|
|||
int deny_severity = LOG_WARNING;
|
||||
#endif /* HAVE_WRAP */
|
||||
|
||||
/* externally-visible settings and pointers */
|
||||
/* externally-visible settings and pointers */
|
||||
|
||||
upstype_t *firstups = NULL;
|
||||
upstype_t *firstups = NULL;
|
||||
|
||||
/* default 15 seconds before data is marked stale */
|
||||
int maxage = 15;
|
||||
/* default 15 seconds before data is marked stale */
|
||||
int maxage = 15;
|
||||
|
||||
/* preloaded to {OPEN_MAX} in main, can be overridden via upsd.conf */
|
||||
int maxconn = 0;
|
||||
/* default to 1h before cleaning up status tracking entries */
|
||||
int tracking_delay = 3600;
|
||||
|
||||
/* preloaded to STATEPATH in main, can be overridden via upsd.conf */
|
||||
char *statepath = NULL;
|
||||
/*
|
||||
* Preloaded to ALLOW_NO_DEVICE from upsd.conf or environment variable
|
||||
* (with higher prio for envvar); defaults to disabled for legacy compat.
|
||||
*/
|
||||
int allow_no_device = 0;
|
||||
|
||||
/* preloaded to DATADIR in main, can be overridden via upsd.conf */
|
||||
char *datapath = NULL;
|
||||
/* preloaded to {OPEN_MAX} in main, can be overridden via upsd.conf */
|
||||
nfds_t maxconn = 0;
|
||||
|
||||
/* everything else */
|
||||
const char *progname;
|
||||
/* preloaded to STATEPATH in main, can be overridden via upsd.conf */
|
||||
char *statepath = NULL;
|
||||
|
||||
/* preloaded to DATADIR in main, can be overridden via upsd.conf */
|
||||
char *datapath = NULL;
|
||||
|
||||
/* everything else */
|
||||
static const char *progname;
|
||||
|
||||
nut_ctype_t *firstclient = NULL;
|
||||
/* static nut_ctype_t *lastclient = NULL; */
|
||||
|
||||
/* default is to listen on all local interfaces */
|
||||
/* default is to listen on all local interfaces */
|
||||
static stype_t *firstaddr = NULL;
|
||||
|
||||
static int opt_af = AF_UNSPEC;
|
||||
|
|
@ -84,6 +103,28 @@ typedef struct {
|
|||
void *data;
|
||||
} handler_t;
|
||||
|
||||
|
||||
/* Commands and settings status tracking */
|
||||
|
||||
/* general enable/disable status info for commands and settings
|
||||
* (disabled by default)
|
||||
* Note that only client that requested it will have it enabled
|
||||
* (see nut_ctype.h) */
|
||||
static int tracking_enabled = 0;
|
||||
|
||||
/* Commands and settings status tracking structure */
|
||||
typedef struct tracking_s {
|
||||
char *id;
|
||||
int status;
|
||||
time_t request_time; /* for cleanup */
|
||||
/* doubly linked list */
|
||||
struct tracking_s *prev;
|
||||
struct tracking_s *next;
|
||||
} tracking_t;
|
||||
|
||||
static tracking_t *tracking_list = NULL;
|
||||
|
||||
|
||||
/* pollfd */
|
||||
static struct pollfd *fds = NULL;
|
||||
static handler_t *handler = NULL;
|
||||
|
|
@ -94,6 +135,11 @@ static char pidfn[SMALLBUF];
|
|||
/* set by signal handlers */
|
||||
static int reload_flag = 0, exit_flag = 0;
|
||||
|
||||
/* Minimalistic support for UUID v4 */
|
||||
/* Ref: RFC 4122 https://tools.ietf.org/html/rfc4122#section-4.1.2 */
|
||||
#define UUID4_BYTESIZE 16
|
||||
|
||||
|
||||
static const char *inet_ntopW (struct sockaddr_storage *s)
|
||||
{
|
||||
static char str[40];
|
||||
|
|
@ -204,7 +250,7 @@ static void setuptcp(stype_t *server)
|
|||
upsdebug_with_errno(3, "setuptcp: socket");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one)) != 0) {
|
||||
fatal_with_errno(EXIT_FAILURE, "setuptcp: setsockopt");
|
||||
}
|
||||
|
|
@ -308,12 +354,15 @@ static void client_disconnect(nut_ctype_t *client)
|
|||
return;
|
||||
}
|
||||
|
||||
/* send the buffer <sendbuf> of length <sendlen> to host <dest> */
|
||||
/* send the buffer <sendbuf> of length <sendlen> to host <dest>
|
||||
* returns effectively a boolean: 0 = failed, 1 = sent ok
|
||||
*/
|
||||
int sendback(nut_ctype_t *client, const char *fmt, ...)
|
||||
{
|
||||
int res, len;
|
||||
char ans[NUT_NET_ANSWER_MAX+1];
|
||||
va_list ap;
|
||||
ssize_t res;
|
||||
size_t len;
|
||||
char ans[NUT_NET_ANSWER_MAX+1];
|
||||
va_list ap;
|
||||
|
||||
if (!client) {
|
||||
return 0;
|
||||
|
|
@ -325,18 +374,23 @@ int sendback(nut_ctype_t *client, const char *fmt, ...)
|
|||
|
||||
len = strlen(ans);
|
||||
|
||||
/* System write() and our ssl_write() have a loophole that they write a
|
||||
* size_t amount of bytes and upon success return that in ssize_t value
|
||||
*/
|
||||
assert(len < SSIZE_MAX);
|
||||
|
||||
#ifdef WITH_SSL
|
||||
if (client->ssl) {
|
||||
res = ssl_write(client, ans, len);
|
||||
} else
|
||||
} else
|
||||
#endif /* WITH_SSL */
|
||||
{
|
||||
res = write(client->sock_fd, ans, len);
|
||||
}
|
||||
|
||||
upsdebugx(2, "write: [destfd=%d] [len=%d] [%s]", client->sock_fd, len, str_rtrim(ans, '\n'));
|
||||
upsdebugx(2, "write: [destfd=%d] [len=%zu] [%s]", client->sock_fd, len, str_rtrim(ans, '\n'));
|
||||
|
||||
if (len != res) {
|
||||
if (res < 0 || len != (size_t)res) {
|
||||
upslog_with_errno(LOG_NOTICE, "write() failed for %s", client->addr);
|
||||
client->last_heard = 0;
|
||||
return 0; /* failed */
|
||||
|
|
@ -396,20 +450,25 @@ int ups_available(const upstype_t *ups, nut_ctype_t *client)
|
|||
}
|
||||
|
||||
/* check flags and access for an incoming command from the network */
|
||||
static void check_command(int cmdnum, nut_ctype_t *client, int numarg,
|
||||
static void check_command(int cmdnum, nut_ctype_t *client, size_t numarg,
|
||||
const char **arg)
|
||||
{
|
||||
upsdebugx(6, "Entering %s: %s", __func__, numarg > 0 ? arg[0] : "<>");
|
||||
|
||||
if (netcmds[cmdnum].flags & FLAG_USER) {
|
||||
/* command requires previous authentication */
|
||||
#ifdef HAVE_WRAP
|
||||
struct request_info req;
|
||||
#endif /* HAVE_WRAP */
|
||||
|
||||
if (!client->username) {
|
||||
upsdebugx(1, "%s: client not logged in yet", __func__);
|
||||
send_err(client, NUT_ERR_USERNAME_REQUIRED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!client->password) {
|
||||
upsdebugx(1, "%s: client not logged in yet", __func__);
|
||||
send_err(client, NUT_ERR_PASSWORD_REQUIRED);
|
||||
return;
|
||||
}
|
||||
|
|
@ -419,15 +478,20 @@ static void check_command(int cmdnum, nut_ctype_t *client, int numarg,
|
|||
fromhost(&req);
|
||||
|
||||
if (!hosts_access(&req)) {
|
||||
/* tcp-wrappers says access should be denied */
|
||||
upsdebugx(1,
|
||||
"%s: while authenticating %s found that "
|
||||
"tcp-wrappers says access should be denied",
|
||||
__func__, client->username);
|
||||
send_err(client, NUT_ERR_ACCESS_DENIED);
|
||||
return;
|
||||
}
|
||||
#endif /* HAVE_WRAP */
|
||||
}
|
||||
|
||||
upsdebugx(6, "%s: Calling command handler for %s", __func__, numarg > 0 ? arg[0] : "<>");
|
||||
|
||||
/* looks good - call the command */
|
||||
netcmds[cmdnum].func(client, numarg - 1, &arg[1]);
|
||||
netcmds[cmdnum].func(client, (numarg < 2) ? 0 : (numarg - 1), (numarg > 1) ? &arg[1] : NULL);
|
||||
}
|
||||
|
||||
/* parse requests from the network */
|
||||
|
|
@ -457,7 +521,7 @@ static void parse_net(nut_ctype_t *client)
|
|||
static void client_connect(stype_t *server)
|
||||
{
|
||||
struct sockaddr_storage csock;
|
||||
#if defined(__hpux) && !defined(_XOPEN_SOURCE_EXTENDED)
|
||||
#if defined(__hpux) && !defined(_XOPEN_SOURCE_EXTENDED)
|
||||
int clen;
|
||||
#else
|
||||
socklen_t clen;
|
||||
|
|
@ -480,6 +544,8 @@ static void client_connect(stype_t *server)
|
|||
|
||||
client->addr = xstrdup(inet_ntopW(&csock));
|
||||
|
||||
client->tracking = 0;
|
||||
|
||||
pconf_init(&client->ctx, NULL);
|
||||
|
||||
if (firstclient) {
|
||||
|
|
@ -504,12 +570,13 @@ static void client_connect(stype_t *server)
|
|||
static void client_readline(nut_ctype_t *client)
|
||||
{
|
||||
char buf[SMALLBUF];
|
||||
int i, ret;
|
||||
int i;
|
||||
ssize_t ret;
|
||||
|
||||
#ifdef WITH_SSL
|
||||
if (client->ssl) {
|
||||
ret = ssl_read(client, buf, sizeof(buf));
|
||||
} else
|
||||
} else
|
||||
#endif /* WITH_SSL */
|
||||
{
|
||||
ret = read(client->sock_fd, buf, sizeof(buf));
|
||||
|
|
@ -569,7 +636,7 @@ void server_load(void)
|
|||
for (server = firstaddr; server; server = server->next) {
|
||||
setuptcp(server);
|
||||
}
|
||||
|
||||
|
||||
/* check if we have at least 1 valid LISTEN interface */
|
||||
if (firstaddr->sock_fd < 0) {
|
||||
fatalx(EXIT_FAILURE, "no listening interface available");
|
||||
|
|
@ -607,11 +674,14 @@ static void client_free(void)
|
|||
}
|
||||
}
|
||||
|
||||
void driver_free(void)
|
||||
static void driver_free(void)
|
||||
{
|
||||
upstype_t *ups, *unext;
|
||||
|
||||
for (ups = firstups; ups; ups = unext) {
|
||||
upsdebugx(1, "%s: forgetting UPS [%s] (FD %d)",
|
||||
__func__, ups->name, ups->sock_fd);
|
||||
|
||||
unext = ups->next;
|
||||
|
||||
if (ups->sock_fd != -1) {
|
||||
|
|
@ -640,10 +710,11 @@ static void upsd_cleanup(void)
|
|||
|
||||
user_flush();
|
||||
desc_free();
|
||||
|
||||
|
||||
server_free();
|
||||
client_free();
|
||||
driver_free();
|
||||
tracking_free();
|
||||
|
||||
free(statepath);
|
||||
free(datapath);
|
||||
|
|
@ -655,27 +726,256 @@ static void upsd_cleanup(void)
|
|||
free(handler);
|
||||
}
|
||||
|
||||
void poll_reload(void)
|
||||
static void poll_reload(void)
|
||||
{
|
||||
int ret;
|
||||
long ret;
|
||||
|
||||
ret = sysconf(_SC_OPEN_MAX);
|
||||
|
||||
if (ret < maxconn) {
|
||||
if ((intmax_t)ret < (intmax_t)maxconn) {
|
||||
fatalx(EXIT_FAILURE,
|
||||
"Your system limits the maximum number of connections to %d\n"
|
||||
"but you requested %d. The server won't start until this\n"
|
||||
"problem is resolved.\n", ret, maxconn);
|
||||
"Your system limits the maximum number of connections to %ld\n"
|
||||
"but you requested %jd. The server won't start until this\n"
|
||||
"problem is resolved.\n", ret, (intmax_t)maxconn);
|
||||
}
|
||||
|
||||
fds = xrealloc(fds, maxconn * sizeof(*fds));
|
||||
handler = xrealloc(handler, maxconn * sizeof(*handler));
|
||||
if (1 > maxconn) {
|
||||
fatalx(EXIT_FAILURE,
|
||||
"You requested %jd as maximum number of connections.\n"
|
||||
"The server won't start until this problem is resolved.\n", (intmax_t)maxconn);
|
||||
}
|
||||
|
||||
/* How many items can we stuff into the array? */
|
||||
size_t maxalloc = SIZE_MAX / sizeof(void *);
|
||||
if ((uintmax_t)maxalloc < (uintmax_t)maxconn) {
|
||||
fatalx(EXIT_FAILURE,
|
||||
"You requested %jd as maximum number of connections, but we can only allocate %zu.\n"
|
||||
"The server won't start until this problem is resolved.\n", (intmax_t)maxconn, maxalloc);
|
||||
}
|
||||
|
||||
/* The checks above effectively limit that maxconn is in size_t range */
|
||||
fds = xrealloc(fds, (size_t)maxconn * sizeof(*fds));
|
||||
handler = xrealloc(handler, (size_t)maxconn * sizeof(*handler));
|
||||
}
|
||||
|
||||
/* instant command and setvar status tracking */
|
||||
|
||||
/* allocate a new status tracking entry */
|
||||
int tracking_add(const char *id)
|
||||
{
|
||||
tracking_t *item;
|
||||
|
||||
if ((!tracking_enabled) || (!id))
|
||||
return 0;
|
||||
|
||||
item = xcalloc(1, sizeof(*item));
|
||||
|
||||
item->id = xstrdup(id);
|
||||
item->status = STAT_PENDING;
|
||||
time(&item->request_time);
|
||||
|
||||
if (tracking_list) {
|
||||
tracking_list->prev = item;
|
||||
item->next = tracking_list;
|
||||
}
|
||||
|
||||
tracking_list = item;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* set status of a specific tracking entry */
|
||||
int tracking_set(const char *id, const char *value)
|
||||
{
|
||||
tracking_t *item, *next_item;
|
||||
|
||||
/* sanity checks */
|
||||
if ((!tracking_list) || (!id) || (!value))
|
||||
return 0;
|
||||
|
||||
for (item = tracking_list; item; item = next_item) {
|
||||
|
||||
next_item = item->next;
|
||||
|
||||
if (!strcasecmp(item->id, id)) {
|
||||
item->status = atoi(value);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0; /* id not found! */
|
||||
}
|
||||
|
||||
/* free a specific tracking entry */
|
||||
int tracking_del(const char *id)
|
||||
{
|
||||
tracking_t *item, *next_item;
|
||||
|
||||
/* sanity check */
|
||||
if ((!tracking_list) || (!id))
|
||||
return 0;
|
||||
|
||||
upsdebugx(3, "%s: deleting id %s", __func__, id);
|
||||
|
||||
for (item = tracking_list; item; item = next_item) {
|
||||
|
||||
next_item = item->next;
|
||||
|
||||
if (strcasecmp(item->id, id))
|
||||
continue;
|
||||
|
||||
if (item->prev)
|
||||
item->prev->next = item->next;
|
||||
else
|
||||
/* deleting first entry */
|
||||
tracking_list = item->next;
|
||||
|
||||
if (item->next)
|
||||
item->next->prev = item->prev;
|
||||
|
||||
free(item->id);
|
||||
free(item);
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
return 0; /* id not found! */
|
||||
}
|
||||
|
||||
/* free all status tracking entries */
|
||||
void tracking_free(void)
|
||||
{
|
||||
tracking_t *item, *next_item;
|
||||
|
||||
/* sanity check */
|
||||
if (!tracking_list)
|
||||
return;
|
||||
|
||||
upsdebugx(3, "%s", __func__);
|
||||
|
||||
for (item = tracking_list; item; item = next_item) {
|
||||
next_item = item->next;
|
||||
tracking_del(item->id);
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup status tracking entries according to their age and tracking_delay */
|
||||
void tracking_cleanup(void)
|
||||
{
|
||||
tracking_t *item, *next_item;
|
||||
time_t now;
|
||||
|
||||
/* sanity check */
|
||||
if (!tracking_list)
|
||||
return;
|
||||
|
||||
time(&now);
|
||||
|
||||
upsdebugx(3, "%s", __func__);
|
||||
|
||||
for (item = tracking_list; item; item = next_item) {
|
||||
|
||||
next_item = item->next;
|
||||
|
||||
if (difftime(now, item->request_time) > tracking_delay) {
|
||||
tracking_del(item->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* get status of a specific tracking entry */
|
||||
char *tracking_get(const char *id)
|
||||
{
|
||||
tracking_t *item, *next_item;
|
||||
|
||||
/* sanity checks */
|
||||
if ((!tracking_list) || (!id))
|
||||
return "ERR UNKNOWN";
|
||||
|
||||
for (item = tracking_list; item; item = next_item) {
|
||||
|
||||
next_item = item->next;
|
||||
|
||||
if (strcasecmp(item->id, id))
|
||||
continue;
|
||||
|
||||
switch (item->status)
|
||||
{
|
||||
case STAT_PENDING:
|
||||
return "PENDING";
|
||||
case STAT_HANDLED:
|
||||
return "SUCCESS";
|
||||
case STAT_UNKNOWN:
|
||||
return "ERR UNKNOWN";
|
||||
case STAT_INVALID:
|
||||
return "ERR INVALID-ARGUMENT";
|
||||
case STAT_FAILED:
|
||||
return "ERR FAILED";
|
||||
}
|
||||
}
|
||||
|
||||
return "ERR UNKNOWN"; /* id not found! */
|
||||
}
|
||||
|
||||
/* enable general status tracking (tracking_enabled) and return its value (1). */
|
||||
int tracking_enable(void)
|
||||
{
|
||||
tracking_enabled = 1;
|
||||
|
||||
return tracking_enabled;
|
||||
}
|
||||
|
||||
/* disable general status tracking only if no client use it anymore.
|
||||
* return the new value for tracking_enabled */
|
||||
int tracking_disable(void)
|
||||
{
|
||||
nut_ctype_t *client, *cnext;
|
||||
|
||||
for (client = firstclient; client; client = cnext) {
|
||||
cnext = client->next;
|
||||
if (client->tracking == 1)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return current general status of tracking (tracking_enabled). */
|
||||
int tracking_is_enabled(void)
|
||||
{
|
||||
return tracking_enabled;
|
||||
}
|
||||
|
||||
/* UUID v4 basic implementation
|
||||
* Note: 'dest' must be at least `UUID4_LEN` long */
|
||||
int nut_uuid_v4(char *uuid_str)
|
||||
{
|
||||
size_t i;
|
||||
uint8_t nut_uuid[UUID4_BYTESIZE];
|
||||
|
||||
if (!uuid_str)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < UUID4_BYTESIZE; i++)
|
||||
nut_uuid[i] = (uint8_t)rand() + (uint8_t)rand();
|
||||
|
||||
/* set variant and version */
|
||||
nut_uuid[6] = (nut_uuid[6] & 0x0F) | 0x40;
|
||||
nut_uuid[8] = (nut_uuid[8] & 0x3F) | 0x80;
|
||||
|
||||
return snprintf(uuid_str, UUID4_LEN,
|
||||
"%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||||
nut_uuid[0], nut_uuid[1], nut_uuid[2], nut_uuid[3],
|
||||
nut_uuid[4], nut_uuid[5], nut_uuid[6], nut_uuid[7],
|
||||
nut_uuid[8], nut_uuid[9], nut_uuid[10], nut_uuid[11],
|
||||
nut_uuid[12], nut_uuid[13], nut_uuid[14], nut_uuid[15]);
|
||||
}
|
||||
|
||||
/* service requests and check on new data */
|
||||
static void mainloop(void)
|
||||
{
|
||||
int i, ret, nfds = 0;
|
||||
int ret;
|
||||
nfds_t i, nfds = 0;
|
||||
|
||||
upstype_t *ups;
|
||||
nut_ctype_t *client, *cnext;
|
||||
|
|
@ -690,12 +990,19 @@ static void mainloop(void)
|
|||
reload_flag = 0;
|
||||
}
|
||||
|
||||
/* cleanup instcmd/setvar status tracking entries if needed */
|
||||
tracking_cleanup();
|
||||
|
||||
/* scan through driver sockets */
|
||||
for (ups = firstups; ups && (nfds < maxconn); ups = ups->next) {
|
||||
|
||||
/* see if we need to (re)connect to the socket */
|
||||
if (ups->sock_fd < 0) {
|
||||
upsdebugx(1, "%s: UPS [%s] is not currently connected",
|
||||
__func__, ups->name);
|
||||
ups->sock_fd = sstate_connect(ups);
|
||||
upsdebugx(1, "%s: UPS [%s] is now connected as FD %d",
|
||||
__func__, ups->name, ups->sock_fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -722,6 +1029,7 @@ static void mainloop(void)
|
|||
|
||||
if (difftime(now, client->last_heard) > 60) {
|
||||
/* shed clients after 1 minute of inactivity */
|
||||
/* FIXME: create an upsd.conf parameter (CLIENT_INACTIVITY_DELAY) */
|
||||
client_disconnect(client);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -756,7 +1064,7 @@ static void mainloop(void)
|
|||
nfds++;
|
||||
}
|
||||
|
||||
upsdebugx(2, "%s: polling %d filedescriptors", __func__, nfds);
|
||||
upsdebugx(2, "%s: polling %jd filedescriptors", __func__, (intmax_t)nfds);
|
||||
|
||||
ret = poll(fds, nfds, 2000);
|
||||
|
||||
|
|
@ -785,9 +1093,36 @@ static void mainloop(void)
|
|||
case SERVER:
|
||||
upsdebugx(2, "%s: server disconnected", __func__);
|
||||
break;
|
||||
|
||||
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) )
|
||||
# pragma GCC diagnostic push
|
||||
#endif
|
||||
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT
|
||||
# pragma GCC diagnostic ignored "-Wcovered-switch-default"
|
||||
#endif
|
||||
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
|
||||
# pragma GCC diagnostic ignored "-Wunreachable-code"
|
||||
#endif
|
||||
/* Older CLANG (e.g. clang-3.4) seems to not support the GCC pragmas above */
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wcovered-switch-default"
|
||||
#pragma clang diagnostic ignored "-Wunreachable-code"
|
||||
#endif
|
||||
/* All enum cases defined as of the time of coding
|
||||
* have been covered above. Handle later definitions,
|
||||
* memory corruptions and buggy inputs below...
|
||||
*/
|
||||
default:
|
||||
upsdebugx(2, "%s: <unknown> disconnected", __func__);
|
||||
break;
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) )
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
continue;
|
||||
|
|
@ -806,9 +1141,35 @@ static void mainloop(void)
|
|||
case SERVER:
|
||||
client_connect((stype_t *)handler[i].data);
|
||||
break;
|
||||
|
||||
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) )
|
||||
# pragma GCC diagnostic push
|
||||
#endif
|
||||
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT
|
||||
# pragma GCC diagnostic ignored "-Wcovered-switch-default"
|
||||
#endif
|
||||
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
|
||||
# pragma GCC diagnostic ignored "-Wunreachable-code"
|
||||
#endif
|
||||
/* Older CLANG (e.g. clang-3.4) seems to not support the GCC pragmas above */
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wcovered-switch-default"
|
||||
#pragma clang diagnostic ignored "-Wunreachable-code"
|
||||
#endif
|
||||
/* All enum cases defined as of the time of coding
|
||||
* have been covered above. Handle later definitions,
|
||||
* memory corruptions and buggy inputs below...
|
||||
*/
|
||||
default:
|
||||
upsdebugx(2, "%s: <unknown> has data available", __func__);
|
||||
break;
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && ( (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT) || (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE) )
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
|
||||
continue;
|
||||
|
|
@ -816,17 +1177,24 @@ static void mainloop(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void help(const char *progname)
|
||||
static void help(const char *arg_progname)
|
||||
__attribute__((noreturn));
|
||||
|
||||
static void help(const char *arg_progname)
|
||||
{
|
||||
printf("Network server for UPS data.\n\n");
|
||||
printf("usage: %s [OPTIONS]\n", progname);
|
||||
printf("usage: %s [OPTIONS]\n", arg_progname);
|
||||
|
||||
printf("\n");
|
||||
printf(" -c <command> send <command> via signal to background process\n");
|
||||
printf(" commands:\n");
|
||||
printf(" - reload: reread configuration files\n");
|
||||
printf(" - stop: stop process and exit\n");
|
||||
printf(" -D raise debugging level\n");
|
||||
printf(" -P <pid> send the signal above to specified PID (bypassing PID file)\n");
|
||||
printf(" -D raise debugging level (and stay foreground by default)\n");
|
||||
printf(" -F stay foregrounded even if no debugging is enabled\n");
|
||||
printf(" -FF stay foregrounded and still save the PID file\n");
|
||||
printf(" -B stay backgrounded even if debugging is bumped\n");
|
||||
printf(" -h display this help\n");
|
||||
printf(" -r <dir> chroots to <dir>\n");
|
||||
printf(" -q raise log level threshold\n");
|
||||
|
|
@ -840,6 +1208,7 @@ static void help(const char *progname)
|
|||
|
||||
static void set_reload_flag(int sig)
|
||||
{
|
||||
NUT_UNUSED_VARIABLE(sig);
|
||||
reload_flag = 1;
|
||||
}
|
||||
|
||||
|
|
@ -857,7 +1226,14 @@ static void setup_signals(void)
|
|||
sa.sa_flags = 0;
|
||||
|
||||
/* basic signal setup to ignore SIGPIPE */
|
||||
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_STRICT_PROTOTYPES)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wstrict-prototypes"
|
||||
#endif
|
||||
sa.sa_handler = SIG_IGN;
|
||||
#if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_STRICT_PROTOTYPES)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
sigaction(SIGPIPE, &sa, NULL);
|
||||
|
||||
/* handle shutdown signals */
|
||||
|
|
@ -890,10 +1266,11 @@ void check_perms(const char *fn)
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, cmd = 0;
|
||||
int i, cmd = 0, cmdret = 0, foreground = -1;
|
||||
char *chroot_path = NULL;
|
||||
const char *user = RUN_AS_USER;
|
||||
struct passwd *new_uid = NULL;
|
||||
pid_t oldpid = -1;
|
||||
|
||||
progname = xbasename(argv[0]);
|
||||
|
||||
|
|
@ -906,25 +1283,29 @@ int main(int argc, char **argv)
|
|||
|
||||
printf("Network UPS Tools %s %s\n", progname, UPS_VERSION);
|
||||
|
||||
while ((i = getopt(argc, argv, "+h46p:qr:i:fu:Vc:D")) != -1) {
|
||||
while ((i = getopt(argc, argv, "+h46p:qr:i:fu:Vc:P:DFB")) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
help(progname);
|
||||
break;
|
||||
case 'p':
|
||||
case 'i':
|
||||
fatalx(EXIT_FAILURE, "Specifying a listening addresses with '-i <address>' and '-p <port>'\n"
|
||||
"is deprecated. Use 'LISTEN <address> [<port>]' in 'upsd.conf' instead.\n"
|
||||
"See 'man 8 upsd.conf' for more information.");
|
||||
#ifndef HAVE___ATTRIBUTE__NORETURN
|
||||
exit(EXIT_FAILURE); /* Should not get here in practice, but compiler is afraid we can fall through */
|
||||
#endif
|
||||
|
||||
case 'q':
|
||||
nut_log_level++;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
chroot_path = optarg;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
user = optarg;
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
/* do nothing - we already printed the banner */
|
||||
exit(EXIT_SUCCESS);
|
||||
|
|
@ -940,9 +1321,25 @@ int main(int argc, char **argv)
|
|||
help(progname);
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
if ((oldpid = parsepid(optarg)) < 0)
|
||||
help(progname);
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
nut_debug_level++;
|
||||
break;
|
||||
case 'F':
|
||||
if (foreground > 0) {
|
||||
/* specified twice to save PID file anyway */
|
||||
foreground = 2;
|
||||
} else {
|
||||
foreground = 1;
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
foreground = 0;
|
||||
break;
|
||||
|
||||
case '4':
|
||||
opt_af = AF_INET;
|
||||
|
|
@ -952,24 +1349,56 @@ int main(int argc, char **argv)
|
|||
opt_af = AF_INET6;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
default:
|
||||
help(progname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foreground < 0) {
|
||||
if (nut_debug_level > 0) {
|
||||
foreground = 1;
|
||||
} else {
|
||||
foreground = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd) {
|
||||
sendsignalfn(pidfn, cmd);
|
||||
exit(EXIT_SUCCESS);
|
||||
if (oldpid < 0) {
|
||||
cmdret = sendsignalfn(pidfn, cmd);
|
||||
} else {
|
||||
cmdret = sendsignalpid(oldpid, cmd);
|
||||
}
|
||||
exit((cmdret == 0)?EXIT_SUCCESS:EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* otherwise, we are being asked to start.
|
||||
* so check if a previous instance is running by sending signal '0'
|
||||
* (Ie 'kill <pid> 0') */
|
||||
if (sendsignalfn(pidfn, 0) == 0) {
|
||||
if (oldpid < 0) {
|
||||
cmdret = sendsignalfn(pidfn, 0);
|
||||
} else {
|
||||
cmdret = sendsignalpid(oldpid, 0);
|
||||
}
|
||||
switch (cmdret) {
|
||||
case 0:
|
||||
printf("Fatal error: A previous upsd instance is already running!\n");
|
||||
printf("Either stop the previous instance first, or use the 'reload' command.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
case -3:
|
||||
case -2:
|
||||
upslogx(LOG_WARNING, "Could not %s PID file '%s' "
|
||||
"to see if previous upsd instance is "
|
||||
"already running!\n",
|
||||
(cmdret == -3 ? "find" : "parse"),
|
||||
pidfn);
|
||||
break;
|
||||
|
||||
case -1:
|
||||
default:
|
||||
/* Just failed to send signal, no competitor running */
|
||||
break;
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
|
|
@ -995,12 +1424,43 @@ int main(int argc, char **argv)
|
|||
chroot_start(chroot_path);
|
||||
}
|
||||
|
||||
/* default to system limit (may be overridden in upsd.conf */
|
||||
maxconn = sysconf(_SC_OPEN_MAX);
|
||||
/* default to system limit (may be overridden in upsd.conf) */
|
||||
/* FIXME: Check for overflows (and int size of nfds_t vs. long) - see get_max_pid_t() for example */
|
||||
maxconn = (nfds_t)sysconf(_SC_OPEN_MAX);
|
||||
|
||||
/* handle upsd.conf */
|
||||
load_upsdconf(0); /* 0 = initial */
|
||||
|
||||
/* CLI debug level can not be smaller than debug_min specified
|
||||
* in upsd.conf. Note that non-zero debug_min does not impact
|
||||
* foreground running mode.
|
||||
*/
|
||||
if (nut_debug_level_global > nut_debug_level)
|
||||
nut_debug_level = nut_debug_level_global;
|
||||
upsdebugx(1, "debug level is '%d'", nut_debug_level);
|
||||
|
||||
{ /* scope */
|
||||
/* As documented above, the ALLOW_NO_DEVICE can be provided via
|
||||
* envvars and then has higher priority than an upsd.conf setting
|
||||
*/
|
||||
const char *envvar = getenv("ALLOW_NO_DEVICE");
|
||||
if ( envvar != NULL) {
|
||||
if ( (!strncasecmp("TRUE", envvar, 4)) || (!strncasecmp("YES", envvar, 3)) || (!strncasecmp("ON", envvar, 2)) || (!strncasecmp("1", envvar, 1)) ) {
|
||||
/* Admins of this server expressed a desire to serve
|
||||
* anything on the NUT protocol, even if nothing is
|
||||
* configured yet - tell the clients so, properly.
|
||||
*/
|
||||
allow_no_device = 1;
|
||||
} else if ( (!strncasecmp("FALSE", envvar, 5)) || (!strncasecmp("NO", envvar, 2)) || (!strncasecmp("OFF", envvar, 3)) || (!strncasecmp("0", envvar, 1)) ) {
|
||||
/* Admins of this server expressed a desire to serve
|
||||
* anything on the NUT protocol, even if nothing is
|
||||
* configured yet - tell the clients so, properly.
|
||||
*/
|
||||
allow_no_device = 0;
|
||||
}
|
||||
}
|
||||
} /* scope */
|
||||
|
||||
/* start server */
|
||||
server_load();
|
||||
|
||||
|
|
@ -1019,7 +1479,11 @@ int main(int argc, char **argv)
|
|||
poll_reload();
|
||||
|
||||
if (num_ups == 0) {
|
||||
fatalx(EXIT_FAILURE, "Fatal error: at least one UPS must be defined in ups.conf");
|
||||
if (allow_no_device) {
|
||||
upslogx(LOG_WARNING, "Normally at least one UPS must be defined in ups.conf, currently there are none (please configure the file and reload the service)");
|
||||
} else {
|
||||
fatalx(EXIT_FAILURE, "Fatal error: at least one UPS must be defined in ups.conf");
|
||||
}
|
||||
}
|
||||
|
||||
/* try to bring in the var/cmd descriptions */
|
||||
|
|
@ -1028,11 +1492,17 @@ int main(int argc, char **argv)
|
|||
/* handle upsd.users */
|
||||
user_load();
|
||||
|
||||
if (!nut_debug_level) {
|
||||
if (!foreground) {
|
||||
background();
|
||||
writepid(pidfn);
|
||||
} else {
|
||||
memset(pidfn, 0, sizeof(pidfn));
|
||||
if (foreground == 2) {
|
||||
upslogx(LOG_WARNING, "Running as foreground process, but saving a PID file anyway");
|
||||
writepid(pidfn);
|
||||
} else {
|
||||
upslogx(LOG_WARNING, "Running as foreground process, not saving a PID file");
|
||||
memset(pidfn, 0, sizeof(pidfn));
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize SSL (keyfile must be readable by nut user) */
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "timehead.h"
|
||||
|
||||
#include <sys/file.h>
|
||||
#include <poll.h> /* nfds_t */
|
||||
|
||||
#include "parseconf.h"
|
||||
#include "nut_ctype.h"
|
||||
|
|
@ -68,9 +69,30 @@ void server_free(void);
|
|||
|
||||
void check_perms(const char *fn);
|
||||
|
||||
/* declarations from upsd.c */
|
||||
/* return values for instcmd / setvar status tracking,
|
||||
* mapped on drivers/upshandler.h, apart from STAT_PENDING (initial state) */
|
||||
enum {
|
||||
STAT_PENDING = -1, /* not yet completed */
|
||||
STAT_HANDLED = 0, /* completed successfully (NUT_SUCCESS or "OK") */
|
||||
STAT_UNKNOWN, /* unspecified error (NUT_ERR_UNKNOWN) */
|
||||
STAT_INVALID, /* invalid command/setvar (NUT_ERR_INVALID_ARGUMENT) */
|
||||
STAT_FAILED /* command/setvar failed (NUT_ERR_INSTCMD_FAILED / NUT_ERR_SET_FAILED) */
|
||||
};
|
||||
|
||||
extern int maxage, maxconn;
|
||||
/* Commands and settings status tracking functions */
|
||||
int tracking_add(const char *id);
|
||||
int tracking_set(const char *id, const char *value);
|
||||
int tracking_del(const char *id);
|
||||
void tracking_free(void);
|
||||
void tracking_cleanup(void);
|
||||
char *tracking_get(const char *id);
|
||||
int tracking_enable(void);
|
||||
int tracking_disable(void);
|
||||
int tracking_is_enabled(void);
|
||||
|
||||
/* declarations from upsd.c */
|
||||
extern int maxage, tracking_delay, allow_no_device;
|
||||
extern nfds_t maxconn;
|
||||
extern char *statepath, *datapath;
|
||||
extern upstype_t *firstups;
|
||||
extern nut_ctype_t *firstclient;
|
||||
|
|
@ -91,6 +113,10 @@ extern nut_ctype_t *firstclient;
|
|||
#define shutdown_how 2
|
||||
#endif
|
||||
|
||||
/* UUID v4 generation function
|
||||
* Note: 'dest' must be at least `UUID4_LEN` long */
|
||||
int nut_uuid_v4(char *uuid_str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef UPSTYPE_H_SEEN
|
||||
#define UPSTYPE_H_SEEN 1
|
||||
#ifndef NUT_UPSTYPE_H_SEEN
|
||||
#define NUT_UPSTYPE_H_SEEN 1
|
||||
|
||||
#include "parseconf.h"
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ typedef struct upstype_s {
|
|||
int fsd; /* forced shutdown in effect? */
|
||||
|
||||
int retain;
|
||||
|
||||
|
||||
struct upstype_s *next;
|
||||
|
||||
} upstype_t;
|
||||
|
|
@ -64,4 +64,4 @@ extern upstype_t *firstups;
|
|||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#endif /* UPSTYPE_H_SEEN */
|
||||
#endif /* NUT_UPSTYPE_H_SEEN */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
/* user-data.h - structures for user.c
|
||||
|
||||
Copyright (C) 2001 Russell Kroll <rkroll@exploits.org>
|
||||
2005 Arnaud Quette <arnaud.quette@free.fr>
|
||||
2007 Peter Selinger <selinger@users.sourceforge.net>
|
||||
2008 Arjen de Korte <adkorte-guest@alioth.debian.org>
|
||||
2013 Emilien Kia <kiae.dev@gmail.com>
|
||||
2020 Jim Klimov <jimklimov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -17,6 +22,9 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef NUT_USERDATA_H_SEEN
|
||||
#define NUT_USERDATA_H_SEEN 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
extern "C" {
|
||||
|
|
@ -47,3 +55,4 @@ typedef struct {
|
|||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#endif /* NUT_USERDATA_H_SEEN */
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h" /* must be the first header */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
|
@ -28,9 +30,9 @@
|
|||
#include "user.h"
|
||||
#include "user-data.h"
|
||||
|
||||
ulist_t *users = NULL;
|
||||
static ulist_t *users = NULL;
|
||||
|
||||
static ulist_t *curr_user;
|
||||
static ulist_t *curr_user;
|
||||
|
||||
/* create a new user entry */
|
||||
static void user_add(const char *un)
|
||||
|
|
@ -57,7 +59,7 @@ static void user_add(const char *un)
|
|||
if (last) {
|
||||
last->next = tmp;
|
||||
} else {
|
||||
users = tmp;
|
||||
users = tmp;
|
||||
}
|
||||
|
||||
/* remember who we're working on */
|
||||
|
|
@ -78,7 +80,7 @@ static void user_password(const char *pw)
|
|||
}
|
||||
|
||||
if (curr_user->password) {
|
||||
fprintf(stderr, "Ignoring duplicate password for %s\n",
|
||||
fprintf(stderr, "Ignoring duplicate password for %s\n",
|
||||
curr_user->username);
|
||||
return;
|
||||
}
|
||||
|
|
@ -317,19 +319,20 @@ int user_checkaction(const char *un, const char *pw, const char *action)
|
|||
return 0; /* fail */
|
||||
}
|
||||
|
||||
/* handle "upsmon master" and "upsmon slave" for nicer configurations */
|
||||
/* handle "upsmon primary" and "upsmon secondary" for nicer configurations */
|
||||
/* FIXME: Protocol update needed to handle master/primary alias (in action and in protocol) */
|
||||
static void set_upsmon_type(char *type)
|
||||
{
|
||||
/* master: login, master, fsd */
|
||||
if (!strcasecmp(type, "master")) {
|
||||
/* primary: login, master, fsd */
|
||||
if (!strcasecmp(type, "master") || !strcasecmp(type, "primary")) {
|
||||
user_add_action("login");
|
||||
user_add_action("master");
|
||||
user_add_action("master"); /* Note: this is linked to "MASTER" API command permission */
|
||||
user_add_action("fsd");
|
||||
return;
|
||||
}
|
||||
|
||||
/* slave: just login */
|
||||
if (!strcasecmp(type, "slave")) {
|
||||
/* secondary: just login */
|
||||
if (!strcasecmp(type, "slave") || !strcasecmp(type, "secondary")) {
|
||||
user_add_action("login");
|
||||
return;
|
||||
}
|
||||
|
|
@ -370,9 +373,9 @@ static void parse_var(char *var, char *val)
|
|||
}
|
||||
|
||||
/* parse first var+val pair, then flip through remaining vals */
|
||||
static void parse_rest(char *var, char *fval, char **arg, int next, int left)
|
||||
static void parse_rest(char *var, char *fval, char **arg, size_t next, size_t left)
|
||||
{
|
||||
int i;
|
||||
size_t i;
|
||||
|
||||
/* no globals supported yet, so there's no sense in continuing */
|
||||
if (!curr_user) {
|
||||
|
|
@ -390,7 +393,7 @@ static void parse_rest(char *var, char *fval, char **arg, int next, int left)
|
|||
}
|
||||
}
|
||||
|
||||
static void user_parse_arg(int numargs, char **arg)
|
||||
static void user_parse_arg(size_t numargs, char **arg)
|
||||
{
|
||||
char *ep;
|
||||
|
||||
|
|
@ -414,7 +417,7 @@ static void user_parse_arg(int numargs, char **arg)
|
|||
/* 0 1 2 ... */
|
||||
/* foo=bar <rest1> <rest2> ... */
|
||||
|
||||
parse_rest(arg[0], ep+1, arg, 1, numargs - 1);
|
||||
parse_rest(arg[0], ep+1, arg, 1, (numargs < 2) ? 0 : (numargs - 1));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -447,8 +450,8 @@ static void user_parse_arg(int numargs, char **arg)
|
|||
/* foo = bar <rest1> <rest2> ... */
|
||||
|
||||
/* parse first var/val, plus subsequent values (if any) */
|
||||
|
||||
parse_rest(arg[0], arg[2], arg, 3, numargs - 3);
|
||||
|
||||
parse_rest(arg[0], arg[2], arg, 3, (numargs < 4) ? 0 : (numargs - 3));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
/* user.c - supporting elements of user handling functions for upsd
|
||||
|
||||
Copyright (C) 2001 Russell Kroll <rkroll@exploits.org>
|
||||
2005 Arnaud Quette <arnaud.quette@free.fr>
|
||||
2007 Peter Selinger <selinger@users.sourceforge.net>
|
||||
2008 Arjen de Korte <adkorte-guest@alioth.debian.org>
|
||||
2013 Emilien Kia <kiae.dev@gmail.com>
|
||||
2020 Jim Klimov <jimklimov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -17,6 +22,9 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef NUT_USER_H_SEEN
|
||||
#define NUT_USER_H_SEEN 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
extern "C" {
|
||||
|
|
@ -39,3 +47,4 @@ void check_perms(const char *fn);
|
|||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
#endif /* NUT_USER_H_SEEN */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue