Imported Upstream version 2.7.1

This commit is contained in:
Laurent Bigonville 2013-11-24 16:00:12 +01:00
parent a1fa151fc7
commit 0121794af9
451 changed files with 41339 additions and 10887 deletions

View file

@ -20,9 +20,9 @@ endif
bin_PROGRAMS = upsc upslog upsrw upscmd
dist_bin_SCRIPTS = upssched-cmd
sbin_PROGRAMS = upsmon upssched
lib_LTLIBRARIES = libupsclient.la
lib_LTLIBRARIES = libupsclient.la libnutclient.la
if WITH_DEV
include_HEADERS = upsclient.h ../include/parseconf.h
include_HEADERS = upsclient.h ../include/parseconf.h nutclient.h
endif
if WITH_CGI
cgiexec_PROGRAMS = upsstats.cgi upsimage.cgi upsset.cgi
@ -50,4 +50,10 @@ libupsclient_la_LIBADD = ../common/libparseconf.la
if WITH_SSL
libupsclient_la_LIBADD += $(LIBSSL_LIBS)
endif
libupsclient_la_LDFLAGS = -version-info 2:0:1
# libupsclient version information
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
libupsclient_la_LDFLAGS = -version-info 3:1:0
libnutclient_la_SOURCES = nutclient.h nutclient.cpp

View file

