Imported Upstream version 2.4.3

This commit is contained in:
arnaud.quette@free.fr 2010-03-26 00:20:59 +01:00
commit 26fb71b504
446 changed files with 148951 additions and 0 deletions

30
server/Makefile.am Normal file
View file

@ -0,0 +1,30 @@
# Network UPS Tools: server
# 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.
AM_CFLAGS = -I$(top_srcdir)/include
if WITH_WRAP
AM_CFLAGS += $(LIBWRAP_CFLAGS)
endif
if WITH_SSL
AM_CFLAGS += $(LIBSSL_CFLAGS)
endif
LDADD = ../common/libcommon.a ../common/libparseconf.la $(NETLIBS)
if WITH_WRAP
LDADD += $(LIBWRAP_LDFLAGS)
endif
if WITH_SSL
LDADD += $(LIBSSL_LDFLAGS)
endif
sbin_PROGRAMS = upsd
EXTRA_PROGRAMS = sockdebug
upsd_SOURCES = upsd.c user.c conf.c ssl.c sstate.c desc.c \
netget.c netmisc.c netlist.c netuser.c netset.c netinstcmd.c \
conf.h ctype.h desc.h netcmds.h neterr.h netget.h netinstcmd.h \
netlist.h netmisc.h netset.h netuser.h ssl.h sstate.h stype.h upsd.h \
upstype.h user-data.h user.h
sockdebug_SOURCES = sockdebug.c

615
server/Makefile.in Normal file
View file