@ -1,9 +1,9 @@
# Makefile.in generated by automake 1.11.1 from Makefile.am.
# Makefile.in generated by automake 1.11.6 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.
# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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.
@ -21,6 +21,23 @@
VPATH = @srcdir@
am__make_dryrun = \
{ \
am__dry=no; \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
| grep '^AM OK$$' >/dev/null || am__dry=yes;; \
*) \
for am__flg in $$MAKEFLAGS; do \
case $$am__flg in \
*=*|--*) ;; \
*n*) am__dry=yes; break;; \
esac; \
done;; \
esac; \
test $$am__dry = yes; \
}
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@ -66,8 +83,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
$(top_srcdir)/m4/nut_check_libltdl.m4 \
$(top_srcdir)/m4/nut_check_libneon.m4 \
$(top_srcdir)/m4/nut_check_libnetsnmp.m4 \
$(top_srcdir)/m4/nut_check_libnss.m4 \
$(top_srcdir)/m4/nut_check_libopenssl.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 \
@ -102,10 +120,19 @@ am__nobase_list = $(am__nobase_strip_setup); \
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
test -z "$$files" \
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
"$(DESTDIR)$(cgiexecdir)" "$(DESTDIR)$(sbindir)" \
"$(DESTDIR)$(bindir)" "$(DESTDIR)$(includedir)"
LTLIBRARIES = $(lib_LTLIBRARIES)
libnutclient_la_LIBADD =
am_libnutclient_la_OBJECTS = nutclient.lo
libnutclient_la_OBJECTS = $(am_libnutclient_la_OBJECTS)
am__DEPENDENCIES_1 =
@WITH_SSL_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
libupsclient_la_DEPENDENCIES = ../common/libparseconf.la \
@ -175,15 +202,32 @@ CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libupsclient_la_SOURCES) $(upsc_SOURCES) $(upscmd_SOURCES) \
$(upsimage_cgi_SOURCES) $(upslog_SOURCES) $(upsmon_SOURCES) \
$(upsrw_SOURCES) $(upssched_SOURCES) $(upsset_cgi_SOURCES) \
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX)
CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libnutclient_la_SOURCES) $(libupsclient_la_SOURCES) \
$(upsc_SOURCES) $(upscmd_SOURCES) $(upsimage_cgi_SOURCES) \
$(upslog_SOURCES) $(upsmon_SOURCES) $(upsrw_SOURCES) \
$(upssched_SOURCES) $(upsset_cgi_SOURCES) \
$(upsstats_cgi_SOURCES)
DIST_SOURCES = $(libupsclient_la_SOURCES) $(upsc_SOURCES) \
$(upscmd_SOURCES) $(upsimage_cgi_SOURCES) $(upslog_SOURCES) \
$(upsmon_SOURCES) $(upsrw_SOURCES) $(upssched_SOURCES) \
$(upsset_cgi_SOURCES) $(upsstats_cgi_SOURCES)
am__include_HEADERS_DIST = upsclient.h ../include/parseconf.h
DIST_SOURCES = $(libnutclient_la_SOURCES) $(libupsclient_la_SOURCES) \
$(upsc_SOURCES) $(upscmd_SOURCES) $(upsimage_cgi_SOURCES) \
$(upslog_SOURCES) $(upsmon_SOURCES) $(upsrw_SOURCES) \
$(upssched_SOURCES) $(upsset_cgi_SOURCES) \
$(upsstats_cgi_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__include_HEADERS_DIST = upsclient.h ../include/parseconf.h \
nutclient.h
HEADERS = $(include_HEADERS)
ETAGS = etags
CTAGS = ctags
@ -193,6 +237,7 @@ ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
ASCIIDOC = @ASCIIDOC@
ASPELL = @ASPELL@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
@ -219,6 +264,7 @@ DOC_BUILD_LIST = @DOC_BUILD_LIST@
DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@
DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@
DRIVER_MAN_LIST = @DRIVER_MAN_LIST@
DRVPATH = @DRVPATH@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
@ -381,8 +427,8 @@ LDADD = ../common/libcommon.la libupsclient.la $(NETLIBS) \
# but only add them if we really use the target.
AM_CFLAGS = -I$(top_srcdir)/include $(am__append_2) $(am__append_3)
dist_bin_SCRIPTS = upssched-cmd
lib_LTLIBRARIES = libupsclient.la
@WITH_DEV_TRUE@include_HEADERS = upsclient.h ../include/parseconf.h
lib_LTLIBRARIES = libupsclient.la libnutclient.la
@WITH_DEV_TRUE@include_HEADERS = upsclient.h ../include/parseconf.h nutclient.h
upsc_SOURCES = upsc.c upsclient.h
upscmd_SOURCES = upscmd.c upsclient.h
upsrw_SOURCES = upsrw.c upsclient.h
@ -400,11 +446,15 @@ upsstats_cgi_SOURCES = upsstats.c upsclient.h status.h upsstats.h \
# not LDADD.
libupsclient_la_SOURCES = upsclient.c upsclient.h
libupsclient_la_LIBADD = ../common/libparseconf.la $(am__append_4)
libupsclient_la_LDFLAGS = -version-info 2:0:1
# libupsclient version information
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
libupsclient_la_LDFLAGS = -version-info 3:1:0
libnutclient_la_SOURCES = nutclient.h nutclient.cpp
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
.SUFFIXES: .c .cpp .lo .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
@ -437,7 +487,6 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__aclocal_m4_deps):
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
list2=; for p in $$list; do \
if test -f $$p; then \
@ -445,6 +494,8 @@ install-libLTLIBRARIES: $(lib_LTLIBRARIES)
else :; fi; \
done; \
test -z "$$list2" || { \
echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
$(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
}
@ -466,12 +517,17 @@ clean-libLTLIBRARIES:
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
libupsclient.la: $(libupsclient_la_OBJECTS) $(libupsclient_la_DEPENDENCIES)
libnutclient.la: $(libnutclient_la_OBJECTS) $(libnutclient_la_DEPENDENCIES) $(EXTRA_libnutclient_la_DEPENDENCIES)
$(CXXLINK) -rpath $(libdir) $(libnutclient_la_OBJECTS) $(libnutclient_la_LIBADD) $(LIBS)
libupsclient.la: $(libupsclient_la_OBJECTS) $(libupsclient_la_DEPENDENCIES) $(EXTRA_libupsclient_la_DEPENDENCIES)
$(libupsclient_la_LINK) -rpath $(libdir) $(libupsclient_la_OBJECTS) $(libupsclient_la_LIBADD) $(LIBS)
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
$(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p || test -f $$p1; \
@ -513,8 +569,11 @@ clean-binPROGRAMS:
rm -f $$list
install-cgiexecPROGRAMS: $(cgiexec_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(cgiexecdir)" || $(MKDIR_P) "$(DESTDIR)$(cgiexecdir)"
@list='$(cgiexec_PROGRAMS)'; test -n "$(cgiexecdir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(cgiexecdir)'"; \
$(MKDIR_P) "$(DESTDIR)$(cgiexecdir)" || exit 1; \
fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p || test -f $$p1; \
@ -556,8 +615,11 @@ clean-cgiexecPROGRAMS:
rm -f $$list
install-sbinPROGRAMS: $(sbin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
$(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p || test -f $$p1; \
@ -597,37 +659,40 @@ clean-sbinPROGRAMS:
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
upsc$(EXEEXT): $(upsc_OBJECTS) $(upsc_DEPENDENCIES)
upsc$(EXEEXT): $(upsc_OBJECTS) $(upsc_DEPENDENCIES) $(EXTRA_upsc_DEPENDENCIES)
@rm -f upsc$(EXEEXT)
$(LINK) $(upsc_OBJECTS) $(upsc_LDADD) $(LIBS)
upscmd$(EXEEXT): $(upscmd_OBJECTS) $(upscmd_DEPENDENCIES)
upscmd$(EXEEXT): $(upscmd_OBJECTS) $(upscmd_DEPENDENCIES) $(EXTRA_upscmd_DEPENDENCIES)
@rm -f upscmd$(EXEEXT)
$(LINK) $(upscmd_OBJECTS) $(upscmd_LDADD) $(LIBS)
upsimage.cgi$(EXEEXT): $(upsimage_cgi_OBJECTS) $(upsimage_cgi_DEPENDENCIES)
upsimage.cgi$(EXEEXT): $(upsimage_cgi_OBJECTS) $(upsimage_cgi_DEPENDENCIES) $(EXTRA_upsimage_cgi_DEPENDENCIES)
@rm -f upsimage.cgi$(EXEEXT)
$(LINK) $(upsimage_cgi_OBJECTS) $(upsimage_cgi_LDADD) $(LIBS)
upslog$(EXEEXT): $(upslog_OBJECTS) $(upslog_DEPENDENCIES)
upslog$(EXEEXT): $(upslog_OBJECTS) $(upslog_DEPENDENCIES) $(EXTRA_upslog_DEPENDENCIES)
@rm -f upslog$(EXEEXT)
$(LINK) $(upslog_OBJECTS) $(upslog_LDADD) $(LIBS)
upsmon$(EXEEXT): $(upsmon_OBJECTS) $(upsmon_DEPENDENCIES)
upsmon$(EXEEXT): $(upsmon_OBJECTS) $(upsmon_DEPENDENCIES) $(EXTRA_upsmon_DEPENDENCIES)
@rm -f upsmon$(EXEEXT)
$(LINK) $(upsmon_OBJECTS) $(upsmon_LDADD) $(LIBS)
upsrw$(EXEEXT): $(upsrw_OBJECTS) $(upsrw_DEPENDENCIES)
upsrw$(EXEEXT): $(upsrw_OBJECTS) $(upsrw_DEPENDENCIES) $(EXTRA_upsrw_DEPENDENCIES)
@rm -f upsrw$(EXEEXT)
$(LINK) $(upsrw_OBJECTS) $(upsrw_LDADD) $(LIBS)
upssched$(EXEEXT): $(upssched_OBJECTS) $(upssched_DEPENDENCIES)
upssched$(EXEEXT): $(upssched_OBJECTS) $(upssched_DEPENDENCIES) $(EXTRA_upssched_DEPENDENCIES)
@rm -f upssched$(EXEEXT)
$(LINK) $(upssched_OBJECTS) $(upssched_LDADD) $(LIBS)
upsset.cgi$(EXEEXT): $(upsset_cgi_OBJECTS) $(upsset_cgi_DEPENDENCIES)
upsset.cgi$(EXEEXT): $(upsset_cgi_OBJECTS) $(upsset_cgi_DEPENDENCIES) $(EXTRA_upsset_cgi_DEPENDENCIES)
@rm -f upsset.cgi$(EXEEXT)
$(LINK) $(upsset_cgi_OBJECTS) $(upsset_cgi_LDADD) $(LIBS)
upsstats.cgi$(EXEEXT): $(upsstats_cgi_OBJECTS) $(upsstats_cgi_DEPENDENCIES)
upsstats.cgi$(EXEEXT): $(upsstats_cgi_OBJECTS) $(upsstats_cgi_DEPENDENCIES) $(EXTRA_upsstats_cgi_DEPENDENCIES)
@rm -f upsstats.cgi$(EXEEXT)
$(LINK) $(upsstats_cgi_OBJECTS) $(upsstats_cgi_LDADD) $(LIBS)
install-dist_binSCRIPTS: $(dist_bin_SCRIPTS)
@$(NORMAL_INSTALL)
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
$(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
@ -655,9 +720,7 @@ uninstall-dist_binSCRIPTS:
@list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 's,.*/,,;$(transform)'`; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(bindir)" && rm -f $$files
dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@ -666,6 +729,7 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cgilib.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nutclient.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsclient.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upscmd.Po@am__quote@
@ -698,6 +762,27 @@ distclean-compile:
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
.cpp.o:
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
.cpp.obj:
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.cpp.lo:
@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
@ -705,8 +790,11 @@ clean-libtool:
-rm -rf .libs _libs
install-includeHEADERS: $(include_HEADERS)
@$(NORMAL_INSTALL)
test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
$(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
@ -720,9 +808,7 @@ uninstall-includeHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(includedir)" && rm -f $$files
dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
@ -825,10 +911,15 @@ install-am: all-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
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:

View file

@ -17,6 +17,12 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef __cplusplus
/* *INDENT-OFF* */
extern "C" {
/* *INDENT-ON* */
#endif
/* other programs that link to this should provide parsearg() ... */
void parsearg(char *var, char *value);
@ -29,3 +35,9 @@ void extractpostargs(void);
/* see if a host is allowed per the hosts.conf */
int checkhost(const char *host, char **desc);
#ifdef __cplusplus
/* *INDENT-OFF* */
}
/* *INDENT-ON* */
#endif

1726
clients/nutclient.cpp Normal file

File diff suppressed because it is too large Load diff

963
clients/nutclient.h Normal file
View file

@ -0,0 +1,963 @@
/* nutclient.h - definitions for nutclient C/C++ library
Copyright (C) 2012 Emilien Kia <emilien.kia@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef NUTCLIENT_HPP_SEEN
#define NUTCLIENT_HPP_SEEN
/* Begin of C++ nutclient library declaration */
#ifdef __cplusplus
#include <string>
#include <vector>
#include <map>
#include <set>
#include <exception>
namespace nut
{
namespace internal
{
class Socket;
} /* namespace internal */
class Client;
class TcpClient;
class Device;
class Variable;
class Command;
/**
* Basic nut exception.
*/
class NutException : public std::exception
{
public:
NutException(const std::string& msg):_msg(msg){}
virtual ~NutException() throw() {}
virtual const char * what() const throw() {return this->_msg.c_str();}
virtual std::string str() const throw() {return this->_msg;}
private:
std::string _msg;
};
/**
* System error.
*/
class SystemException : public NutException
{
public:
SystemException();
virtual ~SystemException() throw() {}
private:
static std::string err();
};
/**
* IO oriented nut exception.
*/
class IOException : public NutException
{
public:
IOException(const std::string& msg):NutException(msg){}
virtual ~IOException() throw() {}
};
/**
* IO oriented nut exception specialized for unknown host
*/
class UnknownHostException : public IOException
{
public:
UnknownHostException():IOException("Unknown host"){}
virtual ~UnknownHostException() throw() {}
};
/**
* IO oriented nut exception when client is not connected
*/
class NotConnectedException : public IOException
{
public:
NotConnectedException():IOException("Not connected"){}
virtual ~NotConnectedException() throw() {}
};
/**
* IO oriented nut exception when there is no response.
*/
class TimeoutException : public IOException
{
public:
TimeoutException():IOException("Timeout"){}
virtual ~TimeoutException() throw() {}
};
/**
* A nut client is the starting point to dialog to NUTD.
* It can connect to an NUTD then retrieve its device list.
* Use a specific client class to connect to a NUTD.
*/
class Client
{
friend class Device;
friend class Variable;
friend class Command;
public:
~Client();
/**
* Intend to authenticate to a NUTD server.
* Set the username and password associated to the connection.
* \param user User name.
* \param passwd Password.
* \todo Is his method is global to all connection protocol or is it specific to TCP ?
* \note Actually, authentication fails only if already set, not if bad values are sent.
*/
virtual void authenticate(const std::string& user, const std::string& passwd)throw(NutException)=0;
/**
* Disconnect from the NUTD server.
* \todo Is his method is global to all connection protocol or is it specific to TCP ?
*/
virtual void logout()throw(NutException)=0;
/**
* Device manipulations.
* \see nut::Device
* \{
*/
/**
* Retrieve a device from its name.
* If the device does not exist, a bad (not ok) device is returned.
* \param name Name of the device.
* \return The device.
*/
virtual Device getDevice(const std::string& name)throw(NutException);
/**
* Retrieve the list of all devices supported by UPSD server.
* \return The set of supported devices.
*/
virtual std::set<Device> getDevices()throw(NutException);
/**
* Test if a device is supported by the NUTD server.
* \param dev Device name.
* \return true if supported, false otherwise.
*/
virtual bool hasDevice(const std::string& dev)throw(NutException);
/**
* Retrieve names of devices supported by NUTD server.
* \return The set of names of supported devices.
*/
virtual std::set<std::string> getDeviceNames()throw(NutException)=0;
/**
* Retrieve the description of a device.
* \param name Device name.
* \return Device description.
*/
virtual std::string getDeviceDescription(const std::string& name)throw(NutException)=0;
/** \} */
/**
* Variable manipulations.
* \see nut::Variable
* \{
*/
/**
* Retrieve names of all variables supported by a device.
* \param dev Device name
* \return Variable names
*/
virtual std::set<std::string> getDeviceVariableNames(const std::string& dev)throw(NutException)=0;
/**
* Retrieve names of read/write variables supported by a device.
* \param dev Device name
* \return RW variable names
*/
virtual std::set<std::string> getDeviceRWVariableNames(const std::string& dev)throw(NutException)=0;
/**
* Test if a variable is supported by a device.
* \param dev Device name
* \param name Variable name
* \return true if the variable is supported.
*/
virtual bool hasDeviceVariable(const std::string& dev, const std::string& name)throw(NutException);
/**
* Retrieve the description of a variable.
* \param dev Device name
* \param name Variable name
* \return Variable description if provided.
*/
virtual std::string getDeviceVariableDescription(const std::string& dev, const std::string& name)throw(NutException)=0;
/**
* Retrieve values of a variable.
* \param dev Device name
* \param name Variable name
* \return Variable values (usually one) if available.
*/
virtual std::vector<std::string> getDeviceVariableValue(const std::string& dev, const std::string& name)throw(NutException)=0;
/**
* Retrieve values of all variables of a device.
* \param dev Device name
* \return Variable values indexed by variable names.
*/
virtual std::map<std::string,std::vector<std::string> > getDeviceVariableValues(const std::string& dev)throw(NutException);
/**
* Intend to set the value of a variable.
* \param dev Device name
* \param name Variable name
* \param value Variable value
*/
virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value)throw(NutException)=0;
/**
* Intend to set the value of a variable.
* \param dev Device name
* \param name Variable name
* \param value Variable value
*/
virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::vector<std::string>& values)throw(NutException)=0;
/** \} */
/**
* Instant command manipulations.
* \see nut::Command
* \{
*/
/**
* Retrieve names of all commands supported by a device.
* \param dev Device name
* \return Command names
*/
virtual std::set<std::string> getDeviceCommandNames(const std::string& dev)throw(NutException)=0;
/**
* Test if a command is supported by a device.
* \param dev Device name
* \param name Command name
* \return true if the command is supported.
*/
virtual bool hasDeviceCommand(const std::string& dev, const std::string& name)throw(NutException);
/**
* Retrieve the description of a command.
* \param dev Device name
* \param name Command name
* \return Command description if provided.
*/
virtual std::string getDeviceCommandDescription(const std::string& dev, const std::string& name)throw(NutException)=0;
/**
* Intend to execute a command.
* \param dev Device name
* \param name Command name
*/
virtual void executeDeviceCommand(const std::string& dev, const std::string& name)throw(NutException)=0;
/** \} */
/**
* Device specific commands.
* \{
*/
/**
* Log the current user (if authenticated) for a device.
* \param dev Device name.
*/
virtual void deviceLogin(const std::string& dev)throw(NutException)=0;
/**
* Retrieve the number of user longged in the specified device.
* \param dev Device name.
* \return Number of logged-in users.
*/
virtual int deviceGetNumLogins(const std::string& dev)throw(NutException)=0;
virtual void deviceMaster(const std::string& dev)throw(NutException)=0;
virtual void deviceForcedShutdown(const std::string& dev)throw(NutException)=0;
protected:
Client();
};
/**
* TCP NUTD client.
* It connect to NUTD with a TCP socket.
*/
class TcpClient : public Client
{
public:
/**
* Construct a nut TcpClient object.
* You must call one of TcpClient::connect() after.
*/
TcpClient();
/**
* Construct a nut TcpClient object then connect it to the specified server.
* \param host Server host name.
* \param port Server port.
*/
TcpClient(const std::string& host, int port = 3493)throw(nut::IOException);
~TcpClient();
/**
* Connect it to the specified server.
* \param host Server host name.
* \param port Server port.
*/
void connect(const std::string& host, int port = 3493)throw(nut::IOException);
/**
* Connect to the server.
* Host name and ports must have already set (usefull for reconnection).
*/
void connect()throw(nut::IOException);
/**
* Test if the connection is active.
* \return tru if the connection is active.
*/
bool isConnected()const;
/**
* Force the deconnection.
*/
void disconnect();
/**
* Set the timeout in seconds.
* \param timeout Timeout n seconds, negative to block operations.
*/
void setTimeout(long timeout);
/**
* Retrieve the timeout.
* \returns Current timeout in seconds.
*/
long getTimeout()const;
/**
* Retriueve the host name of the server the client is connected to.
* \return Server host name
*/
std::string getHost()const;
/**
* Retriueve the port of host of the server the client is connected to.
* \return Server port
*/
int getPort()const;
virtual void authenticate(const std::string& user, const std::string& passwd)throw(NutException);
virtual void logout()throw(NutException);
virtual Device getDevice(const std::string& name)throw(NutException);
virtual std::set<std::string> getDeviceNames()throw(NutException);
virtual std::string getDeviceDescription(const std::string& name)throw(NutException);
virtual std::set<std::string> getDeviceVariableNames(const std::string& dev)throw(NutException);
virtual std::set<std::string> getDeviceRWVariableNames(const std::string& dev)throw(NutException);
virtual std::string getDeviceVariableDescription(const std::string& dev, const std::string& name)throw(NutException);
virtual std::vector<std::string> getDeviceVariableValue(const std::string& dev, const std::string& name)throw(NutException);
virtual std::map<std::string,std::vector<std::string> > getDeviceVariableValues(const std::string& dev)throw(NutException);
virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value)throw(NutException);
virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::vector<std::string>& values)throw(NutException);
virtual std::set<std::string> getDeviceCommandNames(const std::string& dev)throw(NutException);
virtual std::string getDeviceCommandDescription(const std::string& dev, const std::string& name)throw(NutException);
virtual void executeDeviceCommand(const std::string& dev, const std::string& name)throw(NutException);
virtual void deviceLogin(const std::string& dev)throw(NutException);
virtual void deviceMaster(const std::string& dev)throw(NutException);
virtual void deviceForcedShutdown(const std::string& dev)throw(NutException);
virtual int deviceGetNumLogins(const std::string& dev)throw(NutException);
protected:
std::string sendQuery(const std::string& req)throw(nut::IOException);
static void detectError(const std::string& req)throw(nut::NutException);
std::vector<std::string> get(const std::string& subcmd, const std::string& params = "")
throw(nut::NutException);
std::vector<std::vector<std::string> > list(const std::string& subcmd, const std::string& params = "")
throw(nut::NutException);
static std::vector<std::string> explode(const std::string& str, size_t begin=0);
static std::string escape(const std::string& str);
private:
std::string _host;
int _port;
long _timeout;
internal::Socket* _socket;
};
/**
* Device attached to a client.
* Device is a lightweight class which can be copied easily.
*/
class Device
{
friend class Client;
friend class TcpClient;
public:
~Device();
Device(const Device& dev);
/**
* Retrieve the name of the device.
* The name is the unique id under which NUTD known the device.
*/
std::string getName()const;
/**
* Retrieve the client to which the device is attached.
*/
const Client* getClient()const;
/**
* Retrieve the client to which the device is attached.
*/
Client* getClient();
/**
* Test if the device is valid (has a name and is attached to a client).
*/
bool isOk()const;
/**
* Test if the device is valid (has a name and is attached to a client).
* @see Device::isOk()
*/
operator bool()const;
/**
* Test if the device is not valid (has no name or is not attached to any client).
* @see Device::isOk()
*/
bool operator!()const;
/**
* Test if the two devices are sames (same name ad same client attached to).
*/
bool operator==(const Device& dev)const;
/**
* Comparison operator.
*/
bool operator<(const Device& dev)const;
/**
* Retrieve the description of the devce if specified.
*/
std::string getDescription()throw(NutException);
/**
* Intend to retrieve the value of a variable of the device.
* \param name Name of the variable to get.
* \return Value of the variable, if available.
*/
std::vector<std::string> getVariableValue(const std::string& name)throw(NutException);
/**
* Intend to retrieve values of all variables of the devices.
* \return Map of all variables values indexed by their names.
*/
std::map<std::string,std::vector<std::string> > getVariableValues()throw(NutException);
/**
* Retrieve all variables names supported by the device.
* \return Set of available variable names.
*/
std::set<std::string> getVariableNames()throw(NutException);
/**
* Retrieve all Read/Write variables names supported by the device.
* \return Set of available Read/Write variable names.
*/
std::set<std::string> getRWVariableNames()throw(NutException);
/**
* Intend to set the value of a variable of the device.
* \param name Variable name.
* \param value New variable value.
*/
void setVariable(const std::string& name, const std::string& value)throw(NutException);
/**
* Intend to set values of a variable of the device.
* \param name Variable name.
* \param value New variable values.
*/
void setVariable(const std::string& name, const std::vector<std::string>& values)throw(NutException);
/**
* Retrieve a Variable object representing the specified variable.
* \param name Variable name.
* \return Variable object.
*/
Variable getVariable(const std::string& name)throw(NutException);
/**
* Retrieve Variable objects representing all variables available for the device.
* \return Set of Variable objects.
*/
std::set<Variable> getVariables()throw(NutException);
/**
* Retrieve Variable objects representing all Read/Write variables available for the device.
* \return Set of Variable objects.
*/
std::set<Variable> getRWVariables()throw(NutException);
/**
* Retrieve names of all commands supported by the device.
* \return Set of available command names.
*/
std::set<std::string> getCommandNames()throw(NutException);
/**
* Retrieve objects for all commands supported by the device.
* \return Set of available Command objects.
*/
std::set<Command> getCommands()throw(NutException);
/**
* Retrieve an object representing a command of the device.
* \param name Command name.
* \return Command object.
*/
Command getCommand(const std::string& name)throw(NutException);
/**
* Intend to execute a command on the device.
* \param name Command name.
*/
void executeCommand(const std::string& name)throw(NutException);
/**
* Login current client's user for the device.
*/
void login()throw(NutException);
void master()throw(NutException);
void forcedShutdown()throw(NutException);
/**
* Retrieve the number of logged user for the device.
* \return Number of users.
*/
int getNumLogins()throw(NutException);
protected:
Device(Client* client, const std::string& name);
private:
Client* _client;
std::string _name;
};
/**
* Variable attached to a device.
* Variable is a lightweight class which can be copied easily.
*/
class Variable
{
friend class Device;
friend class TcpClient;
public:
~Variable();
Variable(const Variable& var);
/**
* Retrieve variable name.
*/
std::string getName()const;
/**
* Retrieve the device to which the variable is attached to.
*/
const Device* getDevice()const;
/**
* Retrieve the device to which the variable is attached to.
*/
Device* getDevice();
/**
* Test if the variable is valid (has a name and is attached to a device).
*/
bool isOk()const;
/**
* Test if the variable is valid (has a name and is attached to a device).
* @see Variable::isOk()
*/
operator bool()const;
/**
* Test if the variable is not valid (has no name or is not attached to any device).
* @see Variable::isOk()
*/
bool operator!()const;
/**
* Test if the two variables are sames (same name ad same device attached to).
*/
bool operator==(const Variable& var)const;
/**
* Less-than operator (based on variable name) to allow variable sorting.
*/
bool operator<(const Variable& var)const;
/**
* Intend to retrieve variable value.
* \return Value of the variable.
*/
std::vector<std::string> getValue()throw(NutException);
/**
* Intend to retireve variable description.
* \return Variable description if provided.
*/
std::string getDescription()throw(NutException);
/**
* Intend to set a value to the variable.
* \param value New variable value.
*/
void setValue(const std::string& value)throw(NutException);
/**
* Intend to set (multiple) values to the variable.
* \param value New variable values.
*/
void setValues(const std::vector<std::string>& values)throw(NutException);
protected:
Variable(Device* dev, const std::string& name);
private:
Device* _device;
std::string _name;
};
/**
* Command attached to a device.
* Command is a lightweight class which can be copied easily.
*/
class Command
{
friend class Device;
friend class TcpClient;
public:
~Command();
Command(const Command& cmd);
/**
* Retrieve command name.
*/
std::string getName()const;
/**
* Retrieve the device to which the command is attached to.
*/
const Device* getDevice()const;
/**
* Retrieve the device to which the command is attached to.
*/
Device* getDevice();
/**
* Test if the command is valid (has a name and is attached to a device).
*/
bool isOk()const;
/**
* Test if the command is valid (has a name and is attached to a device).
* @see Command::isOk()
*/
operator bool()const;
/**
* Test if the command is not valid (has no name or is not attached to any device).
* @see Command::isOk()
*/
bool operator!()const;
/**
* Test if the two commands are sames (same name ad same device attached to).
*/
bool operator==(const Command& var)const;
/**
* Less-than operator (based on command name) to allow comand sorting.
*/
bool operator<(const Command& var)const;
/**
* Intend to retireve command description.
* \return Command description if provided.
*/
std::string getDescription()throw(NutException);
/**
* Intend to retrieve command description.
* \return Command description if provided.
*/
void execute()throw(NutException);
protected:
Command(Device* dev, const std::string& name);
private:
Device* _device;
std::string _name;
};
} /* namespace nut */
#endif /* __cplusplus */
/* End of C++ nutclient library declaration */
/* Begin of C nutclient library declaration */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* Array of string manipulation functions.
* \{
*/
/** Array of string.*/
typedef char** strarr;
/**
* Alloc an array of string.
*/
strarr strarr_alloc(unsigned short count);
/**
* Free an array of string.
*/
void strarr_free(strarr arr);
/**
* Nut general client types and functions.
* \{
*/
/** Hidden structure representing a connection to NUTD. */
typedef void* NUTCLIENT_t;
/**
* Destroy a client.
* \param client Nut client handle.
*/
void nutclient_destroy(NUTCLIENT_t client);
/**
* Authenticate into the server.
* \param client Nut client handle.
* \param login User name.
* \param passwd Password.
*/
void nutclient_authenticate(NUTCLIENT_t client, const char* login, const char* passwd);
/**
* Log out from server.
* \param client Nut client handle.
*/
void nutclient_logout(NUTCLIENT_t client);
/**
* Register current user on the device.
* \param client Nut client handle.
* \param dev Device name to test.
*/
void nutclient_device_login(NUTCLIENT_t client, const char* dev);
/**
* Retrieve the number of users registered on a device.
* \param client Nut client handle.
* \param dev Device name to test.
*/
int nutclient_get_device_num_logins(NUTCLIENT_t client, const char* dev);
/**
* Set current user as master user of the device.
* \param client Nut client handle.
* \param dev Device name to test.
*/
void nutclient_device_master(NUTCLIENT_t client, const char* dev);
/**
* Set the FSD flag for the device.
* \param client Nut client handle.
* \param dev Device name to test.
*/
void nutclient_device_forced_shutdown(NUTCLIENT_t client, const char* dev);
/**
* Retrieve the list of devices of a client.
* \param client Nut client handle.
* \return Array of string containing device names. Must be freed with strarr_free(strarr).
*/
strarr nutclient_get_devices(NUTCLIENT_t client);
/**
* Test if a device is supported by the client.
* \param client Nut client handle.
* \param dev Device name to test.
* \return 1 if supported, 0 otherwise.
*/
int nutclient_has_device(NUTCLIENT_t client, const char* dev);
/**
* Intend to retrieve device description.
* \param client Nut client handle.
* \param dev Device name to test.
* \return Description of device. Must be freed after use.
*/
char* nutclient_get_device_description(NUTCLIENT_t client, const char* dev);
/**
* Intend to retrieve device variable names.
* \param client Nut client handle.
* \param dev Device name.
* \return Array of string containing variable names. Must be freed with strarr_free(strarr).
*/
strarr nutclient_get_device_variables(NUTCLIENT_t client, const char* dev);
/**
* Intend to retrieve device read/write variable names.
* \param client Nut client handle.
* \param dev Device name.
* \return Array of string containing read/write variable names. Must be freed with strarr_free(strarr).
*/
strarr nutclient_get_device_rw_variables(NUTCLIENT_t client, const char* dev);
/**
* Test if a variable is supported by the device and the client.
* \param client Nut client handle.
* \param dev Device name.
* \param var Variable name.
* \return 1 if supported, 0 otherwise.
*/
int nutclient_has_device_variable(NUTCLIENT_t client, const char* dev, const char* var);
/**
* Intend to retrieve device variable description.
* \param client Nut client handle.
* \param dev Device name.
* \param var Variable name.
* \return Description of device variable. Must be freed after use.
*/
char* nutclient_get_device_variable_description(NUTCLIENT_t client, const char* dev, const char* var);
/**
* Intend to retrieve device variable values.
* \param client Nut client handle.
* \param dev Device name.
* \param var Variable name.
* \return Array of string containing variable values. Must be freed with strarr_free(strarr).
*/
strarr nutclient_get_device_variable_values(NUTCLIENT_t client, const char* dev, const char* var);
/**
* Intend to set device variable value.
* \param client Nut client handle.
* \param dev Device name.
* \param var Variable name.
* \param value Value to set.
*/
void nutclient_set_device_variable_value(NUTCLIENT_t client, const char* dev, const char* var, const char* value);
/**
* Intend to set device variable multiple values.
* \param client Nut client handle.
* \param dev Device name.
* \param var Variable name.
* \param values Values to set. The cller is responsible to free it after call.
*/
void nutclient_set_device_variable_values(NUTCLIENT_t client, const char* dev, const char* var, const strarr values);
/**
* Intend to retrieve device command names.
* \param client Nut client handle.
* \param dev Device name.
* \return Array of string containing command names. Must be freed with strarr_free(strarr).
*/
strarr nutclient_get_device_commands(NUTCLIENT_t client, const char* dev);
/**
* Test if a command is supported by the device and the client.
* \param client Nut client handle.
* \param dev Device name.
* \param cmd Command name.
* \return 1 if supported, 0 otherwise.
*/
int nutclient_has_device_command(NUTCLIENT_t client, const char* dev, const char* cmd);
/**
* Intend to retrieve device command description.
* \param client Nut client handle.
* \param dev Device name.
* \param cmd Command name.
* \return Description of device command. Must be freed after use.
*/
char* nutclient_get_device_command_description(NUTCLIENT_t client, const char* dev, const char* cmd);
/**
* Intend to execute device command.
* \param client Nut client handle.
* \param dev Device name.
* \param cmd Command name.
*/
void nutclient_execute_device_command(NUTCLIENT_t client, const char* dev, const char* cmd);
/** \} */
/**
* Nut TCP client dedicated types and functions
* \{
*/
/**
* Hidden structure representing a TCP connection to NUTD.
* NUTCLIENT_TCP_t is back compatible to NUTCLIENT_t.
*/
typedef NUTCLIENT_t NUTCLIENT_TCP_t;
/**
* Create a client to NUTD using a TCP connection.
* \param host Host name to connect to.
* \param port Host port.
* \return New client or NULL if failed.
*/
NUTCLIENT_TCP_t nutclient_tcp_create_client(const char* host, unsigned short port);
/**
* Test if a nut TCP client is connected.
* \param client Nut TCP client handle.
* \return 1 if connected, 0 otherwise.
*/
int nutclient_tcp_is_connected(NUTCLIENT_TCP_t client);
/**
* Disconnect a nut TCP client.
* \param client Nut TCP client handle.
*/
void nutclient_tcp_disconnect(NUTCLIENT_TCP_t client);
/**
* Intend to reconnect a nut TCP client.
* \param client Nut TCP client handle.
* \return 0 if correctly connected.
* \todo Implement different error codes.
*/
int nutclient_tcp_reconnect(NUTCLIENT_TCP_t client);
/**
* Set the timeout value for the TCP connection.
* \param timeout Timeout in seconds, negative for blocking.
*/
void nutclient_tcp_set_timeout(NUTCLIENT_TCP_t client, long timeout);
/**
* Retrieve the timeout value for the TCP connection.
* \return Timeout value in seconds.
*/
long nutclient_tcp_get_timeout(NUTCLIENT_TCP_t client);
/** \} */
#ifdef __cplusplus
}
#endif /* __cplusplus */
/* End of C nutclient library declaration */
#endif /* NUTCLIENT_HPP_SEEN */

View file

@ -17,6 +17,12 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef __cplusplus
/* *INDENT-OFF* */
extern "C" {
/* *INDENT-ON* */
#endif
struct {
char *name;
char *desc;
@ -35,3 +41,10 @@ struct {
{ "BYPASS", "BYPASS", 2 },
{ NULL, NULL, 0 }
};
#ifdef __cplusplus
/* *INDENT-OFF* */
}
/* *INDENT-ON* */
#endif

View file

@ -19,6 +19,7 @@
*/
#include "common.h"
#include "nut_platform.h"
#include <netdb.h>
#include <netinet/in.h>
@ -274,3 +275,11 @@ int main(int argc, char **argv)
exit(EXIT_SUCCESS);
}
/* Formal do_upsconf_args implementation to satisfy linker on AIX */
#if (defined NUT_PLATFORM_AIX)
void do_upsconf_args(char *upsname, char *var, char *val) {
fatalx(EXIT_FAILURE, "INTERNAL ERROR: formal do_upsconf_args called");
}
#endif /* end of #if (defined NUT_PLATFORM_AIX) */

View file

@ -21,6 +21,11 @@
#include "config.h" /* safe because it doesn't contain prototypes */
#ifdef HAVE_PTHREAD
/* this include is needed on AIX to have errno stored in thread local storage */
#include <pthread.h>
#endif
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
@ -33,8 +38,18 @@
#include <fcntl.h>
#include "upsclient.h"
#include "common.h"
#include "timehead.h"
#ifdef WITH_NSS
#include <prerror.h>
#include <prinit.h>
#include <pk11func.h>
#include <prtypes.h>
#include <ssl.h>
#include <private/pprio.h>
#endif /* WITH_NSS */
#define UPSCLIENT_MAGIC 0x19980308
#define SMALLBUF 512
@ -95,9 +110,354 @@ struct {
{ 0, "Protocol error", }, /* 42: UPSCLI_ERR_PROTOCOL */
};
typedef struct HOST_CERT_s {
const char *host;
const char *certname;
int certverify;
int forcessl;
struct HOST_CERT_s *next;
} HOST_CERT_t;
static HOST_CERT_t* upscli_find_host_cert(const char* hostname);
static int upscli_initialized = 0;
#ifdef WITH_OPENSSL
static SSL_CTX *ssl_ctx;
#elif defined(WITH_NSS) /* WITH_OPENSLL */
static int verify_certificate = 1;
static HOST_CERT_t *first_host_cert = NULL;
static char* nsscertname = NULL;
static char* nsscertpasswd = NULL;
#endif /* WITH_OPENSSL | WITH_NSS */
#ifdef WITH_OPENSSL
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(2, "ssl_debug: %s", errmsg);
}
}
static int ssl_error(SSL *ssl, int ret)
{
int e;
e = SSL_get_error(ssl, ret);
switch (e)
{
case SSL_ERROR_WANT_READ:
upslogx(LOG_ERR, "ssl_error() ret=%d SSL_ERROR_WANT_READ", ret);
break;
case SSL_ERROR_WANT_WRITE:
upslogx(LOG_ERR, "ssl_error() ret=%d SSL_ERROR_WANT_WRITE", ret);
break;
case SSL_ERROR_SYSCALL:
if (ret == 0 && ERR_peek_error() == 0) {
upslogx(LOG_ERR, "ssl_error() EOF from client");
} else {
upslogx(LOG_ERR, "ssl_error() ret=%d SSL_ERROR_SYSCALL", ret);
}
break;
default:
upslogx(LOG_ERR, "ssl_error() ret=%d SSL_ERROR %d", ret, e);
ssl_debug();
}
return -1;
}
#elif defined(WITH_NSS) /* WITH_OPENSSL */
static char *nss_password_callback(PK11SlotInfo *slot, PRBool retry,
void *arg)
{
upslogx(LOG_INFO, "Intend to retrieve password for %s / %s: password %sconfigured",
PK11_GetSlotName(slot), PK11_GetTokenName(slot), nsscertpasswd?"":"not ");
return nsscertpasswd ? PL_strdup(nsscertpasswd) : NULL;
}
static void nss_error(const char* funcname)
{
char buffer[SMALLBUF];
PRInt32 length = PR_GetErrorText(buffer);
if (length > 0 && length < SMALLBUF) {
upsdebugx(1, "nss_error %ld in %s : %s", (long)PR_GetError(), funcname, buffer);
}else{
upsdebugx(1, "nss_error %ld in %s", (long)PR_GetError(), funcname);
}
}
static SECStatus AuthCertificate(CERTCertDBHandle *arg, PRFileDesc *fd,
PRBool checksig, PRBool isServer)
{
UPSCONN_t *ups = (UPSCONN_t *)SSL_RevealPinArg(fd);
SECStatus status = SSL_AuthCertificate(arg, fd, checksig, isServer);
upslogx(LOG_INFO, "Intend to authenticate server %s : %s",
ups?ups->host:"<unnamed>",
status==SECSuccess?"SUCCESS":"FAILED");
if (status != SECSuccess) {
nss_error("SSL_AuthCertificate");
}
return status;
}
static SECStatus AuthCertificateDontVerify(CERTCertDBHandle *arg, PRFileDesc *fd,
PRBool checksig, PRBool isServer)
{
UPSCONN_t *ups = (UPSCONN_t *)SSL_RevealPinArg(fd);
upslogx(LOG_INFO, "Do not intend to authenticate server %s",
ups?ups->host:"<unnamed>");
return SECSuccess;
}
static SECStatus BadCertHandler(UPSCONN_t *arg, PRFileDesc *fd)
{
HOST_CERT_t* cert;
upslogx(LOG_WARNING, "Certificate validation failed for %s",
(arg&&arg->host)?arg->host:"<unnamed>");
/* BadCertHandler is called when the NSS certificate validation is failed.
* If the certificate verification (user conf) is mandatory, reject authentication
* else accept it.
*/
cert = upscli_find_host_cert(arg->host);
if (cert != NULL) {
return cert->certverify==0 ? SECSuccess : SECFailure;
} else {
return verify_certificate==0 ? SECSuccess : SECFailure;
}
}
static SECStatus GetClientAuthData(UPSCONN_t *arg, PRFileDesc *fd,
CERTDistNames *caNames, CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey)
{
CERTCertificate *cert;
SECKEYPrivateKey *privKey;
SECStatus status = NSS_GetClientAuthData(arg, fd, caNames, pRetCert, pRetKey);
if (status == SECFailure) {
if (nsscertname != NULL) {
cert = PK11_FindCertFromNickname(nsscertname, NULL);
if(cert==NULL) {
upslogx(LOG_ERR, "Can not find self-certificate");
nss_error("GetClientAuthData / PK11_FindCertFromNickname");
}else{
privKey = PK11_FindKeyByAnyCert(cert, NULL);
if(privKey==NULL){
upslogx(LOG_ERR, "Can not find private key related to self-certificate");
nss_error("GetClientAuthData / PK11_FindKeyByAnyCert");
}else{
*pRetCert = cert;
*pRetKey = privKey;
status = SECSuccess;
}
}
} else {
upslogx(LOG_ERR, "Self-certificate name not configured");
}
}
return status;
}
static void HandshakeCallback(PRFileDesc *fd, UPSCONN_t *client_data)
{
upslogx(LOG_INFO, "SSL handshake done successfully with server %s",
client_data->host);
}
#endif /* WITH_OPENSSL | WITH_NSS */
int upscli_init(int certverify, const char *certpath,
const char *certname, const char *certpasswd)
{
#ifdef WITH_OPENSSL
int ret, ssl_mode = SSL_VERIFY_NONE;
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
const SSL_METHOD *ssl_method;
#else
SSL_METHOD *ssl_method;
#endif
#elif defined(WITH_NSS) /* WITH_OPENSSL */
SECStatus status;
#endif /* WITH_OPENSSL | WITH_NSS */
if (upscli_initialized == 1) {
upslogx(LOG_WARNING, "upscli already initialized");
return -1;
}
#ifdef WITH_OPENSSL
SSL_library_init();
SSL_load_error_strings();
ssl_method = TLSv1_client_method();
if (!ssl_method) {
return 0;
}
ssl_ctx = SSL_CTX_new(ssl_method);
if (!ssl_ctx) {
upslogx(LOG_ERR, "Can not initialize SSL context");
return -1;
}
if (!certpath) {
if (certverify == 1) {
upslogx(LOG_ERR, "Can not verify certificate if any is specified");
return -1; /* Failed : cert is mandatory but no certfile */
}
} else {
switch(certverify) {
case 0:
ssl_mode = SSL_VERIFY_NONE;
break;
default:
ssl_mode = SSL_VERIFY_PEER;
break;
}
ret = SSL_CTX_load_verify_locations(ssl_ctx, NULL, certpath);
if (ret != 1) {
upslogx(LOG_ERR, "Failed to load certificate from pemfile %s", certpath);
return -1;
}
SSL_CTX_set_verify(ssl_ctx, ssl_mode, NULL);
}
#elif defined(WITH_NSS) /* WITH_OPENSSL */
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
PK11_SetPasswordFunc(nss_password_callback);
if (certpath) {
upslogx(LOG_INFO, "Init SSL with cerificate database located at %s", certpath);
status = NSS_Init(certpath);
} else {
upslogx(LOG_NOTICE, "Init SSL without certificate database");
status = NSS_NoDB_Init(NULL);
}
if (status != SECSuccess) {
upslogx(LOG_ERR, "Can not initialize SSL context");
nss_error("upscli_init / NSS_[NoDB]_Init");
return -1;
}
status = NSS_SetDomesticPolicy();
if (status != SECSuccess) {
upslogx(LOG_ERR, "Can not initialize SSL policy");
nss_error("upscli_init / NSS_SetDomesticPolicy");
return -1;
}
SSL_ClearSessionCache();
status = SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_TRUE);
if (status != SECSuccess) {
upslogx(LOG_ERR, "Can not enable SSLv3");
nss_error("upscli_init / SSL_OptionSetDefault(SSL_ENABLE_SSL3)");
return -1;
}
status = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE);
if (status != SECSuccess) {
upslogx(LOG_ERR, "Can not enable TLSv1");
nss_error("upscli_init / SSL_OptionSetDefault(SSL_ENABLE_TLS)");
return -1;
}
status = SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, PR_FALSE);
if (status != SECSuccess) {
upslogx(LOG_ERR, "Can not disable SSLv2 hello compatibility");
nss_error("upscli_init / SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO)");
return -1;
}
if (certname) {
nsscertname = xstrdup(certname);
}
if (certpasswd) {
nsscertpasswd = xstrdup(certpasswd);
}
verify_certificate = certverify;
#endif /* WITH_OPENSSL | WITH_NSS */
upscli_initialized = 1;
return 1;
}
void upscli_add_host_cert(const char* hostname, const char* certname, int certverify, int forcessl)
{
#ifdef WITH_NSS
HOST_CERT_t* cert = xmalloc(sizeof(HOST_CERT_t));
cert->next = first_host_cert;
cert->host = xstrdup(hostname);
cert->certname = xstrdup(certname);
cert->certverify = certverify;
cert->forcessl = forcessl;
first_host_cert = cert;
#endif /* WITH_NSS */
}
static HOST_CERT_t* upscli_find_host_cert(const char* hostname)
{
#ifdef WITH_NSS
HOST_CERT_t* cert = first_host_cert;
if (hostname != NULL) {
while (cert != NULL) {
if (cert->host != NULL && strcmp(cert->host, hostname)==0 ) {
return cert;
}
cert = cert->next;
}
}
#endif /* WITH_NSS */
return NULL;
}
int upscli_cleanup()
{
#ifdef WITH_OPENSSL
if (ssl_ctx) {
SSL_CTX_free(ssl_ctx);
ssl_ctx = NULL;
}
#endif /* WITH_OPENSSL */
#ifdef WITH_NSS
/* Called to force cache clearing to prevent NSS shutdown failures.
* http://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslfnc.html#1138601
*/
SSL_ClearSessionCache();
NSS_Shutdown();
PR_Cleanup();
/* Called to release memory arena used by NSS/NSPR.
* Prevent to show all PL_ArenaAllocate mem alloc as leaks.
* https://developer.mozilla.org/en/NSS_Memory_allocation
*/
PL_ArenaFinish();
#endif /* WITH_NSS */
upscli_initialized = 0;
return 1;
}
const char *upscli_strerror(UPSCONN_t *ups)
{
#ifdef HAVE_SSL
#ifdef WITH_OPENSSL
unsigned long err;
char sslbuf[UPSCLI_ERRBUF_LEN];
#endif
@ -126,7 +486,7 @@ const char *upscli_strerror(UPSCONN_t *ups)
return ups->errbuf;
case 2: /* SSL error */
#ifdef HAVE_SSL
#ifdef WITH_OPENSSL
err = ERR_get_error();
if (err) {
ERR_error_string(err, sslbuf);
@ -138,10 +498,18 @@ const char *upscli_strerror(UPSCONN_t *ups)
upscli_errlist[ups->upserror].str,
"peer disconnected");
}
#elif defined(WITH_NSS) /* WITH_OPENSSL */
if (PR_GetErrorTextLength() < UPSCLI_ERRBUF_LEN) {
PR_GetErrorText(ups->errbuf);
} else {
snprintf(ups->errbuf, UPSCLI_ERRBUF_LEN,
"SSL error #%ld, message too long to be displayed",
(long)PR_GetError());
}
#else
snprintf(ups->errbuf, UPSCLI_ERRBUF_LEN,
"SSL error, but SSL wasn't enabled at compile-time");
#endif /* HAVE_SSL */
#endif /* WITH_OPENSSL | WITH_NSS */
return ups->errbuf;
case 3: /* parsing (parseconf) error */
@ -162,7 +530,7 @@ const char *upscli_strerror(UPSCONN_t *ups)
/* Read up to buflen bytes from fd and return the number of bytes
read. If no data is available within d_sec + d_usec, return 0.
On error, a value < 0 is returned (errno indicates error). */
static int select_read(const int fd, void *buf, const size_t buflen, const long d_sec, const long d_usec)
static int upscli_select_read(const int fd, void *buf, const size_t buflen, const long d_sec, const long d_usec)
{
int ret;
fd_set fds;
@ -188,9 +556,13 @@ static int net_read(UPSCONN_t *ups, char *buf, size_t buflen)
{
int ret;
#ifdef HAVE_SSL
#ifdef WITH_SSL
if (ups->ssl) {
#ifdef WITH_OPENSSL
ret = SSL_read(ups->ssl, buf, buflen);
#elif defined(WITH_NSS) /* WITH_OPENSSL */
ret = PR_Read(ups->ssl, buf, buflen);
#endif /* WITH_OPENSSL | WITH_NSS*/
if (ret < 1) {
ups->upserror = UPSCLI_ERR_SSLERR;
@ -200,7 +572,7 @@ static int net_read(UPSCONN_t *ups, char *buf, size_t buflen)
}
#endif
ret = select_read(ups->fd, buf, buflen, 5, 0);
ret = upscli_select_read(ups->fd, buf, buflen, 5, 0);
/* error reading data, server disconnected? */
if (ret < 0) {
@ -219,7 +591,7 @@ static int net_read(UPSCONN_t *ups, char *buf, size_t buflen)
/* Write up to buflen bytes to fd and return the number of bytes
written. If no data is available within d_sec + d_usec, return 0.
On error, a value < 0 is returned (errno indicates error). */
static int select_write(const int fd, const void *buf, const size_t buflen, const long d_sec, const long d_usec)
static int upscli_select_write(const int fd, const void *buf, const size_t buflen, const long d_sec, const long d_usec)
{
int ret;
fd_set fds;
@ -245,9 +617,13 @@ static int net_write(UPSCONN_t *ups, const char *buf, size_t buflen)
{
int ret;
#ifdef HAVE_SSL
#ifdef WITH_SSL
if (ups->ssl) {
#ifdef WITH_OPENSSL
ret = SSL_write(ups->ssl, buf, buflen);
#elif defined(WITH_NSS) /* WITH_OPENSSL */
ret = PR_Write(ups->ssl, buf, buflen);
#endif /* WITH_OPENSSL | WITH_NSS */
if (ret < 1) {
ups->upserror = UPSCLI_ERR_SSLERR;
@ -257,7 +633,7 @@ static int net_write(UPSCONN_t *ups, const char *buf, size_t buflen)
}
#endif
ret = select_write(ups->fd, buf, buflen, 0, 0);
ret = upscli_select_write(ups->fd, buf, buflen, 0, 0);
/* error writing data, server disconnected? */
if (ret < 0) {
@ -273,39 +649,34 @@ static int net_write(UPSCONN_t *ups, const char *buf, size_t buflen)
return ret;
}
/* stub first */
#ifndef HAVE_SSL
static int upscli_sslinit(UPSCONN_t *ups)
#ifdef WITH_SSL
/*
* 1 : OK
* -1 : ERROR
* 0 : SSL NOT SUPPORTED
*/
static int upscli_sslinit(UPSCONN_t *ups, int verifycert)
{
return 0; /* not supported */
}
int upscli_sslcert(UPSCONN_t *ups, const char *dir, const char *file, int verify)
{
if (!ups) {
return -1;
}
/* if forcing the verification, this fails since we have no SSL */
if (verify == 1) {
ups->upserror = UPSCLI_ERR_SSLFAIL;
return -1;
}
return 0; /* not supported */
}
#else
static int upscli_sslinit(UPSCONN_t *ups)
{
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
const SSL_METHOD *ssl_method;
#else
SSL_METHOD *ssl_method;
#endif
#ifdef WITH_OPENSSL
int res;
#elif defined(WITH_NSS) /* WITH_OPENSSL */
SECStatus status;
PRFileDesc *socket;
HOST_CERT_t *cert;
#endif /* WITH_OPENSSL | WITH_NSS */
char buf[UPSCLI_NETBUF_LEN];
/* Intend to initialize upscli with no ssl db if not already done.
* Compatibility stuff for old clients which do not initialize them.
*/
if (upscli_initialized==0) {
upsdebugx(3, "upscli not initialized, "
"force initialisation without SSL configuration");
upscli_init(0, NULL, NULL, NULL);
}
/* see if upsd even talks SSL/TLS */
snprintf(buf, sizeof(buf), "STARTTLS\n");
@ -322,84 +693,150 @@ static int upscli_sslinit(UPSCONN_t *ups)
}
/* upsd is happy, so let's crank up the client */
#ifdef WITH_OPENSSL
SSL_load_error_strings();
SSL_library_init();
ssl_method = TLSv1_client_method();
if (!ssl_method) {
if (!ssl_ctx) {
upsdebugx(3, "SSL context is not available");
return 0;
}
ups->ssl_ctx = SSL_CTX_new(ssl_method);
if (!ups->ssl_ctx) {
return 0;
}
ups->ssl = SSL_new(ups->ssl_ctx);
ups->ssl = SSL_new(ssl_ctx);
if (!ups->ssl) {
upsdebugx(3, "Can not create SSL socket");
return 0;
}
if (SSL_set_fd(ups->ssl, ups->fd) != 1) {
upsdebugx(3, "Can not bind file descriptor to SSL socket");
return -1;
}
SSL_set_connect_state(ups->ssl);
return 1; /* OK */
}
/* set the paths for the certs to verify the server */
int upscli_sslcert(UPSCONN_t *ups, const char *file, const char *path, int verify)
{
int ret, ssl_mode = SSL_VERIFY_NONE;
if (!ups) {
return -1;
if (verifycert != 0) {
SSL_set_verify(ups->ssl, SSL_VERIFY_PEER, NULL);
} else {
SSL_set_verify(ups->ssl, SSL_VERIFY_NONE, NULL);
}
if (!ups->ssl_ctx) {
ups->upserror = UPSCLI_ERR_INVALIDARG;
return -1;
}
switch(verify) {
case 0:
ssl_mode = SSL_VERIFY_NONE;
break;
res = SSL_connect(ups->ssl);
switch(res)
{
case 1:
ssl_mode = SSL_VERIFY_PEER;
upsdebugx(3, "SSL connected");
break;
case 0:
upslog_with_errno(1, "SSL_connect do not accept handshake.");
ssl_error(ups->ssl, res);
return -1;
default:
ups->upserror = UPSCLI_ERR_INVALIDARG;
upslog_with_errno(1, "Unknown return value from SSL_connect %d", res);
ssl_error(ups->ssl, res);
return -1;
}
ret = SSL_CTX_load_verify_locations(ups->ssl_ctx, file, path);
if (ret != 1) {
ups->upserror = UPSCLI_ERR_SSLERR;
return -1;
}
SSL_set_verify(ups->ssl, ssl_mode, NULL);
}
return 1;
#elif defined(WITH_NSS) /* WITH_OPENSSL */
socket = PR_ImportTCPSocket(ups->fd);
if (socket == NULL){
nss_error("upscli_sslinit / PR_ImportTCPSocket");
return -1;
}
ups->ssl = SSL_ImportFD(NULL, socket);
if (ups->ssl == NULL){
nss_error("upscli_sslinit / SSL_ImportFD");
return -1;
}
if (SSL_SetPKCS11PinArg(ups->ssl, ups) == -1){
nss_error("upscli_sslinit / SSL_SetPKCS11PinArg");
return -1;
}
if (verifycert) {
status = SSL_AuthCertificateHook(ups->ssl,
(SSLAuthCertificate)AuthCertificate, CERT_GetDefaultCertDB());
} else {
status = SSL_AuthCertificateHook(ups->ssl,
(SSLAuthCertificate)AuthCertificateDontVerify, CERT_GetDefaultCertDB());
}
if (status != SECSuccess) {
nss_error("upscli_sslinit / SSL_AuthCertificateHook");
return -1;
}
status = SSL_BadCertHook(ups->ssl, (SSLBadCertHandler)BadCertHandler, ups);
if (status != SECSuccess) {
nss_error("upscli_sslinit / SSL_BadCertHook");
return -1;
}
status = SSL_GetClientAuthDataHook(ups->ssl, (SSLGetClientAuthData)GetClientAuthData, ups);
if (status != SECSuccess) {
nss_error("upscli_sslinit / SSL_GetClientAuthDataHook");
return -1;
}
status = SSL_HandshakeCallback(ups->ssl, (SSLHandshakeCallback)HandshakeCallback, ups);
if (status != SECSuccess) {
nss_error("upscli_sslinit / SSL_HandshakeCallback");
return -1;
}
cert = upscli_find_host_cert(ups->host);
if (cert != NULL && cert->certname != NULL) {
upslogx(LOG_INFO, "Connecting in SSL to '%s' and look at certificate called '%s'",
ups->host, cert->certname);
status = SSL_SetURL(ups->ssl, cert->certname);
} else {
upslogx(LOG_NOTICE, "Connecting in SSL to '%s' (no certificate name specified)", ups->host);
status = SSL_SetURL(ups->ssl, ups->host);
}
if (status != SECSuccess) {
nss_error("upscli_sslinit / SSL_SetURL");
return -1;
}
status = SSL_ResetHandshake(ups->ssl, PR_FALSE);
if (status != SECSuccess) {
nss_error("upscli_sslinit / SSL_ResetHandshake");
ups->ssl = NULL;
/* EKI wtf unimport or free the socket ? */
return -1;
}
status = SSL_ForceHandshake(ups->ssl);
if (status != SECSuccess) {
nss_error("upscli_sslinit / SSL_ForceHandshake");
ups->ssl = NULL;
/* EKI wtf unimport or free the socket ? */
/* TODO : Close the connection. */
return -1;
}
return 1;
#endif /* WITH_OPENSSL | WITH_NSS */
}
#endif /* HAVE_SSL */
#else /* WITH_SSL */
static int upscli_sslinit(UPSCONN_t *ups, int verifycert)
{
return 0; /* not supported */
}
#endif /* WITH_SSL */
int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags,struct timeval * timeout)
{
int sock_fd;
int sock_fd;
struct addrinfo hints, *res, *ai;
char sport[NI_MAXSERV];
int v;
int v, certverify, tryssl, forcessl, ret;
HOST_CERT_t* hostcert;
fd_set wfds;
int error;
socklen_t error_size;
@ -552,22 +989,46 @@ int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags,stru
ups->port = port;
if (flags & UPSCLI_CONN_TRYSSL) {
upscli_sslinit(ups);
/* see if something made us die inside sslinit */
if (ups->upserror != 0) {
hostcert = upscli_find_host_cert(host);
if (hostcert != NULL) {
/* An host security rule is specified. */
certverify = hostcert->certverify;
forcessl = hostcert->forcessl;
} else {
certverify = (flags & UPSCLI_CONN_CERTVERIF) != 0 ? 1 : 0;
forcessl = (flags & UPSCLI_CONN_REQSSL) != 0 ? 1 : 0;
}
tryssl = (flags & UPSCLI_CONN_TRYSSL) != 0 ? 1 : 0;
if (tryssl || forcessl) {
ret = upscli_sslinit(ups, certverify);
if (forcessl && ret != 1) {
upslogx(LOG_ERR, "Can not connect to %s in SSL, disconnect", host);
ups->upserror = UPSCLI_ERR_SSLFAIL;
upscli_disconnect(ups);
return -1;
} else if (tryssl && ret == -1) {
upslogx(LOG_NOTICE, "Error while connecting to %s, disconnect", host);
upscli_disconnect(ups);
return -1;
} else if (tryssl && ret == 0) {
if (certverify != 0) {
upslogx(LOG_NOTICE, "Can not connect to %s in SSL and "
"certificate is needed, disconnect", host);
upscli_disconnect(ups);
return -1;
}
upsdebugx(3, "Can not connect to %s in SSL, continue uncrypted", host);
} else {
upslogx(LOG_INFO, "Connected to %s in SSL", host);
if (certverify == 0) {
/* you REALLY should set CERTVERIFY to 1 if using SSL... */
upslogx(LOG_WARNING, "Certificate verification is disabled");
}
}
}
if ((flags & UPSCLI_CONN_REQSSL) && (upscli_sslinit(ups) != 1)) {
ups->upserror = UPSCLI_ERR_SSLFAIL;
upscli_disconnect(ups);
return -1;
}
return 0;
}
@ -1044,18 +1505,19 @@ int upscli_disconnect(UPSCONN_t *ups)
net_write(ups, "LOGOUT\n", 7);
#ifdef HAVE_SSL
#ifdef WITH_OPENSSL
if (ups->ssl) {
SSL_shutdown(ups->ssl);
SSL_free(ups->ssl);
ups->ssl = NULL;
}
if (ups->ssl_ctx) {
SSL_CTX_free(ups->ssl_ctx);
ups->ssl_ctx = NULL;
#elif defined(WITH_NSS) /* WITH_OPENSSL */
if (ups->ssl) {
PR_Shutdown(ups->ssl, PR_SHUTDOWN_BOTH);
PR_Close(ups->ssl);
ups->ssl = NULL;
}
#endif
#endif /* WITH_OPENSSL | WITH_NSS */
shutdown(ups->fd, shutdown_how);
@ -1101,9 +1563,11 @@ int upscli_ssl(UPSCONN_t *ups)
return -1;
}
#ifdef WITH_SSL
if (ups->ssl) {
return 1;
}
#endif /* WITH_SSL */
return 0;
}

View file

@ -20,10 +20,13 @@
#ifndef UPSCLIENT_H_SEEN
#define UPSCLIENT_H_SEEN
#ifdef HAVE_SSL
#include <openssl/err.h>
#include <openssl/ssl.h>
#endif
#ifdef WITH_OPENSSL
#include <openssl/err.h>
#include <openssl/ssl.h>
#elif defined(WITH_NSS) /* WITH_OPENSSL */
#include <nss.h>
#include <ssl.h>
#endif /* WITH_OPENSSL | WITH_NSS */
#ifdef __cplusplus
/* *INDENT-OFF* */
@ -49,13 +52,13 @@ typedef struct {
char errbuf[UPSCLI_ERRBUF_LEN];
#ifdef HAVE_SSL
SSL_CTX *ssl_ctx;
#ifdef WITH_OPENSSL
SSL *ssl;
#else
void *ssl_ctx;
void *ssl;
#endif
#elif defined(WITH_NSS) /* WITH_OPENSSL */
PRFileDesc *ssl;
#else /* WITH_OPENSSL | WITH_NSS */
void *ssl;
#endif /* WITH_OPENSSL | WITH_NSS */
char readbuf[64];
size_t readlen;
@ -65,10 +68,14 @@ typedef struct {
const char *upscli_strerror(UPSCONN_t *ups);
int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags, struct timeval *tv);
int upscli_init(int certverify, const char *certpath, const char *certname, const char *certpasswd);
int upscli_cleanup();
int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags, struct timeval *tv);
int upscli_connect(UPSCONN_t *ups, const char *host, int port, int flags);
void upscli_add_host_cert(const char* hostname, const char* certname, int certverify, int forcessl);
/* --- functions that only use the new names --- */
int upscli_get(UPSCONN_t *ups, unsigned int numq, const char **query,
@ -88,8 +95,6 @@ int upscli_splitname(const char *buf, char **upsname, char **hostname,
int upscli_splitaddr(const char *buf, char **hostname, int *port);
int upscli_sslcert(UPSCONN_t *ups, const char *file, const char *path, int verify);
int upscli_disconnect(UPSCONN_t *ups);
/* these functions return elements from UPSCONN_t to avoid direct references */
@ -156,10 +161,11 @@ int upscli_ssl(UPSCONN_t *ups);
/* flags for use with upscli_connect */
#define UPSCLI_CONN_TRYSSL 0x0001 /* try SSL, OK if not supported */
#define UPSCLI_CONN_REQSSL 0x0002 /* try SSL, fail if not supported */
#define UPSCLI_CONN_INET 0x0004 /* IPv4 only */
#define UPSCLI_CONN_INET6 0x0008 /* IPv6 only */
#define UPSCLI_CONN_TRYSSL 0x0001 /* try SSL, OK if not supported */
#define UPSCLI_CONN_REQSSL 0x0002 /* try SSL, fail if not supported */
#define UPSCLI_CONN_INET 0x0004 /* IPv4 only */
#define UPSCLI_CONN_INET6 0x0008 /* IPv6 only */
#define UPSCLI_CONN_CERTVERIF 0x0010 /* Verify certificates for SSL */
#ifdef __cplusplus
/* *INDENT-OFF* */

View file

@ -18,6 +18,7 @@
*/
#include "common.h"
#include "nut_platform.h"
#include <pwd.h>
#include <netdb.h>
@ -316,3 +317,11 @@ int main(int argc, char **argv)
exit(EXIT_SUCCESS);
}
/* Formal do_upsconf_args implementation to satisfy linker on AIX */
#if (defined NUT_PLATFORM_AIX)
void do_upsconf_args(char *upsname, char *var, char *val) {
fatalx(EXIT_FAILURE, "INTERNAL ERROR: formal do_upsconf_args called");
}
#endif /* end of #if (defined NUT_PLATFORM_AIX) */

View file

@ -17,6 +17,12 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef __cplusplus
/* *INDENT-OFF* */
extern "C" {
/* *INDENT-ON* */
#endif
struct {
char *name;
int val; /* hex digits, ala HTML */
@ -58,3 +64,10 @@ typedef struct {
} imgvar_t;
extern imgvar_t imgvar[];
#ifdef __cplusplus
/* *INDENT-OFF* */
}
/* *INDENT-ON* */
#endif

View file

@ -32,6 +32,7 @@
*/
#include "common.h"
#include "nut_platform.h"
#include "upsclient.h"
#include "config.h"
@ -528,3 +529,11 @@ int main(int argc, char **argv)
exit(EXIT_SUCCESS);
}
/* Formal do_upsconf_args implementation to satisfy linker on AIX */
#if (defined NUT_PLATFORM_AIX)
void do_upsconf_args(char *upsname, char *var, char *val) {
fatalx(EXIT_FAILURE, "INTERNAL ERROR: formal do_upsconf_args called");
}
#endif /* end of #if (defined NUT_PLATFORM_AIX) */

View file

@ -1,5 +1,11 @@
/* upslog.h - table of functions for handling various logging functions */
#ifdef __cplusplus
/* *INDENT-OFF* */
extern "C" {
/* *INDENT-ON* */
#endif
/* function list */
typedef struct flist_s {
void (*fptr)(const char *arg);
@ -27,3 +33,10 @@ struct {
{ "ETIME", do_etime },
{ NULL, (void(*)())(NULL) }
};
#ifdef __cplusplus
/* *INDENT-OFF* */
}
/* *INDENT-ON* */
#endif

View file

@ -68,6 +68,8 @@ static char *run_as_user = NULL;
/* SSL details - where to find certs, whether to use them */
static char *certpath = NULL;
static char *certname = NULL;
static char *certpasswd = NULL;
static int certverify = 0; /* don't verify by default */
static int forcessl = 0; /* don't require ssl by default */
@ -1178,10 +1180,25 @@ static int parse_conf_arg(int numargs, char **arg)
return 1;
}
/* CERTIDENT <name> <passwd> */
if (!strcmp(arg[0], "CERTIDENT")) {
free(certname);
certname = xstrdup(arg[1]);
free(certpasswd);
certpasswd = xstrdup(arg[2]);
return 1;
}
/* using up to arg[4] below */
if (numargs < 5)
return 0;
/* CERTHOST <hostname> <certname> (0|1) (0|1) */
if (!strcmp(arg[0], "CERTHOST")) {
upscli_add_host_cert(arg[1], arg[2], atoi(arg[3]), atoi(arg[4]));
return 1;
}
if (!strcmp(arg[0], "MONITOR")) {
/* original style: no username (only 5 args) */
@ -1300,6 +1317,8 @@ static void upsmon_cleanup(void)
for (i = 0; notifylist[i].name != NULL; i++) {
free(notifylist[i].msg);
}
upscli_cleanup();
}
static void user_fsd(int sig)
@ -1362,51 +1381,6 @@ static void update_crittimer(utype_t *ups)
/* fallthrough: let the timer age */
}
static int try_ssl(utype_t *ups)
{
int ret;
/* if not doing SSL, we're done */
if (!upscli_ssl(&ups->conn))
return 1;
if (!certpath) {
if (certverify == 1) {
upslogx(LOG_ERR, "Configuration error: "
"CERTVERIFY is set, but CERTPATH isn't");
upslogx(LOG_ERR, "UPS [%s]: Connection impossible, "
"dropping link", ups->sys);
ups_is_gone(ups);
drop_connection(ups);
return 0; /* failed */
}
/* certverify is 0, so just warn them and return */
upslogx(LOG_WARNING, "Certificate verification is disabled");
return 1;
}
/* you REALLY should set CERTVERIFY to 1 if using SSL... */
if (certverify == 0)
upslogx(LOG_WARNING, "Certificate verification is disabled");
ret = upscli_sslcert(&ups->conn, NULL, certpath, certverify);
if (ret < 0) {
upslogx(LOG_ERR, "UPS [%s]: SSL certificate set failed: %s",
ups->sys, upscli_strerror(&ups->conn));
ups_is_gone(ups);
drop_connection(ups);
return 0;
}
return 1;
}
/* handle connecting to upsd, plus get SSL going too if possible */
static int try_connect(utype_t *ups)
{
@ -1428,21 +1402,33 @@ static int try_connect(utype_t *ups)
if (opt_af == AF_INET6)
flags |= UPSCLI_CONN_INET6;
if (!certpath) {
if (certverify == 1) {
upslogx(LOG_ERR, "Configuration error: "
"CERTVERIFY is set, but CERTPATH isn't");
upslogx(LOG_ERR, "UPS [%s]: Connection impossible, "
"dropping link", ups->sys);
ups_is_gone(ups);
drop_connection(ups);
return 0; /* failed */
}
}
if (certverify == 1) {
flags |= UPSCLI_CONN_CERTVERIF;
}
ret = upscli_connect(&ups->conn, ups->hostname, ups->port, flags);
if (ret < 0) {
upslogx(LOG_ERR, "UPS [%s]: connect failed: %s",
ups->sys, upscli_strerror(&ups->conn));
ups_is_gone(ups);
return 0;
}
ret = try_ssl(ups);
if (ret == 0)
return 0; /* something broke while trying SSL */
/* we're definitely connected now */
setflag(&ups->status, ST_CONNECTED);
@ -1998,7 +1984,11 @@ int main(int argc, char *argv[])
writepid(prog);
}
if (upscli_init(certverify, certpath, certname, certpasswd) < 0) {
exit(EXIT_FAILURE);
}
/* prep our signal handlers */
setup_signals();

View file

@ -30,6 +30,12 @@
/* required contents of flag file */
#define SDMAGIC "upsmon-shutdown-file"
#ifdef __cplusplus
/* *INDENT-OFF* */
extern "C" {
/* *INDENT-ON* */
#endif
/* UPS tracking structure */
typedef struct {
@ -110,3 +116,9 @@ struct {
/* various constants */
#define NET_TIMEOUT 10 /* wait 10 seconds max for upsd to respond */
#ifdef __cplusplus
/* *INDENT-OFF* */
}
/* *INDENT-ON* */
#endif

View file

@ -18,6 +18,7 @@
*/
#include "common.h"
#include "nut_platform.h"
#include <pwd.h>
#include <netdb.h>
@ -202,7 +203,7 @@ static const char *get_data(const char *type, const char *varname)
return answer[3];
}
static void do_string(const char *varname)
static void do_string(const char *varname, const int len)
{
const char *val;
@ -213,6 +214,7 @@ static void do_string(const char *varname)
}
printf("Type: STRING\n");
printf("Maximum length: %d\n", len);
printf("Value: %s\n", val);
}
@ -355,8 +357,13 @@ static void do_type(const char *varname)
}
if (!strncasecmp(answer[i], "STRING:", 7)) {
do_string(varname);
char *len = answer[i] + 7;
int length = strtol(len, NULL, 10);
do_string(varname, length);
return;
}
/* ignore this one */
@ -518,3 +525,11 @@ int main(int argc, char **argv)
exit(EXIT_SUCCESS);
}
/* Formal do_upsconf_args implementation to satisfy linker on AIX */
#if (defined NUT_PLATFORM_AIX)
void do_upsconf_args(char *upsname, char *var, char *val) {
fatalx(EXIT_FAILURE, "INTERNAL ERROR: formal do_upsconf_args called");
}
#endif /* end of #if (defined NUT_PLATFORM_AIX) */

View file

@ -6,9 +6,22 @@
#define SERIALIZE_SET 2
#define SERIALIZE_WAIT 3
#ifdef __cplusplus
/* *INDENT-OFF* */
extern "C" {
/* *INDENT-ON* */
#endif
/* track client connections */
typedef struct conn_s {
int fd;
PCONF_CTX_t ctx;
struct conn_s *next;
} conn_t;
#ifdef __cplusplus
/* *INDENT-OFF* */
}
/* *INDENT-ON* */
#endif

View file

@ -17,8 +17,21 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef __cplusplus
/* *INDENT-OFF* */
extern "C" {
/* *INDENT-ON* */
#endif
typedef struct {
char *sys;
char *desc;
void *next;
} ulist_t;
#ifdef __cplusplus
/* *INDENT-OFF* */
}
/* *INDENT-ON* */
#endif