@ -0,0 +1,615 @@
# Makefile.in generated by automake 1.11 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
# Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# Network UPS Tools: server
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
@WITH_WRAP_TRUE@am__append_1 = $(LIBWRAP_CFLAGS)
@WITH_SSL_TRUE@am__append_2 = $(LIBSSL_CFLAGS)
@WITH_WRAP_TRUE@am__append_3 = $(LIBWRAP_LDFLAGS)
@WITH_SSL_TRUE@am__append_4 = $(LIBSSL_LDFLAGS)
sbin_PROGRAMS = upsd$(EXEEXT)
EXTRA_PROGRAMS = sockdebug$(EXEEXT)
subdir = server
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_create_stdint_h.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_ipv6.m4 \
$(top_srcdir)/m4/nut_check_libgd.m4 \
$(top_srcdir)/m4/nut_check_libhal.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libpowerman.m4 \
$(top_srcdir)/m4/nut_check_libssl.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_report_feature.m4 \
$(top_srcdir)/m4/nut_type_socklen_t.m4 \
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(sbindir)"
PROGRAMS = $(sbin_PROGRAMS)
am_sockdebug_OBJECTS = sockdebug.$(OBJEXT)
sockdebug_OBJECTS = $(am_sockdebug_OBJECTS)
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.a \
../common/libparseconf.la $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3)
am_upsd_OBJECTS = upsd.$(OBJEXT) user.$(OBJEXT) conf.$(OBJEXT) \
ssl.$(OBJEXT) sstate.$(OBJEXT) desc.$(OBJEXT) netget.$(OBJEXT) \
netmisc.$(OBJEXT) netlist.$(OBJEXT) netuser.$(OBJEXT) \
netset.$(OBJEXT) netinstcmd.$(OBJEXT)
upsd_OBJECTS = $(am_upsd_OBJECTS)
upsd_LDADD = $(LDADD)
upsd_DEPENDENCIES = ../common/libcommon.a ../common/libparseconf.la \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
$(am__DEPENDENCIES_3)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(sockdebug_SOURCES) $(upsd_SOURCES)
DIST_SOURCES = $(sockdebug_SOURCES) $(upsd_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BINDIR = @BINDIR@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CONFPATH = @CONFPATH@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
HAL_CALLOUTS_PATH = @HAL_CALLOUTS_PATH@
HAL_DEVICE_MATCH_KEY = @HAL_DEVICE_MATCH_KEY@
HAL_FDI_PATH = @HAL_FDI_PATH@
HAL_USER = @HAL_USER@
HAVE_GLIB_2_14 = @HAVE_GLIB_2_14@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBGD_CFLAGS = @LIBGD_CFLAGS@
LIBGD_LDFLAGS = @LIBGD_LDFLAGS@
LIBHAL_CFLAGS = @LIBHAL_CFLAGS@
LIBHAL_LDFLAGS = @LIBHAL_LDFLAGS@
LIBNEON_CFLAGS = @LIBNEON_CFLAGS@
LIBNEON_LDFLAGS = @LIBNEON_LDFLAGS@
LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@
LIBNETSNMP_LDFLAGS = @LIBNETSNMP_LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBPOWERMAN_CFLAGS = @LIBPOWERMAN_CFLAGS@
LIBPOWERMAN_LDFLAGS = @LIBPOWERMAN_LDFLAGS@
LIBS = @LIBS@
LIBSSL_CFLAGS = @LIBSSL_CFLAGS@
LIBSSL_LDFLAGS = @LIBSSL_LDFLAGS@
LIBTOOL = @LIBTOOL@
LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
LIBUSB_LDFLAGS = @LIBUSB_LDFLAGS@
LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@
LIBWRAP_LDFLAGS = @LIBWRAP_LDFLAGS@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NETLIBS = @NETLIBS@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OS_NAME = @OS_NAME@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
RUN_AS_GROUP = @RUN_AS_GROUP@
RUN_AS_USER = @RUN_AS_USER@
SED = @SED@
SERLIBS = @SERLIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STATEPATH = @STATEPATH@
STRIP = @STRIP@
SUN_LIBUSB = @SUN_LIBUSB@
VERSION = @VERSION@
WORDS_BIGENDIAN = @WORDS_BIGENDIAN@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
cgiexecdir = @cgiexecdir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
driverexecdir = @driverexecdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
hotplugdir = @hotplugdir@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgconfigdir = @pkgconfigdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
udevdir = @udevdir@
# 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.
AM_CFLAGS = -I$(top_srcdir)/include $(am__append_1) $(am__append_2)
LDADD = ../common/libcommon.a ../common/libparseconf.la $(NETLIBS) \
$(am__append_3) $(am__append_4)
upsd_SOURCES = upsd.c user.c conf.c ssl.c sstate.c desc.c \
netget.c netmisc.c netlist.c netuser.c netset.c netinstcmd.c \
conf.h ctype.h desc.h netcmds.h neterr.h netget.h netinstcmd.h \
netlist.h netmisc.h netset.h netuser.h ssl.h sstate.h stype.h upsd.h \
upstype.h user-data.h user.h
sockdebug_SOURCES = sockdebug.c
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --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);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
install-sbinPROGRAMS: $(sbin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p || test -f $$p1; \
then echo "$$p"; echo "$$p"; else :; fi; \
done | \
sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
if ($$2 == $$4) files[d] = files[d] " " $$1; \
else { print "f", $$3 "/" $$4, $$1; } } \
END { for (d in files) print "f", d, files[d] }' | \
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
} \
; done
uninstall-sbinPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-e 's/$$/$(EXEEXT)/' `; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(sbindir)" && rm -f $$files
clean-sbinPROGRAMS:
@list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
echo " rm -f" $$list; \
rm -f $$list || exit $$?; \
test -n "$(EXEEXT)" || exit 0; \
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
sockdebug$(EXEEXT): $(sockdebug_OBJECTS) $(sockdebug_DEPENDENCIES)
@rm -f sockdebug$(EXEEXT)
$(LINK) $(sockdebug_OBJECTS) $(sockdebug_LDADD) $(LIBS)
upsd$(EXEEXT): $(upsd_OBJECTS) $(upsd_DEPENDENCIES)
@rm -f upsd$(EXEEXT)
$(LINK) $(upsd_OBJECTS) $(upsd_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
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)/netuser.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sockdebug.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ssl.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@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(PROGRAMS)
installdirs:
for dir in "$(DESTDIR)$(sbindir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \
mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am: install-sbinPROGRAMS
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-sbinPROGRAMS
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-libtool clean-sbinPROGRAMS ctags distclean \
distclean-compile distclean-generic distclean-libtool \
distclean-tags distdir dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-sbinPROGRAMS install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags uninstall uninstall-am uninstall-sbinPROGRAMS
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

489
server/conf.c Normal file
View file

@ -0,0 +1,489 @@
/* conf.c - configuration handlers for upsd
Copyright (C) 2001 Russell Kroll <rkroll@exploits.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "upsd.h"
#include "conf.h"
#include "upsconf.h"
#include "sstate.h"
#include "user.h"
#include "ssl.h"
ups_t *upstable = NULL;
int num_ups = 0;
/* add another UPS for monitoring from ups.conf */
static void ups_create(const char *fn, const char *name, const char *desc)
{
upstype_t *temp, *last;
temp = last = firstups;
/* find end of linked list */
while (temp != NULL) {
last = temp;
if (!strcasecmp(temp->name, name)) {
upslogx(LOG_ERR, "UPS name [%s] is already in use!",
name);
return;
}
temp = temp->next;
}
/* grab some memory and add the info */
temp = xmalloc(sizeof(upstype_t));
temp->name = xstrdup(name);
temp->fn = xstrdup(fn);
if (desc)
temp->desc = xstrdup(desc);
else
temp->desc = NULL;
temp->stale = 1;
temp->numlogins = 0;
temp->fsd = 0;
temp->retain = 1;
temp->next = NULL;
temp->dumpdone = 0;
temp->data_ok = 0;
/* preload this to the current time to avoid false staleness */
time(&temp->last_heard);
temp->last_ping = 0;
temp->last_connfail = 0;
temp->inforoot = NULL;
temp->cmdlist = NULL;
if (last == NULL)
firstups = temp;
else
last->next = temp;
temp->sock_fd = sstate_connect(temp);
num_ups++;
}
/* change the configuration of an existing UPS (used during reloads) */
static void ups_update(const char *fn, const char *name, const char *desc)
{
upstype_t *temp;
temp = get_ups_ptr(name);
if (!temp) {
upslogx(LOG_ERR, "UPS %s disappeared during reload", name);
return;
}
/* paranoia */
if (!temp->fn) {
upslogx(LOG_ERR, "UPS %s had a NULL filename!", name);
/* let's give it something quick to use later */
temp->fn = xstrdup("");
}
/* when the filename changes, force a reconnect */
if (strcmp(temp->fn, fn) != 0) {
upslogx(LOG_NOTICE, "Redefined UPS [%s]", name);
/* release all data */
sstate_infofree(temp);
sstate_cmdfree(temp);
pconf_finish(&temp->sock_ctx);
close(temp->sock_fd);
temp->sock_fd = -1;
temp->dumpdone = 0;
/* now redefine the filename and wrap up */
free(temp->fn);
temp->fn = xstrdup(fn);
}
/* update the description */
free(temp->desc);
if (desc)
temp->desc = xstrdup(desc);
else
temp->desc = NULL;
/* always set this on reload */
temp->retain = 1;
}
/* return 1 if usable, 0 if not */
static int parse_upsd_conf_args(int numargs, char **arg)
{
/* everything below here uses up through arg[1] */
if (numargs < 2)
return 0;
/* MAXAGE <seconds> */
if (!strcmp(arg[0], "MAXAGE")) {
maxage = atoi(arg[1]);
return 1;
}
/* MAXCONN <connections> */
if (!strcmp(arg[0], "MAXCONN")) {
maxconn = atoi(arg[1]);
return 1;
}
/* STATEPATH <dir> */
if (!strcmp(arg[0], "STATEPATH")) {
free(statepath);
statepath = xstrdup(arg[1]);
return 1;
}
/* DATAPATH <dir> */
if (!strcmp(arg[0], "DATAPATH")) {
free(datapath);
datapath = xstrdup(arg[1]);
return 1;
}
/* CERTFILE <dir> */
if (!strcmp(arg[0], "CERTFILE")) {
free(certfile);
certfile = xstrdup(arg[1]);
return 1;
}
/* ACCEPT <aclname> [<aclname>...] */
if (!strcmp(arg[0], "ACCEPT")) {
upslogx(LOG_WARNING, "ACCEPT in upsd.conf is no longer supported - switch to LISTEN");
return 1;
}
/* REJECT <aclname> [<aclname>...] */
if (!strcmp(arg[0], "REJECT")) {
upslogx(LOG_WARNING, "REJECT in upsd.conf is no longer supported - switch to LISTEN");
return 1;
}
/* LISTEN <address> [<port>] */
if (!strcmp(arg[0], "LISTEN")) {
if (numargs < 3)
listen_add(arg[1], string_const(PORT));
else
listen_add(arg[1], arg[2]);
return 1;
}
/* everything below here uses up through arg[2] */
if (numargs < 3)
return 0;
/* ACL <aclname> <ip block> */
if (!strcmp(arg[0], "ACL")) {
upslogx(LOG_WARNING, "ACL in upsd.conf is no longer supported - switch to LISTEN");
return 1;
}
/* not recognized */
return 0;
}
/* called for fatal errors in parseconf like malloc failures */
static void upsd_conf_err(const char *errmsg)
{
upslogx(LOG_ERR, "Fatal error in parseconf (upsd.conf): %s", errmsg);
}
void load_upsdconf(int reloading)
{
char fn[SMALLBUF];
PCONF_CTX_t ctx;
snprintf(fn, sizeof(fn), "%s/upsd.conf", confpath());
check_perms(fn);
pconf_init(&ctx, upsd_conf_err);
if (!pconf_file_begin(&ctx, fn)) {
pconf_finish(&ctx);
if (!reloading)
fatalx(EXIT_FAILURE, "%s", ctx.errmsg);
upslogx(LOG_ERR, "Reload failed: %s", ctx.errmsg);
return;
}
while (pconf_file_next(&ctx)) {
if (pconf_parse_error(&ctx)) {
upslogx(LOG_ERR, "Parse error: %s:%d: %s",
fn, ctx.linenum, ctx.errmsg);
continue;
}
if (ctx.numargs < 1)
continue;
if (!parse_upsd_conf_args(ctx.numargs, ctx.arglist)) {
unsigned int i;
char errmsg[SMALLBUF];
snprintf(errmsg, sizeof(errmsg),
"upsd.conf: invalid directive");
for (i = 0; i < ctx.numargs; i++)
snprintfcat(errmsg, sizeof(errmsg), " %s",
ctx.arglist[i]);
upslogx(LOG_WARNING, "%s", errmsg);
}
}
pconf_finish(&ctx);
}
/* callback during parsing of ups.conf */
void do_upsconf_args(char *upsname, char *var, char *val)
{
ups_t *tmp, *last;
/* no "global" stuff for us */
if (!upsname)
return;
last = tmp = upstable;
while (tmp) {
last = tmp;
if (!strcmp(tmp->upsname, upsname)) {
if (!strcmp(var, "driver"))
tmp->driver = xstrdup(val);
if (!strcmp(var, "port"))
tmp->port = xstrdup(val);
if (!strcmp(var, "desc"))
tmp->desc = xstrdup(val);
return;
}
tmp = tmp->next;
}
tmp = xmalloc(sizeof(ups_t));
tmp->upsname = xstrdup(upsname);
tmp->driver = NULL;
tmp->port = NULL;
tmp->desc = NULL;
tmp->next = NULL;
if (!strcmp(var, "driver"))
tmp->driver = xstrdup(val);
if (!strcmp(var, "port"))
tmp->port = xstrdup(val);
if (!strcmp(var, "desc"))
tmp->desc = xstrdup(val);
if (last)
last->next = tmp;
else
upstable = tmp;
}
/* add valid UPSes from ups.conf to the internal structures */
void upsconf_add(int reloading)
{
ups_t *tmp = upstable, *next;
char statefn[SMALLBUF];
if (!tmp) {
upslogx(LOG_WARNING, "Warning: no UPS definitions in ups.conf");
return;
}
while (tmp) {
/* save for later, since we delete as we go along */
next = tmp->next;
/* this should always be set, but better safe than sorry */
if (!tmp->upsname) {
tmp = tmp->next;
continue;
}
/* 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",
tmp->upsname);
} else {
snprintf(statefn, sizeof(statefn), "%s-%s",
tmp->driver, tmp->upsname);
/* if a UPS exists, update it, else add it as new */
if ((reloading) && (get_ups_ptr(tmp->upsname) != NULL))
ups_update(statefn, tmp->upsname, tmp->desc);
else
ups_create(statefn, tmp->upsname, tmp->desc);
}
/* free tmp's resources */
free(tmp->driver);
free(tmp->port);
free(tmp->desc);
free(tmp->upsname);
free(tmp);
tmp = next;
}
/* upstable should be completely gone by this point */
upstable = NULL;
}
/* remove a UPS from the linked list */
static void delete_ups(upstype_t *target)
{
upstype_t *ptr, *last;
if (!target)
return;
ptr = last = firstups;
while (ptr) {
if (ptr == target) {
upslogx(LOG_NOTICE, "Deleting UPS [%s]", target->name);
/* make sure nobody stays logged into this thing */
kick_login_clients(target->name);
/* about to delete the first ups? */
if (ptr == last)
firstups = ptr->next;
else
last->next = ptr->next;
if (ptr->sock_fd != -1)
close(ptr->sock_fd);
/* release memory */
sstate_infofree(ptr);
sstate_cmdfree(ptr);
pconf_finish(&ptr->sock_ctx);
free(ptr->fn);
free(ptr->name);
free(ptr->desc);
free(ptr);
return;
}
last = ptr;
ptr = ptr->next;
}
/* 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)
{
char chkfn[SMALLBUF];
FILE *f;
snprintf(chkfn, sizeof(chkfn), "%s/%s", confpath(), fn);
f = fopen(chkfn, "r");
if (!f) {
upslog_with_errno(LOG_ERR, "Reload failed: can't open %s", chkfn);
return 0; /* failed */
}
fclose(f);
return 1; /* OK */
}
/* called after SIGHUP */
void conf_reload(void)
{
upstype_t *upstmp, *upsnext;
upslogx(LOG_INFO, "SIGHUP: reloading configuration");
/* see if we can access upsd.conf before blowing away the config */
if (!check_file("upsd.conf"))
return;
/* reset retain flags on all known UPS entries */
upstmp = firstups;
while (upstmp) {
upstmp->retain = 0;
upstmp = upstmp->next;
}
/* reload from ups.conf */
read_upsconf();
upsconf_add(1); /* 1 = reloading */
/* now reread upsd.conf */
load_upsdconf(1); /* 1 = reloading */
/* now delete all UPS entries that didn't get reloaded */
upstmp = firstups;
while (upstmp) {
/* upstmp may be deleted during this pass */
upsnext = upstmp->next;
if (upstmp->retain == 0)
delete_ups(upstmp);
upstmp = upsnext;
}
/* did they actually delete the last UPS? */
if (firstups == NULL)
upslogx(LOG_WARNING, "Warning: no UPSes currently defined!");
/* and also make sure upsd.users can be read... */
if (!check_file("upsd.users"))
return;
/* delete all users */
user_flush();
/* and finally reread from upsd.users */
user_load();
}

43
server/conf.h Normal file
View file

@ -0,0 +1,43 @@
/* conf.h - supporting elements of conf parsing functions for upsd
Copyright (C)
2001 Russell Kroll <rkroll@exploits.org>
2008 Arjen de Korte <adkorte-guest@alioth.debian.org>
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
*/
/* read upsd.conf */
void load_upsdconf(int reloading);
/* add valid UPSes from ups.conf to the internal structures */
void upsconf_add(int reloading);
/* flush existing config, then reread everything */
void conf_reload(void);
typedef struct ups_s {
char *upsname;
char *driver;
char *port;
char *desc;
struct ups_s *next;
} ups_t;
/* used for really clean shutdowns */
void delete_acls(void);
void delete_access(void);
extern int num_ups;

55
server/ctype.h Normal file
View file

@ -0,0 +1,55 @@
/* ctype.h - client data definitions for upsd
Copyright (C)
2002 Russell Kroll <rkroll@exploits.org>
2008 Arjen de Korte <adkorte-guest@alioth.debian.org>
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 CTYPE_H_SEEN
#define CTYPE_H_SEEN 1
#ifdef HAVE_SSL
#include <openssl/err.h>
#include <openssl/ssl.h>
#endif
#include "parseconf.h"
/* client structure */
typedef struct ctype_s {
char *addr;
int sock_fd;
time_t last_heard;
char *loginups;
char *password;
char *username;
#ifdef HAVE_SSL
SSL *ssl;
#else
void *ssl;
#endif
int ssl_connected;
PCONF_CTX_t ctx;
/* doubly linked list */
struct ctype_s *prev;
struct ctype_s *next;
} ctype_t;
#endif /* CTYPE_H_SEEN */

165
server/desc.c Normal file
View file

@ -0,0 +1,165 @@
/* desc.c - variable/command description handling for upsd
Copyright (C) 2003 Russell Kroll <rkroll@exploits.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
#include "common.h"
#include "parseconf.h"
#include "desc.h"
extern const char *datapath;
struct dlist_t {
char *name;
char *desc;
struct dlist_t *next;
};
static struct dlist_t *cmd_list = NULL, *var_list = NULL;
static void list_free(struct dlist_t *ptr)
{
struct dlist_t *next;
while (ptr) {
next = ptr->next;
free(ptr->name);
free(ptr->desc);
free(ptr);
ptr = next;
}
}
static const char *list_get(const struct dlist_t *list, const char *name)
{
const struct dlist_t *tmp;
tmp = list;
while (tmp) {
if (!strcasecmp(tmp->name, name))
return tmp->desc;
tmp = tmp->next;
}
return NULL;
}
static void desc_add(struct dlist_t **list, const char *name, const char *desc)
{
struct dlist_t *tmp, *last;
tmp = last = *list;
while (tmp) {
last = tmp;
/* replace duplicates */
if (!strcasecmp(tmp->name, name)) {
free(tmp->desc);
tmp->desc = xstrdup(desc);
return;
}
tmp = tmp->next;
}
tmp = xmalloc(sizeof(struct dlist_t));
tmp->name = xstrdup(name);
tmp->desc = xstrdup(desc);
tmp->next = NULL;
if (last)
last->next = tmp;
else
*list = tmp;
}
static void desc_file_err(const char *errmsg)
{
upslogx(LOG_ERR, "Fatal error in parseconf (cmdvartab): %s", errmsg);
}
/* interface */
void desc_load(void)
{
char fn[SMALLBUF];
PCONF_CTX_t ctx;
snprintf(fn, sizeof(fn), "%s/cmdvartab", datapath);
pconf_init(&ctx, desc_file_err);
/* this file is not required */
if (!pconf_file_begin(&ctx, fn)) {
upslogx(LOG_INFO, "%s not found - disabling descriptions", fn);
pconf_finish(&ctx);
return;
}
while (pconf_file_next(&ctx)) {
if (pconf_parse_error(&ctx)) {
upslogx(LOG_ERR, "Parse error: %s:%d: %s",
fn, ctx.linenum, ctx.errmsg);
continue;
}
if (ctx.numargs < 3)
continue;
if (!strcmp(ctx.arglist[0], "CMDDESC")) {
desc_add(&cmd_list, ctx.arglist[1], ctx.arglist[2]);
continue;
}
if (!strcmp(ctx.arglist[0], "VARDESC")) {
desc_add(&var_list, ctx.arglist[1], ctx.arglist[2]);
continue;
}
/* unknown */
}
pconf_finish(&ctx);
}
void desc_free(void)
{
list_free(cmd_list);
list_free(var_list);
cmd_list = var_list = NULL;
}
const char *desc_get_cmd(const char *name)
{
return list_get(cmd_list, name);
}
const char *desc_get_var(const char *name)
{
return list_get(var_list, name);
}

4
server/desc.h Normal file
View file

@ -0,0 +1,4 @@
void desc_load(void);
void desc_free(void);
const char *desc_get_cmd(const char *name);
const char *desc_get_var(const char *name);

60
server/netcmds.h Normal file
View file

@ -0,0 +1,60 @@
/* netcmds.h - upsd support structure details
Copyright (C) 2001 Russell Kroll <rkroll@exploits.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ctype.h"
#include "ssl.h"
#include "netget.h"
#include "netset.h"
#include "netlist.h"
#include "netmisc.h"
#include "netuser.h"
#include "netinstcmd.h"
#define FLAG_USER 0x0001 /* username and password must be set */
struct netcmds_t {
const char *name;
void (*func)(ctype_t *client, int numargs, const char **arg);
int flags;
};
struct netcmds_t netcmds[] =
{
{ "VER", net_ver, 0 },
{ "HELP", net_help, 0 },
{ "STARTTLS", net_starttls, 0 },
{ "GET", net_get, 0 },
{ "LIST", net_list, 0 },
{ "USERNAME", net_username, 0 },
{ "PASSWORD", net_password, 0 },
{ "LOGIN", net_login, FLAG_USER },
{ "LOGOUT", net_logout, 0 },
{ "MASTER", net_master, FLAG_USER },
{ "FSD", net_fsd, FLAG_USER },
{ "SET", net_set, FLAG_USER },
{ "INSTCMD", net_instcmd, FLAG_USER },
{ NULL, (void(*)())(NULL), 0 }
};

35
server/neterr.h Normal file
View file

@ -0,0 +1,35 @@
/* network error definitions for consistency */
#define NUT_ERR_ACCESS_DENIED "ACCESS-DENIED"
#define NUT_ERR_UNKNOWN_UPS "UNKNOWN-UPS"
#define NUT_ERR_VAR_NOT_SUPPORTED "VAR-NOT-SUPPORTED"
#define NUT_ERR_CMD_NOT_SUPPORTED "CMD-NOT-SUPPORTED"
#define NUT_ERR_INVALID_ARGUMENT "INVALID-ARGUMENT"
#define NUT_ERR_INSTCMD_FAILED "INSTCMD-FAILED"
#define NUT_ERR_SET_FAILED "SET-FAILED"
#define NUT_ERR_READONLY "READONLY"
#define NUT_ERR_TOO_LONG "TOO-LONG"
#define NUT_ERR_FEATURE_NOT_SUPPORTED "FEATURE-NOT-SUPPORTED"
#define NUT_ERR_FEATURE_NOT_CONFIGURED "FEATURE-NOT-CONFIGURED"
#define NUT_ERR_ALREADY_SSL_MODE "ALREADY-SSL-MODE"
/* errors which are only used by top-level upsd functions */
#define NUT_ERR_DRIVER_NOT_CONNECTED "DRIVER-NOT-CONNECTED"
#define NUT_ERR_DATA_STALE "DATA-STALE"
#define NUT_ERR_ALREADY_LOGGED_IN "ALREADY-LOGGED-IN"
#define NUT_ERR_INVALID_PASSWORD "INVALID-PASSWORD"
#define NUT_ERR_ALREADY_SET_PASSWORD "ALREADY-SET-PASSWORD"
#define NUT_ERR_INVALID_USERNAME "INVALID-USERNAME"
#define NUT_ERR_ALREADY_SET_USERNAME "ALREADY-SET-USERNAME"
#define NUT_ERR_USERNAME_REQUIRED "USERNAME-REQUIRED"
#define NUT_ERR_PASSWORD_REQUIRED "PASSWORD-REQUIRED"
#define NUT_ERR_UNKNOWN_COMMAND "UNKNOWN-COMMAND"
/* errors which are only used with the old functions */
#define NUT_ERR_VAR_UNKNOWN "VAR-UNKNOWN"
#define NUT_ERR_UNKNOWN_TYPE "UNKNOWN-TYPE"
#define NUT_ERR_UNKNOWN_INSTCMD "UNKNOWN-INSTCMD"
#define NUT_ERR_MISSING_ARGUMENT "MISSING-ARGUMENT"
#define NUT_ERR_INVALID_VALUE "INVALID-VALUE"

266
server/netget.c Normal file
View file

@ -0,0 +1,266 @@
/* netget.c - GET handlers for upsd
Copyright (C) 2003 Russell Kroll <rkroll@exploits.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "common.h"
#include "upsd.h"
#include "sstate.h"
#include "state.h"
#include "desc.h"
#include "neterr.h"
#include "netget.h"
static void get_numlogins(ctype_t *client, const char *upsname)
{
const upstype_t *ups;
ups = get_ups_ptr(upsname);
if (!ups) {
send_err(client, NUT_ERR_UNKNOWN_UPS);
return;
}
if (!ups_available(ups, client))
return;
sendback(client, "NUMLOGINS %s %d\n", upsname, ups->numlogins);
}
static void get_upsdesc(ctype_t *client, const char *upsname)
{
const upstype_t *ups;
char esc[SMALLBUF];
ups = get_ups_ptr(upsname);
if (!ups) {
send_err(client, NUT_ERR_UNKNOWN_UPS);
return;
}
if (!ups_available(ups, client))
return;
if (ups->desc) {
pconf_encode(ups->desc, esc, sizeof(esc));
sendback(client, "UPSDESC %s \"%s\"\n", upsname, esc);
} else {
sendback(client, "UPSDESC %s \"Unavailable\"\n", upsname);
}
}
static void get_desc(ctype_t *client, const char *upsname, const char *var)
{
const upstype_t *ups;
const char *desc;
ups = get_ups_ptr(upsname);
if (!ups) {
send_err(client, NUT_ERR_UNKNOWN_UPS);
return;
}
if (!ups_available(ups, client))
return;
desc = desc_get_var(var);
if (desc)
sendback(client, "DESC %s %s \"%s\"\n", upsname, var, desc);
else
sendback(client, "DESC %s %s \"Description unavailable\"\n", upsname, var);
}
static void get_cmddesc(ctype_t *client, const char *upsname, const char *cmd)
{
const upstype_t *ups;
const char *desc;
ups = get_ups_ptr(upsname);
if (!ups) {
send_err(client, NUT_ERR_UNKNOWN_UPS);
return;
}
if (!ups_available(ups, client))
return;
desc = desc_get_cmd(cmd);
if (desc)
sendback(client, "CMDDESC %s %s \"%s\"\n", upsname, cmd, desc);
else
sendback(client, "CMDDESC %s %s \"Description unavailable\"\n",
upsname, cmd);
}
static void get_type(ctype_t *client, const char *upsname, const char *var)
{
char buf[SMALLBUF];
const upstype_t *ups;
const struct st_tree_t *node;
ups = get_ups_ptr(upsname);
if (!ups) {
send_err(client, NUT_ERR_UNKNOWN_UPS);
return;
}
if (!ups_available(ups, client))
return;
node = sstate_getnode(ups, var);
if (!node) {
send_err(client, NUT_ERR_VAR_NOT_SUPPORTED);
return;
}
snprintf(buf, sizeof(buf), "TYPE %s %s", upsname, var);
if (node->flags & ST_FLAG_RW)
snprintfcat(buf, sizeof(buf), " RW");
if (node->enum_list) {
sendback(client, "%s ENUM\n", buf);
return;
}
if (node->flags & ST_FLAG_STRING) {
sendback(client, "%s STRING:%d\n", buf, node->aux);
return;
}
/* hmm... */
sendback(client, "TYPE %s %s UNKNOWN\n", upsname, var);
}
static void get_var_server(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",
upsname, UPS_VERSION);
return;
}
if (!strcasecmp(var, "server.version")) {
sendback(client, "VAR %s server.version \"%s\"\n",
upsname, UPS_VERSION);
return;
}
send_err(client, NUT_ERR_VAR_NOT_SUPPORTED);
}
static void get_var(ctype_t *client, const char *upsname, const char *var)
{
const upstype_t *ups;
const char *val;
/* ignore upsname for server.* variables */
if (!strncasecmp(var, "server.", 7)) {
get_var_server(client, upsname, var);
return;
}
ups = get_ups_ptr(upsname);
if (!ups) {
send_err(client, NUT_ERR_UNKNOWN_UPS);
return;
}
if (!ups_available(ups, client))
return;
val = sstate_getinfo(ups, var);
if (!val) {
send_err(client, NUT_ERR_VAR_NOT_SUPPORTED);
return;
}
/* handle special case for status */
if ((!strcasecmp(var, "ups.status")) && (ups->fsd))
sendback(client, "VAR %s %s \"FSD %s\"\n", upsname, var, val);
else
sendback(client, "VAR %s %s \"%s\"\n", upsname, var, val);
}
void net_get(ctype_t *client, int numarg, const char **arg)
{
if (numarg < 2) {
send_err(client, NUT_ERR_INVALID_ARGUMENT);
return;
}
/* GET NUMLOGINS UPS */
if (!strcasecmp(arg[0], "NUMLOGINS")) {
get_numlogins(client, arg[1]);
return;
}
/* GET UPSDESC UPS */
if (!strcasecmp(arg[0], "UPSDESC")) {
get_upsdesc(client, arg[1]);
return;
}
if (numarg < 3) {
send_err(client, NUT_ERR_INVALID_ARGUMENT);
return;
}
/* GET VAR UPS VARNAME */
if (!strcasecmp(arg[0], "VAR")) {
get_var(client, arg[1], arg[2]);
return;
}
/* GET TYPE UPS VARNAME */
if (!strcasecmp(arg[0], "TYPE")) {
get_type(client, arg[1], arg[2]);
return;
}
/* GET DESC UPS VARNAME */
if (!strcasecmp(arg[0], "DESC")) {
get_desc(client, arg[1], arg[2]);
return;
}
/* GET CMDDESC UPS CMDNAME */
if (!strcasecmp(arg[0], "CMDDESC")) {
get_cmddesc(client, arg[1], arg[2]);
return;
}
send_err(client, NUT_ERR_INVALID_ARGUMENT);
return;
}

1
server/netget.h Normal file
View file

@ -0,0 +1 @@
void net_get(ctype_t *client, int numarg, const char **arg);

98
server/netinstcmd.c Normal file
View file

@ -0,0 +1,98 @@
/* netinstcmd.c - INSTCMD handler for upsd
Copyright (C) 2003 Russell Kroll <rkroll@exploits.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "common.h"
#include "upsd.h"
#include "sstate.h"
#include "state.h"
#include "user.h" /* for user_checkinstcmd */
#include "neterr.h"
#include "netinstcmd.h"
static void send_instcmd(ctype_t *client, const char *upsname,
const char *cmdname)
{
int found;
upstype_t *ups;
const struct cmdlist_t *ctmp;
char sockcmd[SMALLBUF];
ups = get_ups_ptr(upsname);
if (!ups) {
send_err(client, NUT_ERR_UNKNOWN_UPS);
return;
}
if (!ups_available(ups, client))
return;
ctmp = sstate_getcmdlist(ups);
found = 0;
while (ctmp) {
if (!strcasecmp(ctmp->name, cmdname)) {
found = 1;
break;
}
ctmp = ctmp->next;
}
if (!found) {
send_err(client, NUT_ERR_CMD_NOT_SUPPORTED);
return;
}
/* see if this user is allowed to do this command */
if (!user_checkinstcmd(client->username, client->password, cmdname)) {
send_err(client, NUT_ERR_ACCESS_DENIED);
return;
}
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);
if (!sstate_sendline(ups, sockcmd)) {
upslogx(LOG_INFO, "Set command send failed");
send_err(client, NUT_ERR_INSTCMD_FAILED);
return;
}
sendback(client, "OK\n");
}
void net_instcmd(ctype_t *client, int numarg, const char **arg)
{
if (numarg < 2) {
send_err(client, NUT_ERR_INVALID_ARGUMENT);
return;
}
/* INSTCMD <ups> <cmdname> */
send_instcmd(client, arg[0], arg[1]);
return;
}

1
server/netinstcmd.h Normal file
View file

@ -0,0 +1 @@
void net_instcmd(ctype_t *client, int numarg, const char **arg);

268
server/netlist.c Normal file
View file

@ -0,0 +1,268 @@
/* netlist.c - LIST handlers for upsd
Copyright (C) 2003 Russell Kroll <rkroll@exploits.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "common.h"
#include "upsd.h"
#include "sstate.h"
#include "state.h"
#include "neterr.h"
#include "netlist.h"
extern upstype_t *firstups; /* for list_ups */
static int tree_dump(struct st_tree_t *node, ctype_t *client, const char *ups,
int rw, int fsd)
{
int ret;
if (!node)
return 1; /* not an error */
if (node->left) {
ret = tree_dump(node->left, client, ups, rw, fsd);
if (!ret)
return 0; /* write failed in child */
}
if (rw) {
/* only send this back if it's been flagged RW */
if (node->flags & ST_FLAG_RW) {
ret = sendback(client, "RW %s %s \"%s\"\n",
ups, node->var, node->val);
} else {
ret = 1; /* dummy */
}
} else {
/* normal variable list only */
/* status is always a special case */
if ((fsd == 1) && (!strcasecmp(node->var, "ups.status"))) {
ret = sendback(client, "VAR %s %s \"FSD %s\"\n",
ups, node->var, node->val);
} else {
ret = sendback(client, "VAR %s %s \"%s\"\n",
ups, node->var, node->val);
}
}
if (ret != 1)
return 0;
if (node->right)
return tree_dump(node->right, client, ups, rw, fsd);
return 1;
}
static void list_rw(ctype_t *client, const char *upsname)
{
const upstype_t *ups;
ups = get_ups_ptr(upsname);
if (!ups) {
send_err(client, NUT_ERR_UNKNOWN_UPS);
return;
}
if (!ups_available(ups, client))
return;
if (!sendback(client, "BEGIN LIST RW %s\n", upsname))
return;
if (!tree_dump(ups->inforoot, client, upsname, 1, ups->fsd))
return;
sendback(client, "END LIST RW %s\n", upsname);
}
static void list_var(ctype_t *client, const char *upsname)
{
const upstype_t *ups;
ups = get_ups_ptr(upsname);
if (!ups) {
send_err(client, NUT_ERR_UNKNOWN_UPS);
return;
}
if (!ups_available(ups, client))
return;
if (!sendback(client, "BEGIN LIST VAR %s\n", upsname))
return;
if (!tree_dump(ups->inforoot, client, upsname, 0, ups->fsd))
return;
sendback(client, "END LIST VAR %s\n", upsname);
}
static void list_cmd(ctype_t *client, const char *upsname)
{
const upstype_t *ups;
struct cmdlist_t *ctmp;
ups = get_ups_ptr(upsname);
if (!ups) {
send_err(client, NUT_ERR_UNKNOWN_UPS);
return;
}
if (!ups_available(ups, client))
return;
if (!sendback(client, "BEGIN LIST CMD %s\n", upsname))
return;
for (ctmp = ups->cmdlist; ctmp != NULL; ctmp = ctmp->next) {
if (!sendback(client, "CMD %s %s\n", upsname, ctmp->name))
return;
}
sendback(client, "END LIST CMD %s\n", upsname);
}
static void list_enum(ctype_t *client, const char *upsname, const char *var)
{
const upstype_t *ups;
const struct st_tree_t *node;
const struct enum_t *etmp;
ups = get_ups_ptr(upsname);
if (!ups) {
send_err(client, NUT_ERR_UNKNOWN_UPS);
return;
}
if (!ups_available(ups, client))
return;
node = sstate_getnode(ups, var);
if (!node) {
send_err(client, NUT_ERR_VAR_NOT_SUPPORTED);
return;
}
if (!sendback(client, "BEGIN LIST ENUM %s %s\n", upsname, var))
return;
for (etmp = node->enum_list; etmp != NULL; etmp = etmp->next) {
if (!sendback(client, "ENUM %s %s \"%s\"\n",
upsname, var, etmp->val))
return;
}
sendback(client, "END LIST ENUM %s %s\n", upsname, var);
}
static void list_ups(ctype_t *client)
{
upstype_t *utmp;
char esc[SMALLBUF];
if (!sendback(client, "BEGIN LIST UPS\n"))
return;
utmp = firstups;
while (utmp) {
int ret;
if (utmp->desc) {
pconf_encode(utmp->desc, esc, sizeof(esc));
ret = sendback(client, "UPS %s \"%s\"\n",
utmp->name, esc);
} else {
ret = sendback(client, "UPS %s \"Unavailable\"\n",
utmp->name);
}
if (!ret)
return;
utmp = utmp->next;
}
sendback(client, "END LIST UPS\n");
}
void net_list(ctype_t *client, int numarg, const char **arg)
{
if (numarg < 1) {
send_err(client, NUT_ERR_INVALID_ARGUMENT);
return;
}
/* LIST UPS */
if (!strcasecmp(arg[0], "UPS")) {
list_ups(client);
return;
}
if (numarg < 2) {
send_err(client, NUT_ERR_INVALID_ARGUMENT);
return;
}
/* LIST VAR UPS */
if (!strcasecmp(arg[0], "VAR")) {
list_var(client, arg[1]);
return;
}
/* LIST RW UPS */
if (!strcasecmp(arg[0], "RW")) {
list_rw(client, arg[1]);
return;
}
/* LIST CMD UPS */
if (!strcasecmp(arg[0], "CMD")) {
list_cmd(client, arg[1]);
return;
}
if (numarg < 3) {
send_err(client, NUT_ERR_INVALID_ARGUMENT);
return;
}
/* LIST ENUM UPS VARNAME */
if (!strcasecmp(arg[0], "ENUM")) {
list_enum(client, arg[1], arg[2]);
return;
}
send_err(client, NUT_ERR_INVALID_ARGUMENT);
}

1
server/netlist.h Normal file
View file

@ -0,0 +1 @@
void net_list(ctype_t *client, int numarg, const char **arg);

80
server/netmisc.c Normal file
View file

@ -0,0 +1,80 @@
/* netmisc.c - miscellaneous network handlers for upsd (VER, HELP, FSD)
Copyright (C) 2003 Russell Kroll <rkroll@exploits.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "common.h"
#include "upsd.h"
#include "sstate.h"
#include "state.h"
#include "user.h" /* for user_checkaction */
#include "neterr.h"
#include "netmisc.h"
void net_ver(ctype_t *client, int numarg, const char **arg)
{
if (numarg != 0) {
send_err(client, NUT_ERR_INVALID_ARGUMENT);
return;
}
sendback(client, "Network UPS Tools upsd %s - http://www.networkupstools.org/\n",
UPS_VERSION);
}
void net_help(ctype_t *client, int numarg, const char **arg)
{
if (numarg != 0) {
send_err(client, NUT_ERR_INVALID_ARGUMENT);
return;
}
sendback(client, "Commands: HELP VER GET LIST SET INSTCMD LOGIN LOGOUT"
" USERNAME PASSWORD STARTTLS\n");
}
void net_fsd(ctype_t *client, int numarg, const char **arg)
{
upstype_t *ups;
if (numarg != 1) {
send_err(client, NUT_ERR_INVALID_ARGUMENT);
return;
}
ups = get_ups_ptr(arg[0]);
if (!ups) {
send_err(client, NUT_ERR_UNKNOWN_UPS);
return;
}
/* 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]",
client->username, client->addr, ups->name);
ups->fsd = 1;
sendback(client, "OK FSD-SET\n");
}

3
server/netmisc.h Normal file
View file

@ -0,0 +1,3 @@
void net_ver(ctype_t *client, int numarg, const char **arg);
void net_help(ctype_t *client, int numarg, const char **arg);
void net_fsd(ctype_t *client, int numarg, const char **arg);

143
server/netset.c Normal file
View file

@ -0,0 +1,143 @@
/* netset.c - SET handler for upsd
Copyright (C) 2003 Russell Kroll <rkroll@exploits.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "common.h"
#include "upsd.h"
#include "sstate.h"
#include "state.h"
#include "user.h" /* for user_checkaction */
#include "neterr.h"
#include "netset.h"
static void set_var(ctype_t *client, const char *upsname, const char *var,
const char *newval)
{
upstype_t *ups;
const char *val;
const struct enum_t *etmp;
char cmd[SMALLBUF], esc[SMALLBUF];
ups = get_ups_ptr(upsname);
if (!ups) {
send_err(client, NUT_ERR_UNKNOWN_UPS);
return;
}
if (!ups_available(ups, client))
return;
/* make sure this user is allowed to do SET */
if (!user_checkaction(client->username, client->password, "SET")) {
send_err(client, NUT_ERR_ACCESS_DENIED);
return;
}
val = sstate_getinfo(ups, var);
if (!val) {
send_err(client, NUT_ERR_VAR_NOT_SUPPORTED);
return;
}
/* make sure this variable is writable (RW) */
if ((sstate_getflags(ups, var) & ST_FLAG_RW) == 0) {
send_err(client, NUT_ERR_READONLY);
return;
}
/* see if the new value is allowed for this variable */
if (sstate_getflags(ups, var) & ST_FLAG_STRING) {
int aux;
aux = sstate_getaux(ups, var);
/* check for insanity from the driver */
if (aux < 1) {
upslogx(LOG_WARNING, "UPS [%s]: auxdata for %s is invalid",
ups->name, var);
send_err(client, NUT_ERR_SET_FAILED);
return;
}
if (aux < (int) strlen(newval)) {
send_err(client, NUT_ERR_TOO_LONG);
return;
}
}
/* see if it's enumerated */
etmp = sstate_getenumlist(ups, var);
if (etmp) {
int found = 0;
while (etmp) {
if (!strcmp(etmp->val, newval)) {
found = 1;
break;
}
etmp = etmp->next;
}
if (!found) {
send_err(client, NUT_ERR_INVALID_VALUE);
return;
}
}
/* 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",
var, pconf_encode(newval, esc, sizeof(esc)));
if (!sstate_sendline(ups, cmd)) {
upslogx(LOG_INFO, "Set command send failed");
send_err(client, NUT_ERR_SET_FAILED);
return;
}
sendback(client, "OK\n");
}
void net_set(ctype_t *client, int numarg, const char **arg)
{
if (numarg < 4) {
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]);
return;
}
send_err(client, NUT_ERR_INVALID_ARGUMENT);
return;
}

1
server/netset.h Normal file
View file

@ -0,0 +1 @@
void net_set(ctype_t *client, int numarg, const char **arg);

154
server/netuser.c Normal file
View file

@ -0,0 +1,154 @@
/* netuser.c - LOGIN/LOGOUT/USERNAME/PASSWORD/MASTER handlers for upsd
Copyright (C) 2003 Russell Kroll <rkroll@exploits.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "common.h"
#include "upsd.h"
#include "sstate.h"
#include "state.h"
#include "neterr.h"
#include "user.h" /* for user_checkaction */
#include "netuser.h"
/* LOGIN <ups> */
void net_login(ctype_t *client, int numarg, const char **arg)
{
upstype_t *ups;
if (numarg != 1) {
send_err(client, NUT_ERR_INVALID_ARGUMENT);
return;
}
if (client->loginups != NULL) {
upslogx(LOG_INFO, "Client %s@%s tried to login twice", client->username, client->addr);
send_err(client, NUT_ERR_ALREADY_LOGGED_IN);
return;
}
/* make sure we got a valid UPS name */
ups = get_ups_ptr(arg[0]);
if (!ups) {
send_err(client, NUT_ERR_UNKNOWN_UPS);
return;
}
/* make sure this is a valid user */
if (!user_checkaction(client->username, client->password, "LOGIN")) {
send_err(client, NUT_ERR_ACCESS_DENIED);
return;
}
ups->numlogins++;
client->loginups = xstrdup(ups->name);
upslogx(LOG_INFO, "User %s@%s logged into UPS [%s]%s", client->username, client->addr,
client->loginups, client->ssl ? " (SSL)" : "");
sendback(client, "OK\n");
}
void net_logout(ctype_t *client, int numarg, const char **arg)
{
if (numarg != 0) {
send_err(client, NUT_ERR_INVALID_ARGUMENT);
return;
}
if (client->loginups != NULL) {
upslogx(LOG_INFO, "User %s@%s logged out from UPS [%s]%s", client->username, client->addr,
client->loginups, client->ssl ? " (SSL)" : "");
}
sendback(client, "OK Goodbye\n");
client->last_heard = 0;
}
/* MASTER <upsname> */
void net_master(ctype_t *client, int numarg, const char **arg)
{
upstype_t *ups;
if (numarg != 1) {
send_err(client, NUT_ERR_INVALID_ARGUMENT);
return;
}
ups = get_ups_ptr(arg[0]);
if (!ups) {
send_err(client, NUT_ERR_UNKNOWN_UPS);
return;
}
/* make sure this user is allowed to do MASTER */
if (!user_checkaction(client->username, client->password, "MASTER")) {
send_err(client, NUT_ERR_ACCESS_DENIED);
return;
}
/* this is just an access level check */
sendback(client, "OK MASTER-GRANTED\n");
}
/* USERNAME <username> */
void net_username(ctype_t *client, int numarg, const char **arg)
{
if (numarg != 1) {
send_err(client, NUT_ERR_INVALID_ARGUMENT);
return;
}
if (client->username != NULL) {
upslogx(LOG_INFO, "Client %s@%s tried to set a username twice",
client->username, client->addr);
send_err(client, NUT_ERR_ALREADY_SET_USERNAME);
return;
}
client->username = xstrdup(arg[0]);
sendback(client, "OK\n");
}
/* PASSWORD <password> */
void net_password(ctype_t *client, int numarg, const char **arg)
{
if (numarg != 1) {
send_err(client, NUT_ERR_INVALID_ARGUMENT);
return;
}
if (client->password != NULL) {
if (client->username)
upslogx(LOG_INFO, "Client %s@%s tried to set a password twice",
client->username, client->addr);
else
upslogx(LOG_INFO, "Client on %s tried to set a password twice",
client->addr);
send_err(client, NUT_ERR_ALREADY_SET_PASSWORD);
return;
}
client->password = xstrdup(arg[0]);
sendback(client, "OK\n");
}

5
server/netuser.h Normal file
View file

@ -0,0 +1,5 @@
void net_login(ctype_t *client, int numarg, const char **arg);
void net_logout(ctype_t *client, int numarg, const char **arg);
void net_master(ctype_t *client, int numarg, const char **arg);
void net_username(ctype_t *client, int numarg, const char **arg);
void net_password(ctype_t *client, int numarg, const char **arg);

171
server/sockdebug.c Normal file
View file

@ -0,0 +1,171 @@
/* sockdebug.c - Network UPS Tools driver-server socket debugger
Copyright (C) 2003 Russell Kroll <rkroll@exploits.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "common.h"
#include "parseconf.h"
PCONF_CTX_t sock_ctx;
static void sock_arg(int numarg, char **arg)
{
int i;
printf("numarg=%d : ", numarg);
for (i = 0; i < numarg; i++)
printf("[%s] ", arg[i]);
printf("\n");
}
static int socket_connect(const char *sockfn)
{
int ret, fd;
struct sockaddr_un sa;
memset(&sa, '\0', sizeof(sa));
sa.sun_family = AF_UNIX;
snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", sockfn);
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
ret = connect(fd, (struct sockaddr *) &sa, sizeof(sa));
if (ret < 0) {
perror("connect");
exit(EXIT_FAILURE);
}
#if 0
ret = fcntl(fd, F_GETFL, 0);
if (ret < 0) {
perror("fcntl(get)");
exit(EXIT_FAILURE);
}
ret = fcntl(fd, F_SETFL, ret | O_NDELAY);
if (ret < 0) {
perror("fcntl(set)");
exit(EXIT_FAILURE);
}
#endif
return fd;
}
static void read_sock(int fd)
{
int i, ret;
char buf[SMALLBUF];
ret = read(fd, buf, sizeof(buf));
if (ret == 0) {
fprintf(stderr, "read on socket returned 0\n");
exit(EXIT_FAILURE);
}
if (ret < 0) {
perror("read sockfd");
exit(EXIT_FAILURE);
}
for (i = 0; i < ret; i++) {
switch (pconf_char(&sock_ctx, buf[i])) {
case 1:
sock_arg(sock_ctx.numargs, sock_ctx.arglist);
break;
case -1:
printf("Parse error: [%s]\n", sock_ctx.errmsg);
break;
}
}
}
int main(int argc, char **argv)
{
int ret, sockfd;
if (argc != 2) {
fprintf(stderr, "usage: %s <socket name>\n", argv[0]);
fprintf(stderr, " %s /var/state/ups/apcsmart-ttyS1.newsock\n",
argv[0]);
exit(EXIT_SUCCESS);
}
sockfd = socket_connect(argv[1]);
printf("connected: fd %d\n", sockfd);
pconf_init(&sock_ctx, NULL);
for (;;) {
struct timeval tv;
fd_set rfds;
int maxfd;
tv.tv_sec = 2;
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(fileno(stdin), &rfds);
FD_SET(sockfd, &rfds);
/* paranoia */
maxfd = (sockfd > fileno(stdin)) ? sockfd : fileno(stdin);
ret = select(maxfd + 1, &rfds, NULL, NULL, &tv);
if (FD_ISSET(sockfd, &rfds))
read_sock(sockfd);
if (FD_ISSET(fileno(stdin), &rfds)) {
char buf[SMALLBUF];
fgets(buf, sizeof(buf), stdin);
ret = write(sockfd, buf, strlen(buf));
if ((ret < 0) || (ret != (int) strlen(buf))) {
perror("write to socket");
exit(EXIT_FAILURE);
}
}
}
/* NOTREACHED */
exit(EXIT_FAILURE);
}

248
server/ssl.c Normal file
View file

@ -0,0 +1,248 @@
/* ssl.c - Interface to OpenSSL for upsd
Copyright (C)
2002 Russell Kroll <rkroll@exploits.org>
2008 Arjen de Korte <adkorte-guest@alioth.debian.org>
based on the original implementation:
Copyright (C) 2002 Technorama Ltd. <oss-list-ups@technorama.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "upsd.h"
#include "neterr.h"
#include "ssl.h"
char *certfile = NULL;
static int ssl_initialized = 0;
#ifndef HAVE_SSL
/* stubs for non-ssl compiles */
void net_starttls(ctype_t *client, int numarg, const char **arg)
{
send_err(client, NUT_ERR_FEATURE_NOT_SUPPORTED);
return;
}
int ssl_write(ctype_t *client, const char *buf, size_t buflen)
{
upslogx(LOG_ERR, "ssl_write called but SSL wasn't compiled in");
return -1;
}
int ssl_read(ctype_t *client, char *buf, size_t buflen)
{
upslogx(LOG_ERR, "ssl_read called but SSL wasn't compiled in");
return -1;
}
void ssl_init(void)
{
ssl_initialized = 0; /* keep gcc quiet */
}
void ssl_finish(ctype_t *client)
{
if (client->ssl) {
upslogx(LOG_ERR, "ssl_finish found active SSL connection but SSL wasn't compiled in");
}
}
#else
static SSL_CTX *ssl_ctx = NULL;
static void ssl_debug(void)
{
int e;
char errmsg[SMALLBUF];
while ((e = ERR_get_error()) != 0) {
ERR_error_string_n(e, errmsg, sizeof(errmsg));
upsdebugx(1, "ssl_debug: %s", errmsg);
}
}
void net_starttls(ctype_t *client, int numarg, const char **arg)
{
if (client->ssl) {
send_err(client, NUT_ERR_ALREADY_SSL_MODE);
return;
}
if ((!ssl_ctx) || (!certfile) || (!ssl_initialized)) {
send_err(client, NUT_ERR_FEATURE_NOT_CONFIGURED);
return;
}
if (!sendback(client, "OK STARTTLS\n")) {
return;
}
client->ssl = SSL_new(ssl_ctx);
if (!client->ssl) {
upslog_with_errno(LOG_ERR, "SSL_new failed\n");
ssl_debug();
return;
}
if (SSL_set_fd(client->ssl, client->sock_fd) != 1) {
upslog_with_errno(LOG_ERR, "SSL_set_fd failed\n");
ssl_debug();
}
}
void ssl_init(void)
{
if (!certfile) {
return;
}
check_perms(certfile);
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
if ((ssl_ctx = SSL_CTX_new(TLSv1_server_method())) == NULL) {
fatal_with_errno(EXIT_FAILURE, "SSL_CTX_new");
}
if (SSL_CTX_use_RSAPrivateKey_file(ssl_ctx, certfile, SSL_FILETYPE_PEM) != 1) {
ssl_debug();
upslogx(LOG_ERR, "SSL_CTX_use_RSAPrivateKey_file(%s) failed", certfile);
return;
}
if (SSL_CTX_use_certificate_chain_file(ssl_ctx, certfile) != 1) {
upslogx(LOG_ERR, "SSL_CTX_use_certificate_chain_file(%s) failed", certfile);
return;
}
if (SSL_CTX_check_private_key(ssl_ctx) != 1) {
upslogx(LOG_ERR, "SSL_CTX_check_private_key(%s) failed", certfile);
return;
}
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL);
if (SSL_CTX_set_cipher_list(ssl_ctx, "HIGH:@STRENGTH") != 1) {
fatalx(EXIT_FAILURE, "SSL_CTX_set_cipher_list");
}
ssl_initialized = 1;
}
static int ssl_error(SSL *ssl, int ret)
{
int e;
e = SSL_get_error(ssl, ret);
switch (e)
{
case SSL_ERROR_WANT_READ:
upsdebugx(1, "ssl_error() ret=%d SSL_ERROR_WANT_READ", ret);
break;
case SSL_ERROR_WANT_WRITE:
upsdebugx(1, "ssl_error() ret=%d 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);
}
break;
default:
upsdebugx(1, "ssl_error() ret=%d SSL_ERROR %d", ret, e);
ssl_debug();
}
return -1;
}
static int ssl_accept(ctype_t *client)
{
int ret;
ret = SSL_accept(client->ssl);
switch (ret)
{
case 1:
client->ssl_connected = 1;
upsdebugx(3, "SSL connected");
return 0;
case 0:
case -1:
return ssl_error(client->ssl, ret);
}
upslog_with_errno(LOG_ERR, "Unknown return value from SSL_accept");
return -1;
}
int ssl_read(ctype_t *client, char *buf, size_t buflen)
{
int ret;
if (!client->ssl_connected) {
if (ssl_accept(client) != 0)
return -1;
}
ret = SSL_read(client->ssl, buf, buflen);
if (ret < 1) {
ssl_error(client->ssl, ret);
return -1;
}
return ret;
}
int ssl_write(ctype_t *client, const char *buf, size_t buflen)
{
int ret;
ret = SSL_write(client->ssl, buf, buflen);
upsdebugx(5, "ssl_write ret=%d", ret);
return ret;
}
void ssl_finish(ctype_t *client)
{
if (client->ssl) {
SSL_free(client->ssl);
}
}
#endif /* HAVE_SSL */

40
server/ssl.h Normal file
View file

@ -0,0 +1,40 @@
/* ssl.h - ssl support prototypes for upsd
Copyright (C) 2002 Russell Kroll <rkroll@exploits.org>
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 SSL_H_SEEN
#define SSL_H_SEEN 1
#ifdef HAVE_SSL
#include <openssl/err.h>
#include <openssl/ssl.h>
#endif
#include "ctype.h"
extern char *certfile;
void ssl_init(void);
void ssl_finish(ctype_t *client);
int ssl_read(ctype_t *client, char *buf, size_t buflen);
int ssl_write(ctype_t *client, const char *buf, size_t buflen);
void net_starttls(ctype_t *client, int numarg, const char **arg);
#endif /* SSL_H_SEEN */

382
server/sstate.c Normal file
View file

@ -0,0 +1,382 @@
/* sstate.c - Network UPS Tools server-side state management
Copyright (C)
2003 Russell Kroll <rkroll@exploits.org>
2008 Arjen de Korte <adkorte-guest@alioth.debian.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "common.h"
#include "timehead.h"
#include "upstype.h"
#include "sstate.h"
#include "state.h"
static int parse_args(upstype_t *ups, int numargs, char **arg)
{
if (numargs < 1)
return 0;
if (!strcasecmp(arg[0], "PONG")) {
upsdebugx(3, "Got PONG from UPS [%s]", ups->name);
return 1;
}
if (!strcasecmp(arg[0], "DUMPDONE")) {
upsdebugx(3, "UPS [%s]: dump is done", ups->name);
ups->dumpdone = 1;
return 1;
}
if (!strcasecmp(arg[0], "DATASTALE")) {
ups->data_ok = 0;
return 1;
}
if (!strcasecmp(arg[0], "DATAOK")) {
ups->data_ok = 1;
return 1;
}
if (numargs < 2)
return 0;
/* ADDCMD <cmdname> */
if (!strcasecmp(arg[0], "ADDCMD")) {
state_addcmd(&ups->cmdlist, arg[1]);
return 1;
}
/* DELCMD <cmdname> */
if (!strcasecmp(arg[0], "DELCMD")) {
state_delcmd(&ups->cmdlist, arg[1]);
return 1;
}
/* DELINFO <var> */
if (!strcasecmp(arg[0], "DELINFO")) {
state_delinfo(&ups->inforoot, arg[1]);
return 1;
}
if (numargs < 3)
return 0;
/* SETFLAGS <varname> <flags>... */
if (!strcasecmp(arg[0], "SETFLAGS")) {
state_setflags(ups->inforoot, arg[1], numargs - 2, &arg[2]);
return 1;
}
/* SETINFO <varname> <value> */
if (!strcasecmp(arg[0], "SETINFO")) {
state_setinfo(&ups->inforoot, arg[1], arg[2]);
return 1;
}
/* ADDENUM <varname> <enumval> */
if (!strcasecmp(arg[0], "ADDENUM")) {
state_addenum(ups->inforoot, arg[1], arg[2]);
return 1;
}
/* DELENUM <varname> <enumval> */
if (!strcasecmp(arg[0], "DELENUM")) {
state_delenum(ups->inforoot, arg[1], arg[2]);
return 1;
}
/* SETAUX <varname> <auxval> */
if (!strcasecmp(arg[0], "SETAUX")) {
state_setaux(ups->inforoot, arg[1], arg[2]);
return 1;
}
return 0;
}
/* nothing fancy - just make the driver say something back to us */
static void sendping(upstype_t *ups)
{
int ret;
const char *cmd = "PING\n";
if ((!ups) || (ups->sock_fd < 0)) {
return;
}
upsdebugx(3, "Pinging UPS [%s]", ups->name);
ret = write(ups->sock_fd, cmd, strlen(cmd));
if (ret != (int)strlen(cmd)) {
upslog_with_errno(LOG_NOTICE, "Send ping to UPS [%s] failed", ups->name);
sstate_disconnect(ups);
return;
}
time(&ups->last_ping);
}
/* interface */
int sstate_connect(upstype_t *ups)
{
int ret, fd;
const char *dumpcmd = "DUMPALL\n";
struct sockaddr_un sa;
memset(&sa, '\0', sizeof(sa));
sa.sun_family = AF_UNIX;
snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", ups->fn);
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
upslog_with_errno(LOG_ERR, "Can't create socket for UPS [%s]", ups->name);
return -1;
}
ret = connect(fd, (struct sockaddr *) &sa, sizeof(sa));
if (ret < 0) {
time_t now;
close(fd);
/* rate-limit complaints - don't spam the syslog */
time(&now);
if (difftime(now, ups->last_connfail) < SS_CONNFAIL_INT)
return -1;
ups->last_connfail = now;
upslog_with_errno(LOG_ERR, "Can't connect to UPS [%s] (%s)",
ups->name, ups->fn);
return -1;
}
ret = fcntl(fd, F_GETFL, 0);
if (ret < 0) {
upslog_with_errno(LOG_ERR, "fcntl get on UPS [%s] failed", ups->name);
close(fd);
return -1;
}
ret = fcntl(fd, F_SETFL, ret | O_NDELAY);
if (ret < 0) {
upslog_with_errno(LOG_ERR, "fcntl set O_NDELAY on UPS [%s] failed", ups->name);
close(fd);
return -1;
}
/* get a dump started so we have a fresh set of data */
ret = write(fd, dumpcmd, strlen(dumpcmd));
if (ret != (int)strlen(dumpcmd)) {
upslog_with_errno(LOG_ERR, "Initial write to UPS [%s] failed", ups->name);
close(fd);
return -1;
}
pconf_init(&ups->sock_ctx, NULL);
ups->dumpdone = 0;
ups->stale = 0;
/* now is the last time we heard something from the driver */
time(&ups->last_heard);
/* set ups.status to "WAIT" while waiting for the driver response to dumpcmd */
state_setinfo(&ups->inforoot, "ups.status", "WAIT");
upslogx(LOG_INFO, "Connected to UPS [%s]: %s", ups->name, ups->fn);
return fd;
}
void sstate_disconnect(upstype_t *ups)
{
if ((!ups) || (ups->sock_fd < 0)) {
return;
}
sstate_infofree(ups);
sstate_cmdfree(ups);
pconf_finish(&ups->sock_ctx);
close(ups->sock_fd);
ups->sock_fd = -1;
}
void sstate_readline(upstype_t *ups)
{
int i, ret;
char buf[SMALLBUF];
if ((!ups) || (ups->sock_fd < 0)) {
return;
}
ret = read(ups->sock_fd, buf, sizeof(buf));
if (ret < 0) {
switch(errno)
{
case EINTR:
case EAGAIN:
return;
default:
upslog_with_errno(LOG_WARNING, "Read from UPS [%s] failed", ups->name);
sstate_disconnect(ups);
return;
}
}
for (i = 0; i < ret; i++) {
switch (pconf_char(&ups->sock_ctx, buf[i]))
{
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);
}
continue;
case 0:
continue; /* haven't gotten a line yet */
default:
/* parse error */
upslogx(LOG_NOTICE, "Parse error on sock: %s", ups->sock_ctx.errmsg);
return;
}
}
}
const char *sstate_getinfo(const upstype_t *ups, const char *var)
{
return state_getinfo(ups->inforoot, 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)
{
return state_getaux(ups->inforoot, var);
}
const struct enum_t *sstate_getenumlist(const upstype_t *ups, const char *var)
{
return state_getenumlist(ups->inforoot, var);
}
const struct cmdlist_t *sstate_getcmdlist(const upstype_t *ups)
{
return ups->cmdlist;
}
int sstate_dead(upstype_t *ups, int maxage)
{
time_t now;
double elapsed;
/* an unconnected ups is always dead */
if (ups->sock_fd < 0) {
upsdebugx(3, "sstate_dead: connection to driver socket for UPS [%s] lost", ups->name);
return 1; /* dead */
}
time(&now);
/* ignore DATAOK/DATASTALE unless the dump is done */
if ((ups->dumpdone) && (!ups->data_ok)) {
upsdebugx(3, "sstate_dead: driver for UPS [%s] says data is stale", ups->name);
return 1; /* dead */
}
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)))
sendping(ups);
if (elapsed > maxage) {
upsdebugx(3, "sstate_dead: didn't hear from driver for UPS [%s] for %g seconds (max %d)",
ups->name, elapsed, maxage);
return 1; /* dead */
}
return 0;
}
/* release all info(tree) data used by <ups> */
void sstate_infofree(upstype_t *ups)
{
state_infofree(ups->inforoot);
ups->inforoot = NULL;
}
void sstate_cmdfree(upstype_t *ups)
{
state_cmdfree(ups->cmdlist);
ups->cmdlist = NULL;
}
int sstate_sendline(upstype_t *ups, const char *buf)
{
int ret;
if ((!ups) ||(ups->sock_fd < 0)) {
return 0; /* failed */
}
ret = write(ups->sock_fd, buf, strlen(buf));
if (ret == (int)strlen(buf)) {
return 1;
}
upslog_with_errno(LOG_NOTICE, "Send to UPS [%s] failed", ups->name);
sstate_disconnect(ups);
return 0; /* failed */
}
const struct st_tree_t *sstate_getnode(const upstype_t *ups, const char *varname)
{
return state_tree_find(ups->inforoot, varname);
}

43
server/sstate.h Normal file
View file

@ -0,0 +1,43 @@
/* sstate.h - Network UPS Tools server-side state management
Copyright (C)
2003 Russell Kroll <rkroll@exploits.org>
2008 Arjen de Korte <adkorte-guest@alioth.debian.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "upstype.h"
#define SS_CONNFAIL_INT 300 /* complain about a dead driver every 5 mins */
#define SS_MAX_READ 256 /* don't let drivers tie us up in read() */
int sstate_connect(upstype_t *ups);
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);
const struct enum_t *sstate_getenumlist(const upstype_t *ups, const char *var);
const struct cmdlist_t *sstate_getcmdlist(const upstype_t *ups);
void sstate_makeinfolist(const upstype_t *ups, char *buf, size_t bufsize);
void sstate_makerwlist(const upstype_t *ups, char *buf, size_t bufsize);
void sstate_makeinstcmdlist_t(const upstype_t *ups, char *buf, size_t bufsize);
int sstate_dead(upstype_t *ups, int maxage);
void sstate_infofree(upstype_t *ups);
void sstate_cmdfree(upstype_t *ups);
int sstate_sendline(upstype_t *ups, const char *buf);
const struct st_tree_t *sstate_getnode(const upstype_t *ups, const char *varname);

41
server/stype.h Normal file
View file

@ -0,0 +1,41 @@
/* stype.h - server data definitions for upsd
Copyright (C)
2007 Arjen de Korte <arjen@de-korte.org>
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 STYPE_H_SEEN
#define STYPE_H_SEEN 1
#include <netdb.h>
#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
#endif
#ifndef NI_MAXSERV
#define NI_MAXSERV 32
#endif
typedef struct stype_s {
char *addr;
char *port;
int sock_fd;
struct stype_s *next;
} stype_t;
#endif /* STYPE_H_SEEN */

1091
server/upsd.c Normal file

File diff suppressed because it is too large Load diff

87
server/upsd.h Normal file
View file

@ -0,0 +1,87 @@
/* upsd.h - support structures and other minor details
Copyright (C) 1999 Russell Kroll <rkroll@exploits.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Much of the content from here was also useful to the
* drivers, so has been moved into include/shared-tables.h
* instead of being within the daemon specific include file
*
*/
#ifndef UPSD_H_SEEN
#define UPSD_H_SEEN
#include "attribute.h"
#include "common.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "timehead.h"
#include <sys/file.h>
#include "parseconf.h"
#include "ctype.h"
#include "upstype.h"
#define NUT_NET_ANSWER_MAX SMALLBUF
/* prototypes from upsd.c */
upstype_t *get_ups_ptr(const char *upsname);
int ups_available(const upstype_t *ups, ctype_t *client);
void listen_add(const char *addr, const char *port);
void kick_login_clients(const char *upsname);
int sendback(ctype_t *client, const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
int send_err(ctype_t *client, const char *errtype);
void server_load(void);
void server_free(void);
void check_perms(const char *fn);
/* declarations from upsd.c */
extern int maxage, maxconn;
extern char *statepath, *datapath;
extern upstype_t *firstups;
/* map commands onto signals */
#define SIGCMD_STOP SIGTERM
#define SIGCMD_RELOAD SIGHUP
/* awkward way to make a string out of a numeric constant */
#define string_const_aux(x) #x
#define string_const(x) string_const_aux(x)
#ifdef SHUT_RDWR
#define shutdown_how SHUT_RDWR
#else
#define shutdown_how 2
#endif
#endif /* UPSD_H_SEEN */

55
server/upstype.h Normal file
View file

@ -0,0 +1,55 @@
/* upstype.h - internal UPS tracking structure details
Copyright (C)
2003 Russell Kroll <rkroll@exploits.org>
2008 Arjen de Korte <adkorte-guest@alioth.debian.org>
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 UPSTYPE_H_SEEN
#define UPSTYPE_H_SEEN 1
#include "parseconf.h"
/* structure for the linked list of each UPS that we track */
typedef struct upstype_s {
char *name;
char *fn;
char *desc;
int sock_fd;
int stale;
int dumpdone;
int data_ok;
time_t last_heard;
time_t last_ping;
time_t last_connfail;
PCONF_CTX_t sock_ctx;
struct st_tree_t *inforoot;
struct cmdlist_t *cmdlist;
int numlogins;
int fsd; /* forced shutdown in effect? */
int retain;
struct upstype_s *next;
} upstype_t;
extern upstype_t *firstups;
#endif /* UPSTYPE_H_SEEN */

36
server/user-data.h Normal file
View file

@ -0,0 +1,36 @@
/* user-data.h - structures for user.c
Copyright (C) 2001 Russell Kroll <rkroll@exploits.org>
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
*/
typedef struct {
char *cmd;
void *next;
} instcmdlist_t;
typedef struct {
char *action;
void *next;
} actionlist_t;
typedef struct {
char *username;
char *password;
instcmdlist_t *firstcmd;
actionlist_t *firstaction;
void *next;
} ulist_t;

491
server/user.c Normal file
View file

@ -0,0 +1,491 @@
/* user.c - user handling functions for upsd
Copyright (C) 2001 Russell Kroll <rkroll@exploits.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "common.h"
#include "parseconf.h"
#include "user.h"
#include "user-data.h"
ulist_t *users = NULL;
static ulist_t *curr_user;
/* create a new user entry */
static void user_add(const char *un)
{
ulist_t *tmp, *last = NULL;
if (!un) {
return;
}
for (tmp = users; tmp != NULL; tmp = tmp->next) {
last = tmp;
if (!strcmp(tmp->username, un)) {
fprintf(stderr, "Ignoring duplicate user %s\n", un);
return;
}
}
tmp = xcalloc(1, sizeof(*tmp));
tmp->username = xstrdup(un);
if (last) {
last->next = tmp;
} else {
users = tmp;
}
/* remember who we're working on */
curr_user = tmp;
}
/* set password */
static void user_password(const char *pw)
{
if (!curr_user) {
upslogx(LOG_WARNING, "Ignoring password definition outside "
"user section");
return;
}
if (!pw) {
return;
}
if (curr_user->password) {
fprintf(stderr, "Ignoring duplicate password for %s\n",
curr_user->username);
return;
}
curr_user->password = xstrdup(pw);
}
/* attach allowed instcmds to user */
static void user_add_instcmd(const char *cmd)
{
instcmdlist_t *tmp, *last = NULL;
if (!curr_user) {
upslogx(LOG_WARNING, "Ignoring instcmd definition outside "
"user section");
return;
}
if (!cmd) {
return;
}
for (tmp = curr_user->firstcmd; tmp != NULL; tmp = tmp->next) {
last = tmp;
/* ignore duplicates */
if (!strcasecmp(tmp->cmd, cmd)) {
return;
}
}
tmp = xcalloc(1, sizeof(*tmp));
tmp->cmd = xstrdup(cmd);
if (last) {
last->next = tmp;
} else {
curr_user->firstcmd = tmp;
}
}
static actionlist_t *addaction(actionlist_t *base, const char *action)
{
actionlist_t *tmp, *last = NULL;
if (!action) {
return base;
}
for (tmp = base; tmp != NULL; tmp = tmp->next) {
last = tmp;
}
tmp = xcalloc(1, sizeof(*tmp));
tmp->action = xstrdup(action);
if (last) {
last->next = tmp;
return base;
}
return tmp;
}
/* attach allowed actions to user */
static void user_add_action(const char *act)
{
if (!curr_user) {
upslogx(LOG_WARNING, "Ignoring action definition outside "
"user section");
return;
}
curr_user->firstaction = addaction(curr_user->firstaction, act);
}
static void flushcmd(instcmdlist_t *ptr)
{
if (!ptr) {
return;
}
flushcmd(ptr->next);
free(ptr->cmd);
free(ptr);
}
static void flushaction(actionlist_t *ptr)
{
if (!ptr) {
return;
}
flushaction(ptr->next);
free(ptr->action);
free(ptr);
}
static void flushuser(ulist_t *ptr)
{
if (!ptr) {
return;
}
flushuser(ptr->next);
flushcmd(ptr->firstcmd);
flushaction(ptr->firstaction);
free(ptr->username);
free(ptr->password);
free(ptr);
}
/* flush all user attributes - used during reload */
void user_flush(void)
{
flushuser(users);
users = NULL;
}
static int user_matchinstcmd(ulist_t *user, const char * cmd)
{
instcmdlist_t *tmp;
for (tmp = user->firstcmd; tmp != NULL; tmp = tmp->next) {
if (!strcasecmp(tmp->cmd, cmd)) {
return 1; /* good */
}
if (!strcasecmp(tmp->cmd, "all")) {
return 1; /* good */
}
}
return 0; /* fail */
}
int user_checkinstcmd(const char *un, const char *pw, const char *cmd)
{
ulist_t *tmp;
if ((!un) || (!pw) || (!cmd)) {
return 0; /* failed */
}
for (tmp = users; tmp != NULL; tmp = tmp->next) {
/* let's be paranoid before we call strcmp */
if ((!tmp->username) || (!tmp->password)) {
continue;
}
if (strcmp(tmp->username, un)) {
continue;
}
if (strcmp(tmp->password, pw)) {
/* password mismatch */
return 0; /* fail */
}
if (!user_matchinstcmd(tmp, cmd)) {
return 0; /* fail */
}
/* passed all checks */
return 1; /* good */
}
/* username not found */
return 0; /* fail */
}
static int user_matchaction(ulist_t *user, const char *action)
{
actionlist_t *tmp;
for (tmp = user->firstaction; tmp != NULL; tmp = tmp->next) {
if (!strcasecmp(tmp->action, action)) {
return 1; /* good */
}
}
return 0; /* fail */
}
int user_checkaction(const char *un, const char *pw, const char *action)
{
ulist_t *tmp;
if ((!un) || (!pw) || (!action))
return 0; /* failed */
for (tmp = users; tmp != NULL; tmp = tmp->next) {
/* let's be paranoid before we call strcmp */
if ((!tmp->username) || (!tmp->password)) {
continue;
}
if (strcmp(tmp->username, un)) {
continue;
}
if (strcmp(tmp->password, pw)) {
upsdebugx(2, "user_checkaction: password mismatch");
return 0; /* fail */
}
if (!user_matchaction(tmp, action)) {
upsdebugx(2, "user_matchaction: failed");
return 0; /* fail */
}
/* passed all checks */
return 1; /* good */
}
/* username not found */
return 0; /* fail */
}
/* handle "upsmon master" and "upsmon slave" for nicer configurations */
static void set_upsmon_type(char *type)
{
/* master: login, master, fsd */
if (!strcasecmp(type, "master")) {
user_add_action("login");
user_add_action("master");
user_add_action("fsd");
return;
}
/* slave: just login */
if (!strcasecmp(type, "slave")) {
user_add_action("login");
return;
}
upslogx(LOG_WARNING, "Unknown upsmon type %s", type);
}
/* actually do something with the variable + value pairs */
static void parse_var(char *var, char *val)
{
if (!strcasecmp(var, "password")) {
user_password(val);
return;
}
if (!strcasecmp(var, "instcmds")) {
user_add_instcmd(val);
return;
}
if (!strcasecmp(var, "actions")) {
user_add_action(val);
return;
}
if (!strcasecmp(var, "allowfrom")) {
upslogx(LOG_WARNING, "allowfrom in upsd.users is no longer used");
return;
}
/* someone did 'upsmon = type' - allow it anyway */
if (!strcasecmp(var, "upsmon")) {
set_upsmon_type(val);
return;
}
upslogx(LOG_NOTICE, "Unrecognized user setting %s", var);
}
/* parse first var+val pair, then flip through remaining vals */
static void parse_rest(char *var, char *fval, char **arg, int next, int left)
{
int i;
/* no globals supported yet, so there's no sense in continuing */
if (!curr_user) {
return;
}
parse_var(var, fval);
if (left == 0) {
return;
}
for (i = 0; i < left; i++) {
parse_var(var, arg[next + i]);
}
}
static void user_parse_arg(int numargs, char **arg)
{
char *ep;
if ((numargs == 0) || (!arg)) {
return;
}
/* ignore old file format */
if (!strcasecmp(arg[0], "user")) {
return;
}
/* handle 'foo=bar' (compressed form) */
ep = strchr(arg[0], '=');
if (ep) {
*ep = '\0';
/* parse first var/val, plus subsequent values (if any) */
/* 0 1 2 ... */
/* foo=bar <rest1> <rest2> ... */
parse_rest(arg[0], ep+1, arg, 1, numargs - 1);
return;
}
/* look for section headers - [username] */
if ((arg[0][0] == '[') && (arg[0][strlen(arg[0])-1] == ']')) {
arg[0][strlen(arg[0])-1] = '\0';
user_add(&arg[0][1]);
return;
}
if (numargs < 2) {
return;
}
if (!strcasecmp(arg[0], "upsmon")) {
set_upsmon_type(arg[1]);
}
/* everything after here needs arg[1] and arg[2] */
if (numargs < 3) {
return;
}
/* handle 'foo = bar' (split form) */
if (!strcmp(arg[1], "=")) {
/* 0 1 2 3 4 ... */
/* foo = bar <rest1> <rest2> ... */
/* parse first var/val, plus subsequent values (if any) */
parse_rest(arg[0], arg[2], arg, 3, numargs - 3);
return;
}
/* ... unhandled ... */
}
/* called for fatal errors in parseconf like malloc failures */
static void upsd_user_err(const char *errmsg)
{
upslogx(LOG_ERR, "Fatal error in parseconf(upsd.users): %s", errmsg);
}
void user_load(void)
{
char fn[SMALLBUF];
PCONF_CTX_t ctx;
curr_user = NULL;
snprintf(fn, sizeof(fn), "%s/upsd.users", confpath());
check_perms(fn);
pconf_init(&ctx, upsd_user_err);
if (!pconf_file_begin(&ctx, fn)) {
pconf_finish(&ctx);
upslogx(LOG_WARNING, "%s", ctx.errmsg);
return;
}
while (pconf_file_next(&ctx)) {
if (pconf_parse_error(&ctx)) {
upslogx(LOG_ERR, "Parse error: %s:%d: %s",
fn, ctx.linenum, ctx.errmsg);
continue;
}
user_parse_arg(ctx.numargs, ctx.arglist);
}
pconf_finish(&ctx);
}

28
server/user.h Normal file
View file

@ -0,0 +1,28 @@
/* user.c - supporting elements of user handling functions for upsd
Copyright (C) 2001 Russell Kroll <rkroll@exploits.org>
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
*/
void user_load(void);
int user_checkinstcmd(const char *un, const char *pw, const char *cmd);
int user_checkaction(const char *un, const char *pw, const char *action);
void user_flush(void);
/* cheat - we don't want the full upsd.h included here */
void check_perms(const char *fn);