summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am43
-rw-r--r--src/Makefile.in788
-rw-r--r--src/ipmievd.c881
-rw-r--r--src/ipmishell.c510
-rw-r--r--src/ipmitool.c136
-rw-r--r--src/plugins/Makefile.am43
-rw-r--r--src/plugins/Makefile.in695
-rw-r--r--src/plugins/bmc/Makefile.am41
-rw-r--r--src/plugins/bmc/Makefile.in541
-rw-r--r--src/plugins/bmc/bmc.c351
-rw-r--r--src/plugins/bmc/bmc.h52
-rw-r--r--src/plugins/bmc/bmc_intf.h207
-rw-r--r--src/plugins/dummy/Makefile.am8
-rw-r--r--src/plugins/dummy/Makefile.in508
-rw-r--r--src/plugins/dummy/dummy.c286
-rw-r--r--src/plugins/free/Makefile.am9
-rw-r--r--src/plugins/free/Makefile.in512
-rw-r--r--src/plugins/free/free.c318
-rw-r--r--src/plugins/imb/Makefile.am39
-rw-r--r--src/plugins/imb/Makefile.in539
-rw-r--r--src/plugins/imb/imb.c131
-rw-r--r--src/plugins/imb/imbapi.c2090
-rw-r--r--src/plugins/imb/imbapi.h652
-rw-r--r--src/plugins/ipmi_intf.c651
-rw-r--r--src/plugins/lan/Makefile.am39
-rw-r--r--src/plugins/lan/Makefile.in540
-rw-r--r--src/plugins/lan/asf.h75
-rw-r--r--src/plugins/lan/auth.c220
-rw-r--r--src/plugins/lan/auth.h40
-rw-r--r--src/plugins/lan/lan.c2112
-rw-r--r--src/plugins/lan/lan.h41
-rw-r--r--src/plugins/lan/md5.c381
-rw-r--r--src/plugins/lan/md5.h91
-rw-r--r--src/plugins/lan/rmcp.h99
-rw-r--r--src/plugins/lanplus/Makefile.am45
-rw-r--r--src/plugins/lanplus/Makefile.in550
-rw-r--r--src/plugins/lanplus/asf.h75
-rw-r--r--src/plugins/lanplus/lanplus.c3680
-rw-r--r--src/plugins/lanplus/lanplus.h126
-rw-r--r--src/plugins/lanplus/lanplus_crypt.c934
-rw-r--r--src/plugins/lanplus/lanplus_crypt.h75
-rw-r--r--src/plugins/lanplus/lanplus_crypt_impl.c293
-rw-r--r--src/plugins/lanplus/lanplus_crypt_impl.h66
-rw-r--r--src/plugins/lanplus/lanplus_dump.c192
-rw-r--r--src/plugins/lanplus/lanplus_dump.h45
-rw-r--r--src/plugins/lanplus/lanplus_strings.c39
-rw-r--r--src/plugins/lanplus/rmcp.h82
-rw-r--r--src/plugins/lipmi/Makefile.am39
-rw-r--r--src/plugins/lipmi/Makefile.in538
-rw-r--r--src/plugins/lipmi/lipmi.c129
-rw-r--r--src/plugins/open/Makefile.am39
-rw-r--r--src/plugins/open/Makefile.in538
-rw-r--r--src/plugins/open/open.c439
-rw-r--r--src/plugins/open/open.h106
-rw-r--r--src/plugins/serial/Makefile.am38
-rw-r--r--src/plugins/serial/Makefile.in539
-rw-r--r--src/plugins/serial/serial_basic.c1029
-rw-r--r--src/plugins/serial/serial_terminal.c919
58 files changed, 24224 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..ba388d3
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,43 @@
+# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Sun Microsystems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+INCLUDES = -I$(top_srcdir)/include
+SUBDIRS = plugins
+
+MAINTAINERCLEANFILES = Makefile.in
+
+ipmitool_SOURCES = ipmitool.c ipmishell.c
+ipmitool_LDADD = $(top_builddir)/lib/libipmitool.la plugins/libintf.la
+
+ipmievd_SOURCES = ipmievd.c
+ipmievd_LDADD = $(top_builddir)/lib/libipmitool.la plugins/libintf.la
+
+bin_PROGRAMS = ipmitool
+sbin_PROGRAMS = ipmievd
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..b3cde64
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,788 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 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.
+
+# 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@
+
+# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Sun Microsystems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+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@
+bin_PROGRAMS = ipmitool$(EXEEXT)
+sbin_PROGRAMS = ipmievd$(EXEEXT)
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)"
+PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS)
+am_ipmievd_OBJECTS = ipmievd.$(OBJEXT)
+ipmievd_OBJECTS = $(am_ipmievd_OBJECTS)
+ipmievd_DEPENDENCIES = $(top_builddir)/lib/libipmitool.la \
+ plugins/libintf.la
+am_ipmitool_OBJECTS = ipmitool.$(OBJEXT) ipmishell.$(OBJEXT)
+ipmitool_OBJECTS = $(am_ipmitool_OBJECTS)
+ipmitool_DEPENDENCIES = $(top_builddir)/lib/libipmitool.la \
+ plugins/libintf.la
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+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 = $(ipmievd_SOURCES) $(ipmitool_SOURCES)
+DIST_SOURCES = $(ipmievd_SOURCES) $(ipmitool_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+ARCH = @ARCH@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASEDIR = @BASEDIR@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTRO = @DISTRO@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTF_BMC = @INTF_BMC@
+INTF_BMC_LIB = @INTF_BMC_LIB@
+INTF_DUMMY = @INTF_DUMMY@
+INTF_DUMMY_LIB = @INTF_DUMMY_LIB@
+INTF_FREE = @INTF_FREE@
+INTF_FREE_LIB = @INTF_FREE_LIB@
+INTF_IMB = @INTF_IMB@
+INTF_IMB_LIB = @INTF_IMB_LIB@
+INTF_LAN = @INTF_LAN@
+INTF_LANPLUS = @INTF_LANPLUS@
+INTF_LANPLUS_LIB = @INTF_LANPLUS_LIB@
+INTF_LAN_LIB = @INTF_LAN_LIB@
+INTF_LIPMI = @INTF_LIPMI@
+INTF_LIPMI_LIB = @INTF_LIPMI_LIB@
+INTF_OPEN = @INTF_OPEN@
+INTF_OPEN_LIB = @INTF_OPEN_LIB@
+INTF_SERIAL = @INTF_SERIAL@
+INTF_SERIAL_LIB = @INTF_SERIAL_LIB@
+IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OS = @OS@
+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@
+POW_LIB = @POW_LIB@
+PSTAMP = @PSTAMP@
+RANLIB = @RANLIB@
+RPMBUILD = @RPMBUILD@
+RPM_RELEASE = @RPM_RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_configure_args = @ac_configure_args@
+ac_ct_AR = @ac_ct_AR@
+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@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+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@
+INCLUDES = -I$(top_srcdir)/include
+SUBDIRS = plugins
+MAINTAINERCLEANFILES = Makefile.in
+ipmitool_SOURCES = ipmitool.c ipmishell.c
+ipmitool_LDADD = $(top_builddir)/lib/libipmitool.la plugins/libintf.la
+ipmievd_SOURCES = ipmievd.c
+ipmievd_LDADD = $(top_builddir)/lib/libipmitool.la plugins/libintf.la
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(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) --foreign src/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/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: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || 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)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || 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)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ @list='$(bin_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
+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
+ipmievd$(EXEEXT): $(ipmievd_OBJECTS) $(ipmievd_DEPENDENCIES) $(EXTRA_ipmievd_DEPENDENCIES)
+ @rm -f ipmievd$(EXEEXT)
+ $(LINK) $(ipmievd_OBJECTS) $(ipmievd_LDADD) $(LIBS)
+ipmitool$(EXEEXT): $(ipmitool_OBJECTS) $(ipmitool_DEPENDENCIES) $(EXTRA_ipmitool_DEPENDENCIES)
+ @rm -f ipmitool$(EXEEXT)
+ $(LINK) $(ipmitool_OBJECTS) $(ipmitool_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmievd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmishell.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmitool.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
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+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: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ 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: ctags-recursive $(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
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(PROGRAMS)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ 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:
+
+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."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-recursive
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool \
+ clean-sbinPROGRAMS mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS install-sbinPROGRAMS
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-sbinPROGRAMS
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic clean-libtool clean-sbinPROGRAMS ctags \
+ ctags-recursive distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-binPROGRAMS \
+ 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 \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am uninstall-binPROGRAMS \
+ 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:
diff --git a/src/ipmievd.c b/src/ipmievd.c
new file mode 100644
index 0000000..f940579
--- /dev/null
+++ b/src/ipmievd.c
@@ -0,0 +1,881 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#if defined(HAVE_SYS_IOCCOM_H)
+# include <sys/ioccom.h>
+#endif
+
+#ifdef HAVE_PATHS_H
+# include <paths.h>
+#endif
+
+#ifndef _PATH_VARRUN
+# define _PATH_VARRUN "/var/run/"
+#endif
+
+#ifdef IPMI_INTF_OPEN
+# if defined(HAVE_OPENIPMI_H)
+# if defined(HAVE_LINUX_COMPILER_H)
+# include <linux/compiler.h>
+# endif
+# include <linux/ipmi.h>
+# elif defined(HAVE_FREEBSD_IPMI_H)
+# include <sys/ipmi.h>
+# else
+# include "plugins/open/open.h"
+# endif
+# include <sys/poll.h>
+#endif /* IPMI_INTF_OPEN */
+
+#include <ipmitool/helper.h>
+#include <ipmitool/log.h>
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_intf.h>
+#include <ipmitool/ipmi_sel.h>
+#include <ipmitool/ipmi_sdr.h>
+#include <ipmitool/ipmi_strings.h>
+#include <ipmitool/ipmi_main.h>
+
+#define WARNING_THRESHOLD 80
+#define DEFAULT_PIDFILE _PATH_VARRUN "ipmievd.pid"
+char pidfile[64];
+
+/* global variables */
+int verbose = 0;
+int csv_output = 0;
+uint16_t selwatch_count = 0; /* number of entries in the SEL */
+uint16_t selwatch_lastid = 0; /* current last entry in the SEL */
+int selwatch_pctused = 0; /* current percent usage in the SEL */
+int selwatch_overflow = 0; /* SEL overflow */
+int selwatch_timeout = 10; /* default to 10 seconds */
+
+/* event interface definition */
+struct ipmi_event_intf {
+ char name[16];
+ char desc[128];
+ char prefix[72];
+ int (*setup)(struct ipmi_event_intf * eintf);
+ int (*wait)(struct ipmi_event_intf * eintf);
+ int (*read)(struct ipmi_event_intf * eintf);
+ int (*check)(struct ipmi_event_intf * eintf);
+ void (*log)(struct ipmi_event_intf * eintf, struct sel_event_record * evt);
+ struct ipmi_intf * intf;
+};
+
+/* Data from SEL we are interested in */
+typedef struct sel_data {
+ uint16_t entries;
+ int pctused;
+ int overflow;
+} sel_data;
+
+static void log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt);
+
+/* ~~~~~~~~~~~~~~~~~~~~~~ openipmi ~~~~~~~~~~~~~~~~~~~~ */
+#ifdef IPMI_INTF_OPEN
+static int openipmi_setup(struct ipmi_event_intf * eintf);
+static int openipmi_wait(struct ipmi_event_intf * eintf);
+static int openipmi_read(struct ipmi_event_intf * eintf);
+static struct ipmi_event_intf openipmi_event_intf = {
+ name: "open",
+ desc: "OpenIPMI asyncronous notification of events",
+ prefix: "",
+ setup: openipmi_setup,
+ wait: openipmi_wait,
+ read: openipmi_read,
+ log: log_event,
+};
+#endif
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+/* ~~~~~~~~~~~~~~~~~~~~~~ selwatch ~~~~~~~~~~~~~~~~~~~~ */
+static int selwatch_setup(struct ipmi_event_intf * eintf);
+static int selwatch_wait(struct ipmi_event_intf * eintf);
+static int selwatch_read(struct ipmi_event_intf * eintf);
+static int selwatch_check(struct ipmi_event_intf * eintf);
+static struct ipmi_event_intf selwatch_event_intf = {
+ name: "sel",
+ desc: "Poll SEL for notification of events",
+ setup: selwatch_setup,
+ wait: selwatch_wait,
+ read: selwatch_read,
+ check: selwatch_check,
+ log: log_event,
+};
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+struct ipmi_event_intf * ipmi_event_intf_table[] = {
+#ifdef IPMI_INTF_OPEN
+ &openipmi_event_intf,
+#endif
+ &selwatch_event_intf,
+ NULL
+};
+
+/*************************************************************************/
+
+static void
+ipmievd_usage(void)
+{
+ lprintf(LOG_NOTICE, "Options:");
+ lprintf(LOG_NOTICE, "\ttimeout=# Time between checks for SEL polling method [default=10]");
+ lprintf(LOG_NOTICE, "\tdaemon Become a daemon [default]");
+ lprintf(LOG_NOTICE, "\tnodaemon Do NOT become a daemon");
+}
+
+/* ipmi_intf_load - Load an event interface from the table above
+ * If no interface name is given return first entry
+ *
+ * @name: interface name to try and load
+ *
+ * returns pointer to inteface structure if found
+ * returns NULL on error
+ */
+static struct ipmi_event_intf *
+ipmi_event_intf_load(char * name)
+{
+ struct ipmi_event_intf ** intf;
+ struct ipmi_event_intf * i;
+
+ if (name == NULL) {
+ i = ipmi_event_intf_table[0];
+ return i;
+ }
+
+ for (intf = ipmi_event_intf_table;
+ ((intf != NULL) && (*intf != NULL));
+ intf++) {
+ i = *intf;
+ if (strncmp(name, i->name, strlen(name)) == 0) {
+ return i;
+ }
+ }
+
+ return NULL;
+}
+
+static int
+compute_pctfull(uint16_t entries, uint16_t freespace)
+{
+ int pctfull = 0;
+
+ if (entries) {
+ entries *= 16;
+ freespace += entries;
+ pctfull = (int)(100 * ( (double)entries / (double)freespace ));
+ }
+ return pctfull;
+}
+
+
+static void
+log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt)
+{
+ char *desc;
+ const char *type;
+ struct sdr_record_list * sdr;
+ struct ipmi_intf * intf = eintf->intf;
+ float trigger_reading = 0.0;
+ float threshold_reading = 0.0;
+
+ if (evt == NULL)
+ return;
+
+ if (evt->record_type == 0xf0) {
+ lprintf(LOG_ALERT, "%sLinux kernel panic: %.11s",
+ eintf->prefix, (char *) evt + 5);
+ return;
+ }
+ else if (evt->record_type >= 0xc0) {
+ lprintf(LOG_NOTICE, "%sIPMI Event OEM Record %02x",
+ eintf->prefix, evt->record_type);
+ return;
+ }
+
+ type = ipmi_sel_get_sensor_type_offset(evt->sel_type.standard_type.sensor_type,
+ evt->sel_type.standard_type.event_data[0]);
+
+ ipmi_get_event_desc(intf, evt, &desc);
+
+ sdr = ipmi_sdr_find_sdr_bynumtype(intf, evt->sel_type.standard_type.gen_id, evt->sel_type.standard_type.sensor_num,
+ evt->sel_type.standard_type.sensor_type);
+
+ if (sdr == NULL) {
+ /* could not find matching SDR record */
+ if (desc) {
+ lprintf(LOG_NOTICE, "%s%s sensor - %s",
+ eintf->prefix, type, desc);
+ free(desc);
+ desc = NULL;
+ } else {
+ lprintf(LOG_NOTICE, "%s%s sensor %02x",
+ eintf->prefix, type,
+ evt->sel_type.standard_type.sensor_num);
+ }
+ return;
+ }
+
+ switch (sdr->type) {
+ case SDR_RECORD_TYPE_FULL_SENSOR:
+ if (evt->sel_type.standard_type.event_type == 1) {
+ /*
+ * Threshold Event
+ */
+
+ /* trigger reading in event data byte 2 */
+ if (((evt->sel_type.standard_type.event_data[0] >> 6) & 3) == 1) {
+ trigger_reading = sdr_convert_sensor_reading(
+ sdr->record.full, evt->sel_type.standard_type.event_data[1]);
+ }
+
+ /* trigger threshold in event data byte 3 */
+ if (((evt->sel_type.standard_type.event_data[0] >> 4) & 3) == 1) {
+ threshold_reading = sdr_convert_sensor_reading(
+ sdr->record.full, evt->sel_type.standard_type.event_data[2]);
+ }
+
+ lprintf(LOG_NOTICE, "%s%s sensor %s %s %s (Reading %.*f %s Threshold %.*f %s)",
+ eintf->prefix,
+ type,
+ sdr->record.full->id_string,
+ desc ? : "",
+ (evt->sel_type.standard_type.event_dir
+ ? "Deasserted" : "Asserted"),
+ (trigger_reading==(int)trigger_reading) ? 0 : 2,
+ trigger_reading,
+ ((evt->sel_type.standard_type.event_data[0] & 0xf) % 2) ? ">" : "<",
+ (threshold_reading==(int)threshold_reading) ? 0 : 2,
+ threshold_reading,
+ ipmi_sdr_get_unit_string(sdr->record.common->unit.pct,
+ sdr->record.common->unit.modifier,
+ sdr->record.common->unit.type.base,
+ sdr->record.common->unit.type.modifier));
+ }
+ else if ((evt->sel_type.standard_type.event_type >= 0x2 && evt->sel_type.standard_type.event_type <= 0xc) ||
+ (evt->sel_type.standard_type.event_type == 0x6f)) {
+ /*
+ * Discrete Event
+ */
+ lprintf(LOG_NOTICE, "%s%s sensor %s %s %s",
+ eintf->prefix, type,
+ sdr->record.full->id_string, desc ? : "",
+ (evt->sel_type.standard_type.event_dir
+ ? "Deasserted" : "Asserted"));
+ if (((evt->sel_type.standard_type.event_data[0] >> 6) & 3) == 1) {
+ /* previous state and/or severity in event data byte 2 */
+ }
+ }
+ else if (evt->sel_type.standard_type.event_type >= 0x70 && evt->sel_type.standard_type.event_type <= 0x7f) {
+ /*
+ * OEM Event
+ */
+ lprintf(LOG_NOTICE, "%s%s sensor %s %s %s",
+ eintf->prefix, type,
+ sdr->record.full->id_string, desc ? : "",
+ (evt->sel_type.standard_type.event_dir
+ ? "Deasserted" : "Asserted"));
+ }
+ break;
+
+ case SDR_RECORD_TYPE_COMPACT_SENSOR:
+ lprintf(LOG_NOTICE, "%s%s sensor %s - %s %s",
+ eintf->prefix, type,
+ sdr->record.compact->id_string, desc ? : "",
+ (evt->sel_type.standard_type.event_dir
+ ? "Deasserted" : "Asserted"));
+ break;
+
+ default:
+ lprintf(LOG_NOTICE, "%s%s sensor - %s",
+ eintf->prefix, type,
+ evt->sel_type.standard_type.sensor_num, desc ? : "");
+ break;
+ }
+
+ if (desc) {
+ free(desc);
+ desc = NULL;
+ }
+}
+/*************************************************************************/
+
+
+/*************************************************************************/
+/** OpenIPMI Functions **/
+/*************************************************************************/
+#ifdef IPMI_INTF_OPEN
+static int
+openipmi_enable_event_msg_buffer(struct ipmi_intf * intf)
+{
+ struct ipmi_rs * rsp;
+ struct ipmi_rq req;
+ uint8_t bmc_global_enables;
+
+ /* we must read/modify/write bmc global enables */
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_APP;
+ req.msg.cmd = 0x2f; /* Get BMC Global Enables */
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL) {
+ lprintf(LOG_ERR, "Get BMC Global Enables command failed");
+ return -1;
+ }
+ else if (rsp->ccode > 0) {
+ lprintf(LOG_ERR, "Get BMC Global Enables command failed: %s",
+ val2str(rsp->ccode, completion_code_vals));
+ return -1;
+ }
+
+ bmc_global_enables = rsp->data[0] | 0x04;
+ req.msg.cmd = 0x2e; /* Set BMC Global Enables */
+ req.msg.data = &bmc_global_enables;
+ req.msg.data_len = 1;
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL) {
+ lprintf(LOG_ERR, "Set BMC Global Enables command failed");
+ return -1;
+ }
+ else if (rsp->ccode > 0) {
+ lprintf(LOG_ERR, "Set BMC Global Enables command failed: %s",
+ val2str(rsp->ccode, completion_code_vals));
+ return -1;
+ }
+
+ lprintf(LOG_DEBUG, "BMC Event Message Buffer enabled");
+
+ return 0;
+}
+
+static int
+openipmi_setup(struct ipmi_event_intf * eintf)
+{
+ int i, r;
+
+ /* enable event message buffer */
+ lprintf(LOG_DEBUG, "Enabling event message buffer");
+ r = openipmi_enable_event_msg_buffer(eintf->intf);
+ if (r < 0) {
+ lprintf(LOG_ERR, "Could not enable event message buffer");
+ return -1;
+ }
+
+ /* enable OpenIPMI event receiver */
+ lprintf(LOG_DEBUG, "Enabling event receiver");
+ i = 1;
+ r = ioctl(eintf->intf->fd, IPMICTL_SET_GETS_EVENTS_CMD, &i);
+ if (r != 0) {
+ lperror(LOG_ERR, "Could not enable event receiver");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+openipmi_read(struct ipmi_event_intf * eintf)
+{
+ struct ipmi_addr addr;
+ struct ipmi_recv recv;
+ uint8_t data[80];
+ int rv;
+
+ recv.addr = (unsigned char *) &addr;
+ recv.addr_len = sizeof(addr);
+ recv.msg.data = data;
+ recv.msg.data_len = sizeof(data);
+
+ rv = ioctl(eintf->intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv);
+ if (rv < 0) {
+ switch (errno) {
+ case EINTR:
+ return 0; /* abort */
+ case EMSGSIZE:
+ recv.msg.data_len = sizeof(data); /* truncated */
+ break;
+ default:
+ lperror(LOG_ERR, "Unable to receive IPMI message");
+ return -1;
+ }
+ }
+
+ if (!recv.msg.data || recv.msg.data_len == 0) {
+ lprintf(LOG_ERR, "No data in event");
+ return -1;
+ }
+ if (recv.recv_type != IPMI_ASYNC_EVENT_RECV_TYPE) {
+ lprintf(LOG_ERR, "Type %x is not an event", recv.recv_type);
+ return -1;
+ }
+
+ lprintf(LOG_DEBUG, "netfn:%x cmd:%x ccode:%d",
+ recv.msg.netfn, recv.msg.cmd, recv.msg.data[0]);
+
+ eintf->log(eintf, (struct sel_event_record *)recv.msg.data);
+
+ return 0;
+}
+
+static int
+openipmi_wait(struct ipmi_event_intf * eintf)
+{
+ struct pollfd pfd;
+ int r;
+
+ for (;;) {
+ pfd.fd = eintf->intf->fd; /* wait on openipmi device */
+ pfd.events = POLLIN; /* wait for input */
+ r = poll(&pfd, 1, -1);
+
+ switch (r) {
+ case 0:
+ /* timeout is disabled */
+ break;
+ case -1:
+ lperror(LOG_CRIT, "Unable to read from IPMI device");
+ return -1;
+ default:
+ if (pfd.revents & POLLIN)
+ eintf->read(eintf);
+ }
+ }
+
+ return 0;
+}
+#endif /* IPMI_INTF_OPEN */
+/*************************************************************************/
+
+
+/*************************************************************************/
+/** SEL Watch Functions **/
+/*************************************************************************/
+static int
+selwatch_get_data(struct ipmi_intf * intf, struct sel_data *data)
+{
+ struct ipmi_rs * rsp;
+ struct ipmi_rq req;
+ uint16_t freespace;
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_STORAGE;
+ req.msg.cmd = IPMI_CMD_GET_SEL_INFO;
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL) {
+ lprintf(LOG_ERR, "Get SEL Info command failed");
+ return 0;
+ }
+ if (rsp->ccode > 0) {
+ lprintf(LOG_ERR, "Get SEL Info command failed: %s",
+ val2str(rsp->ccode, completion_code_vals));
+ return 0;
+ }
+
+ freespace = buf2short(rsp->data + 3);
+ data->entries = buf2short(rsp->data + 1);
+ data->pctused = compute_pctfull (data->entries, freespace);
+ data->overflow = rsp->data[13] & 0x80;
+
+ lprintf(LOG_DEBUG, "SEL count is %d", data->entries);
+ lprintf(LOG_DEBUG, "SEL freespace is %d", freespace);
+ lprintf(LOG_DEBUG, "SEL Percent Used: %d%%\n", data->pctused);
+ lprintf(LOG_DEBUG, "SEL Overflow: %s", data->overflow ? "true" : "false");
+
+ return 1;
+}
+
+static uint16_t
+selwatch_get_lastid(struct ipmi_intf * intf)
+{
+ int next_id = 0;
+ uint16_t curr_id = 0;
+ struct sel_event_record evt;
+
+ if (selwatch_count == 0)
+ return 0;
+
+ while (next_id != 0xffff) {
+ curr_id = next_id;
+ lprintf(LOG_DEBUG, "SEL Next ID: %04x", curr_id);
+
+ next_id = ipmi_sel_get_std_entry(intf, curr_id, &evt);
+ if (next_id < 0)
+ break;
+ if (next_id == 0) {
+ /*
+ * usually next_id of zero means end but
+ * retry because some hardware has quirks
+ * and will return 0 randomly.
+ */
+ next_id = ipmi_sel_get_std_entry(intf, curr_id, &evt);
+ if (next_id <= 0)
+ break;
+ }
+ }
+
+ lprintf(LOG_DEBUG, "SEL lastid is %04x", curr_id);
+
+ return curr_id;
+}
+
+static int
+selwatch_setup(struct ipmi_event_intf * eintf)
+{
+ struct sel_data data;
+
+ /* save current sel record count */
+ if (selwatch_get_data(eintf->intf, &data)) {
+ selwatch_count = data.entries;
+ selwatch_pctused = data.pctused;
+ selwatch_overflow = data.overflow;
+ lprintf(LOG_DEBUG, "Current SEL count is %d", selwatch_count);
+ /* save current last record ID */
+ selwatch_lastid = selwatch_get_lastid(eintf->intf);
+ lprintf(LOG_DEBUG, "Current SEL lastid is %04x", selwatch_lastid);
+ /* display alert/warning immediatly as startup if relevant */
+ if (selwatch_pctused >= WARNING_THRESHOLD) {
+ lprintf(LOG_WARNING, "SEL buffer used at %d%%, please consider clearing the SEL buffer", selwatch_pctused);
+ }
+ if (selwatch_overflow) {
+ lprintf(LOG_ALERT, "SEL buffer overflow, no SEL message can be logged until the SEL buffer is cleared");
+ }
+
+ return 1;
+ }
+
+ lprintf(LOG_ERR, "Unable to retrieve SEL data");
+ return 0;
+}
+
+/* selwatch_check - check for waiting events
+ *
+ * this is done by reading sel info and comparing
+ * the sel count value to what we currently know
+ */
+static int
+selwatch_check(struct ipmi_event_intf * eintf)
+{
+ uint16_t old_count = selwatch_count;
+ int old_pctused = selwatch_pctused;
+ int old_overflow = selwatch_overflow;
+ struct sel_data data;
+
+ if (selwatch_get_data(eintf->intf, &data)) {
+ selwatch_count = data.entries;
+ selwatch_pctused = data.pctused;
+ selwatch_overflow = data.overflow;
+ if (old_overflow && !selwatch_overflow) {
+ lprintf(LOG_NOTICE, "SEL overflow is cleared");
+ } else if (!old_overflow && selwatch_overflow) {
+ lprintf(LOG_ALERT, "SEL buffer overflow, no new SEL message will be logged until the SEL buffer is cleared");
+ }
+ if ((selwatch_pctused >= WARNING_THRESHOLD) && (selwatch_pctused > old_pctused)) {
+ lprintf(LOG_WARNING, "SEL buffer is %d%% full, please consider clearing the SEL buffer", selwatch_pctused);
+ }
+ if (selwatch_count == 0) {
+ lprintf(LOG_DEBUG, "SEL count is 0 (old=%d), resetting lastid to 0", old_count);
+ selwatch_lastid = 0;
+ } else if (selwatch_count < old_count) {
+ selwatch_lastid = selwatch_get_lastid(eintf->intf);
+ lprintf(LOG_DEBUG, "SEL count lowered, new SEL lastid is %04x", selwatch_lastid);
+ }
+ }
+ return (selwatch_count > old_count);
+}
+
+static int
+selwatch_read(struct ipmi_event_intf * eintf)
+{
+ uint16_t curr_id = 0;
+ int next_id = selwatch_lastid;
+ struct sel_event_record evt;
+
+ if (selwatch_count == 0)
+ return -1;
+
+ while (next_id != 0xffff) {
+ curr_id = next_id;
+ lprintf(LOG_DEBUG, "SEL Read ID: %04x", curr_id);
+
+ next_id = ipmi_sel_get_std_entry(eintf->intf, curr_id, &evt);
+ if (next_id < 0)
+ break;
+ if (next_id == 0) {
+ /*
+ * usually next_id of zero means end but
+ * retry because some hardware has quirks
+ * and will return 0 randomly.
+ */
+ next_id = ipmi_sel_get_std_entry(eintf->intf, curr_id, &evt);
+ if (next_id <= 0)
+ break;
+ }
+
+ if (curr_id != selwatch_lastid)
+ eintf->log(eintf, &evt);
+ else if (curr_id == 0)
+ eintf->log(eintf, &evt);
+ }
+
+ selwatch_lastid = curr_id;
+ return 0;
+}
+
+static int
+selwatch_wait(struct ipmi_event_intf * eintf)
+{
+ for (;;) {
+ if (eintf->check(eintf) > 0) {
+ lprintf(LOG_DEBUG, "New Events");
+ eintf->read(eintf);
+ }
+ sleep(selwatch_timeout);
+ }
+ return 0;
+}
+/*************************************************************************/
+
+static void
+ipmievd_cleanup(int signal)
+{
+ struct stat st1;
+
+ if (lstat(pidfile, &st1) == 0) {
+ /* cleanup daemon pidfile */
+ (void)unlink(pidfile);
+ }
+
+ exit(EXIT_SUCCESS);
+}
+
+int
+ipmievd_main(struct ipmi_event_intf * eintf, int argc, char ** argv)
+{
+ int i, rc;
+ int daemon = 1;
+ struct sigaction act;
+
+ memset(pidfile, 0, 64);
+ sprintf(pidfile, "%s%d", DEFAULT_PIDFILE, eintf->intf->devnum);
+ lprintf(LOG_NOTICE, "ipmievd: using pidfile %s", pidfile);
+
+ for (i = 0; i < argc; i++) {
+ if (strncasecmp(argv[i], "help", 4) == 0) {
+ ipmievd_usage();
+ return 0;
+ }
+ if (strncasecmp(argv[i], "daemon", 6) == 0) {
+ daemon = 1;
+ }
+ else if (strncasecmp(argv[i], "nodaemon", 8) == 0) {
+ daemon = 0;
+ }
+ else if (strncasecmp(argv[i], "daemon=", 7) == 0) {
+ if (strncasecmp(argv[i]+7, "on", 2) == 0 ||
+ strncasecmp(argv[i]+7, "yes", 3) == 0)
+ daemon = 1;
+ else if (strncasecmp(argv[i]+7, "off", 3) == 0 ||
+ strncasecmp(argv[i]+7, "no", 2) == 0)
+ daemon = 0;
+ }
+ else if (strncasecmp(argv[i], "timeout=", 8) == 0) {
+ if ( (str2int(argv[i]+8, &selwatch_timeout) != 0) ||
+ selwatch_timeout < 0) {
+ lprintf(LOG_ERR, "Invalid input given or out of range for time-out.");
+ return (-1);
+ }
+ }
+ else if (strncasecmp(argv[i], "pidfile=", 8) == 0) {
+ memset(pidfile, 0, 64);
+ strncpy(pidfile, argv[i]+8,
+ __min(strlen((const char *)(argv[i]+8)), 63));
+ }
+ }
+
+ /*
+ * We need to open interface before forking daemon
+ * so error messages are not lost to syslog and
+ * return code is successfully returned to initscript
+ */
+ if (eintf->intf->open(eintf->intf) < 0) {
+ lprintf(LOG_ERR, "Unable to open interface");
+ return -1;
+ }
+
+ if (daemon) {
+ FILE *fp;
+ struct stat st1;
+
+ if (lstat(pidfile, &st1) == 0) {
+ /* PID file already exists -> exit. */
+ lprintf(LOG_ERR, "PID file '%s' already exists.", pidfile);
+ lprintf(LOG_ERR, "Perhaps another instance is already running.");
+ return (-1);
+ }
+
+ ipmi_start_daemon(eintf->intf);
+
+ umask(022);
+ fp = ipmi_open_file_write(pidfile);
+ if (fp == NULL) {
+ /* Failed to get fp on PID file -> exit. */
+ log_halt();
+ log_init("ipmievd", daemon, verbose);
+ lprintf(LOG_ERR,
+ "Failed to open PID file '%s' for writing. Check file permission.",
+ pidfile);
+ exit(EXIT_FAILURE);
+ }
+ fprintf(fp, "%d\n", (int)getpid());
+ fclose(fp);
+ }
+
+ /* register signal handler for cleanup */
+ act.sa_handler = ipmievd_cleanup;
+ act.sa_flags = 0;
+ sigemptyset(&act.sa_mask);
+ sigaction(SIGINT, &act, NULL);
+ sigaction(SIGQUIT, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
+
+ log_halt();
+ log_init("ipmievd", daemon, verbose);
+
+ /* generate SDR cache for fast lookups */
+ lprintf(LOG_NOTICE, "Reading sensors...");
+ ipmi_sdr_list_cache(eintf->intf);
+ lprintf(LOG_DEBUG, "Sensors cached");
+
+ /* call event handler setup routine */
+
+ if (eintf->setup != NULL) {
+ rc = eintf->setup(eintf);
+ if (rc < 0) {
+ lprintf(LOG_ERR, "Error setting up Event Interface %s", eintf->name);
+ return -1;
+ }
+ }
+
+ lprintf(LOG_NOTICE, "Waiting for events...");
+
+ /* now launch event wait loop */
+ if (eintf->wait != NULL) {
+ rc = eintf->wait(eintf);
+ if (rc < 0) {
+ lprintf(LOG_ERR, "Error waiting for events!");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int
+ipmievd_sel_main(struct ipmi_intf * intf, int argc, char ** argv)
+{
+ struct ipmi_event_intf * eintf;
+
+ eintf = ipmi_event_intf_load("sel");
+ if (eintf == NULL) {
+ lprintf(LOG_ERR, "Unable to load event interface");
+ return -1;
+ }
+
+ eintf->intf = intf;
+
+ if (intf->session != NULL) {
+ snprintf(eintf->prefix,
+ strlen((const char *)intf->session->hostname) + 3,
+ "%s: ", intf->session->hostname);
+ }
+
+ return ipmievd_main(eintf, argc, argv);
+}
+
+int
+ipmievd_open_main(struct ipmi_intf * intf, int argc, char ** argv)
+{
+ struct ipmi_event_intf * eintf;
+
+ /* only one interface works for this */
+ if (strncmp(intf->name, "open", 4) != 0) {
+ lprintf(LOG_ERR, "Invalid Interface for OpenIPMI Event Handler: %s", intf->name);
+ return -1;
+ }
+
+ eintf = ipmi_event_intf_load("open");
+ if (eintf == NULL) {
+ lprintf(LOG_ERR, "Unable to load event interface");
+ return -1;
+ }
+
+ eintf->intf = intf;
+
+ return ipmievd_main(eintf, argc, argv);
+}
+
+struct ipmi_cmd ipmievd_cmd_list[] = {
+#ifdef IPMI_INTF_OPEN
+ { ipmievd_open_main, "open", "Use OpenIPMI for asyncronous notification of events" },
+#endif
+ { ipmievd_sel_main, "sel", "Poll SEL for notification of events" },
+ { NULL }
+};
+
+int main(int argc, char ** argv)
+{
+ int rc;
+
+ rc = ipmi_main(argc, argv, ipmievd_cmd_list, NULL);
+
+ if (rc < 0)
+ exit(EXIT_FAILURE);
+ else
+ exit(EXIT_SUCCESS);
+}
diff --git a/src/ipmishell.c b/src/ipmishell.c
new file mode 100644
index 0000000..4eebcd8
--- /dev/null
+++ b/src/ipmishell.c
@@ -0,0 +1,510 @@
+/*
+ * Copyright (c) 2003, 2004 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <ipmitool/helper.h>
+#include <ipmitool/log.h>
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_intf.h>
+#include <ipmitool/ipmi_session.h>
+#include <ipmitool/ipmi_main.h>
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define EXEC_BUF_SIZE 2048
+#define EXEC_ARG_SIZE 64
+#define MAX_PORT 65535
+
+extern const struct valstr ipmi_privlvl_vals[];
+extern const struct valstr ipmi_authtype_session_vals[];
+
+#ifdef HAVE_READLINE
+
+/* avoid warnings errors due to non-ANSI type declarations in readline.h */
+#define _FUNCTION_DEF
+#define USE_VARARGS
+#define PREFER_STDARG
+
+#include <readline/readline.h>
+#include <readline/history.h>
+#define RL_PROMPT "ipmitool> "
+#define RL_TIMEOUT 30
+
+static struct ipmi_intf * shell_intf;
+
+/* This function attempts to keep lan sessions active
+ * so they do not time out waiting for user input. The
+ * readline timeout is set to 1 second but lan session
+ * timeout is ~60 seconds.
+ */
+static int rl_event_keepalive(void)
+{
+ static int internal_timer = 0;
+
+ if (shell_intf == NULL)
+ return -1;
+ if (shell_intf->keepalive == NULL)
+ return 0;
+#if defined (RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0402
+ if (internal_timer++ < RL_TIMEOUT)
+#else
+ /* In readline < 4.2 keyboard timeout hardcoded to 0.1 second */
+ if (internal_timer++ < RL_TIMEOUT * 10)
+#endif
+ return 0;
+
+ internal_timer = 0;
+ shell_intf->keepalive(shell_intf);
+
+ return 0;
+}
+
+int ipmi_shell_main(struct ipmi_intf * intf, int argc, char ** argv)
+{
+ char *ptr, *pbuf, **ap, *__argv[EXEC_ARG_SIZE];
+ int __argc, rc=0;
+
+ rl_readline_name = "ipmitool";
+
+ /* this essentially disables command completion
+ * until its implemented right, otherwise we get
+ * the current directory contents... */
+ rl_bind_key('\t', rl_insert);
+
+ if (intf->keepalive) {
+ /* hook to keep lan sessions active */
+ shell_intf = intf;
+ rl_event_hook = rl_event_keepalive;
+#if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0402
+ /* There is a bug in readline 4.2 and later (at least on FreeBSD and NetBSD):
+ * timeout equal or greater than 1 second causes an infinite loop. */
+ rl_set_keyboard_input_timeout(1000 * 1000 - 1);
+#endif
+ }
+
+ while ((pbuf = (char *)readline(RL_PROMPT)) != NULL) {
+ if (strlen(pbuf) == 0) {
+ free(pbuf);
+ pbuf = NULL;
+ continue;
+ }
+ if (strncmp(pbuf, "quit", 4) == 0 ||
+ strncmp(pbuf, "exit", 4) == 0) {
+ free(pbuf);
+ pbuf = NULL;
+ return 0;
+ }
+ if (strncmp(pbuf, "help", 4) == 0 ||
+ strncmp(pbuf, "?", 1) == 0) {
+ ipmi_cmd_print(intf->cmdlist);
+ free(pbuf);
+ pbuf = NULL;
+ continue;
+ }
+
+ /* for the all-important up arrow :) */
+ add_history(pbuf);
+
+ /* change "" and '' with spaces in the middle to ~ */
+ ptr = pbuf;
+ while (*ptr != '\0') {
+ if (*ptr == '"') {
+ ptr++;
+ while (*ptr != '"' && *ptr != '\0') {
+ if (isspace((int)*ptr))
+ *ptr = '~';
+ ptr++;
+ }
+ }
+ if (*ptr == '\'') {
+ ptr++;
+ while (*ptr != '\'' && *ptr != '\0') {
+ if (isspace((int)*ptr))
+ *ptr = '~';
+ ptr++;
+ }
+ }
+ ptr++;
+ }
+
+ __argc = 0;
+ ap = __argv;
+
+ for (*ap = strtok(pbuf, " \t");
+ *ap != NULL;
+ *ap = strtok(NULL, " \t")) {
+ __argc++;
+
+ ptr = *ap;
+ if (*ptr == '\'') {
+ memmove(ptr, ptr+1, strlen(ptr));
+ while (*ptr != '\'' && *ptr != '\0') {
+ if (*ptr == '~')
+ *ptr = ' ';
+ ptr++;
+ }
+ *ptr = '\0';
+ }
+ if (*ptr == '"') {
+ memmove(ptr, ptr+1, strlen(ptr));
+ while (*ptr != '"' && *ptr != '\0') {
+ if (*ptr == '~')
+ *ptr = ' ';
+ ptr++;
+ }
+ *ptr = '\0';
+ }
+
+ if (**ap != '\0') {
+ if (++ap >= &__argv[EXEC_ARG_SIZE])
+ break;
+ }
+ }
+
+ if (__argc && __argv[0])
+ rc = ipmi_cmd_run(intf,
+ __argv[0],
+ __argc-1,
+ &(__argv[1]));
+
+ free(pbuf);
+ pbuf = NULL;
+ }
+ printf("\n");
+ return rc;
+}
+
+#else /* HAVE_READLINE */
+
+int
+ipmi_shell_main(struct ipmi_intf * intf, int argc, char ** argv)
+{
+ lprintf(LOG_ERR, "Compiled without readline, shell is disabled");
+ return -1;
+}
+
+#endif /* HAVE_READLINE */
+
+int ipmi_echo_main(struct ipmi_intf * intf, int argc, char ** argv)
+{
+ int i;
+
+ for (i=0; i<argc; i++) {
+ printf("%s ", argv[i]);
+ }
+ printf("\n");
+
+ return 0;
+}
+
+static void
+ipmi_set_usage(void)
+{
+ lprintf(LOG_NOTICE, "Usage: set <option> <value>\n");
+ lprintf(LOG_NOTICE, "Options are:");
+ lprintf(LOG_NOTICE, " hostname <host> Session hostname");
+ lprintf(LOG_NOTICE, " username <user> Session username");
+ lprintf(LOG_NOTICE, " password <pass> Session password");
+ lprintf(LOG_NOTICE, " privlvl <level> Session privilege level force");
+ lprintf(LOG_NOTICE, " authtype <type> Authentication type force");
+ lprintf(LOG_NOTICE, " localaddr <addr> Local IPMB address");
+ lprintf(LOG_NOTICE, " targetaddr <addr> Remote target IPMB address");
+ lprintf(LOG_NOTICE, " port <port> Remote RMCP port");
+ lprintf(LOG_NOTICE, " csv [level] enable output in comma separated format");
+ lprintf(LOG_NOTICE, " verbose [level] Verbose level");
+ lprintf(LOG_NOTICE, "");
+}
+
+int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv)
+{
+ if (argc == 0 || strncmp(argv[0], "help", 4) == 0) {
+ ipmi_set_usage();
+ return -1;
+ }
+
+ /* these options can have no arguments */
+ if (strncmp(argv[0], "verbose", 7) == 0) {
+ if (argc > 1) {
+ if (str2int(argv[1], &verbose) != 0) {
+ lprintf(LOG_ERR,
+ "Given verbose '%s' argument is invalid.",
+ argv[1]);
+ return (-1);
+ }
+ } else {
+ verbose = verbose + 1;
+ }
+ return 0;
+ }
+ if (strncmp(argv[0], "csv", 3) == 0) {
+ if (argc > 1) {
+ if (str2int(argv[1], &csv_output) != 0) {
+ lprintf(LOG_ERR,
+ "Given csv '%s' argument is invalid.",
+ argv[1]);
+ return (-1);
+ }
+ } else {
+ csv_output = 1;
+ }
+ return 0;
+ }
+
+ /* the rest need an argument */
+ if (argc == 1) {
+ ipmi_set_usage();
+ return -1;
+ }
+
+ if (strncmp(argv[0], "host", 4) == 0 ||
+ strncmp(argv[0], "hostname", 8) == 0) {
+ ipmi_intf_session_set_hostname(intf, argv[1]);
+ if (intf->session == NULL) {
+ lprintf(LOG_ERR, "Failed to set session hostname.");
+ return (-1);
+ }
+ printf("Set session hostname to %s\n",
+ intf->session->hostname);
+ }
+ else if (strncmp(argv[0], "user", 4) == 0 ||
+ strncmp(argv[0], "username", 8) == 0) {
+ ipmi_intf_session_set_username(intf, argv[1]);
+ if (intf->session == NULL) {
+ lprintf(LOG_ERR, "Failed to set session username.");
+ return (-1);
+ }
+ printf("Set session username to %s\n",
+ intf->session->username);
+ }
+ else if (strncmp(argv[0], "pass", 4) == 0 ||
+ strncmp(argv[0], "password", 8) == 0) {
+ ipmi_intf_session_set_password(intf, argv[1]);
+ if (intf->session == NULL) {
+ lprintf(LOG_ERR, "Failed to set session password.");
+ return (-1);
+ }
+ printf("Set session password\n");
+ }
+ else if (strncmp(argv[0], "authtype", 8) == 0) {
+ int authtype;
+ authtype = str2val(argv[1], ipmi_authtype_session_vals);
+ if (authtype == 0xFF) {
+ lprintf(LOG_ERR, "Invalid authtype: %s",
+ argv[1]);
+ return (-1);
+ }
+ ipmi_intf_session_set_authtype(intf, authtype);
+ if (intf->session == NULL) {
+ lprintf(LOG_ERR, "Failed to set session authtype.");
+ return (-1);
+ }
+ printf("Set session authtype to %s\n",
+ val2str(intf->session->authtype_set,
+ ipmi_authtype_session_vals));
+ }
+ else if (strncmp(argv[0], "privlvl", 7) == 0) {
+ int privlvl;
+ privlvl = str2val(argv[1], ipmi_privlvl_vals);
+ if (privlvl == 0xFF) {
+ lprintf(LOG_ERR, "Invalid privilege level: %s",
+ argv[1]);
+ return (-1);
+ }
+ ipmi_intf_session_set_privlvl(intf, privlvl);
+ if (intf->session == NULL) {
+ lprintf(LOG_ERR,
+ "Failed to set session privilege level.");
+ return (-1);
+ }
+ printf("Set session privilege level to %s\n",
+ val2str(intf->session->privlvl,
+ ipmi_privlvl_vals));
+ }
+ else if (strncmp(argv[0], "port", 4) == 0) {
+ int port = 0;
+ if (str2int(argv[1], &port) != 0 || port > MAX_PORT) {
+ lprintf(LOG_ERR, "Given port '%s' is invalid.",
+ argv[1]);
+ return (-1);
+ }
+ ipmi_intf_session_set_port(intf, port);
+ if (intf->session == NULL) {
+ lprintf(LOG_ERR, "Failed to set session port.");
+ return (-1);
+ }
+ printf("Set session port to %d\n", intf->session->port);
+ }
+ else if (strncmp(argv[0], "localaddr", 9) == 0) {
+ uint8_t my_addr = 0;
+ if (str2uchar(argv[1], &my_addr) != 0) {
+ lprintf(LOG_ERR, "Given localaddr '%s' is invalid.",
+ argv[1]);
+ return (-1);
+ }
+ intf->my_addr = my_addr;
+ printf("Set local IPMB address to 0x%02x\n", intf->my_addr);
+ }
+ else if (strncmp(argv[0], "targetaddr", 10) == 0) {
+ uint8_t target_addr = 0;
+ if (str2uchar(argv[1], &target_addr) != 0) {
+ lprintf(LOG_ERR, "Given targetaddr '%s' is invalid.",
+ argv[1]);
+ return (-1);
+ }
+ intf->target_addr = target_addr;
+ printf("Set remote IPMB address to 0x%02x\n", intf->target_addr);
+ }
+ else {
+ ipmi_set_usage();
+ return -1;
+ }
+ return 0;
+}
+
+int ipmi_exec_main(struct ipmi_intf * intf, int argc, char ** argv)
+{
+ FILE * fp;
+ char buf[EXEC_BUF_SIZE];
+ char * ptr, * tok, * ret, * tmp;
+ int __argc, i, r;
+ char * __argv[EXEC_ARG_SIZE];
+ int rc=0;
+
+ if (argc < 1) {
+ lprintf(LOG_ERR, "Usage: exec <filename>");
+ return -1;
+ }
+
+ fp = ipmi_open_file_read(argv[0]);
+ if (fp == NULL)
+ return -1;
+
+ while (feof(fp) == 0) {
+ ret = fgets(buf, EXEC_BUF_SIZE, fp);
+ if (ret == NULL)
+ continue;
+
+ /* clip off optional comment tail indicated by # */
+ ptr = strchr(buf, '#');
+ if (ptr)
+ *ptr = '\0';
+ else
+ ptr = buf + strlen(buf);
+
+ /* change "" and '' with spaces in the middle to ~ */
+ ptr = buf;
+ while (*ptr != '\0') {
+ if (*ptr == '"') {
+ ptr++;
+ while (*ptr != '"' && *ptr != '\0') {
+ if (isspace((int)*ptr))
+ *ptr = '~';
+ ptr++;
+ }
+ }
+ if (*ptr == '\'') {
+ ptr++;
+ while (*ptr != '\'' && *ptr != '\0') {
+ if (isspace((int)*ptr))
+ *ptr = '~';
+ ptr++;
+ }
+ }
+ ptr++;
+ }
+
+ /* clip off trailing and leading whitespace */
+ ptr--;
+ while (isspace((int)*ptr) && ptr >= buf)
+ *ptr-- = '\0';
+ ptr = buf;
+ while (isspace((int)*ptr))
+ ptr++;
+ if (strlen(ptr) == 0)
+ continue;
+
+ /* parse it and make argument list */
+ __argc = 0;
+ for (tok = strtok(ptr, " "); tok != NULL; tok = strtok(NULL, " ")) {
+ if (__argc < EXEC_ARG_SIZE) {
+ __argv[__argc++] = strdup(tok);
+ if (__argv[__argc-1] == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return -1;
+ }
+ tmp = __argv[__argc-1];
+ if (*tmp == '\'') {
+ memmove(tmp, tmp+1, strlen(tmp));
+ while (*tmp != '\'' && *tmp != '\0') {
+ if (*tmp == '~')
+ *tmp = ' ';
+ tmp++;
+ }
+ *tmp = '\0';
+ }
+ if (*tmp == '"') {
+ memmove(tmp, tmp+1, strlen(tmp));
+ while (*tmp != '"' && *tmp != '\0') {
+ if (*tmp == '~')
+ *tmp = ' ';
+ tmp++;
+ }
+ *tmp = '\0';
+ }
+ }
+ }
+
+ /* now run the command, save the result if not successful */
+ r = ipmi_cmd_run(intf, __argv[0], __argc-1, &(__argv[1]));
+ if (r != 0)
+ rc = r;
+
+ /* free argument list */
+ for (i=0; i<__argc; i++) {
+ if (__argv[i] != NULL) {
+ free(__argv[i]);
+ __argv[i] = NULL;
+ }
+ }
+ }
+
+ fclose(fp);
+ return rc;
+}
diff --git a/src/ipmitool.c b/src/ipmitool.c
new file mode 100644
index 0000000..6230e5c
--- /dev/null
+++ b/src/ipmitool.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_intf.h>
+#include <ipmitool/ipmi_main.h>
+
+#include <ipmitool/ipmi_sdr.h>
+#include <ipmitool/ipmi_gendev.h>
+#include <ipmitool/ipmi_sel.h>
+#include <ipmitool/ipmi_fru.h>
+#include <ipmitool/ipmi_sol.h>
+#include <ipmitool/ipmi_isol.h>
+#include <ipmitool/ipmi_tsol.h>
+#include <ipmitool/ipmi_lanp.h>
+#include <ipmitool/ipmi_chassis.h>
+#include <ipmitool/ipmi_mc.h>
+#include <ipmitool/ipmi_sensor.h>
+#include <ipmitool/ipmi_channel.h>
+#include <ipmitool/ipmi_session.h>
+#include <ipmitool/ipmi_event.h>
+#include <ipmitool/ipmi_user.h>
+#include <ipmitool/ipmi_raw.h>
+#include <ipmitool/ipmi_pef.h>
+#include <ipmitool/ipmi_oem.h>
+#include <ipmitool/ipmi_sunoem.h>
+#include <ipmitool/ipmi_fwum.h>
+#include <ipmitool/ipmi_picmg.h>
+#include <ipmitool/ipmi_kontronoem.h>
+#include <ipmitool/ipmi_firewall.h>
+#include <ipmitool/ipmi_hpmfwupg.h>
+#include <ipmitool/ipmi_delloem.h>
+#include <ipmitool/ipmi_ekanalyzer.h>
+#include <ipmitool/ipmi_ime.h>
+#include <ipmitool/ipmi_dcmi.h>
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_READLINE
+extern int ipmi_shell_main(struct ipmi_intf * intf, int argc, char ** argv);
+#endif
+extern int ipmi_echo_main(struct ipmi_intf * intf, int argc, char ** argv);
+extern int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv);
+extern int ipmi_exec_main(struct ipmi_intf * intf, int argc, char ** argv);
+
+
+int csv_output = 0;
+int verbose = 0;
+
+struct ipmi_cmd ipmitool_cmd_list[] = {
+ { ipmi_raw_main, "raw", "Send a RAW IPMI request and print response" },
+ { ipmi_rawi2c_main, "i2c", "Send an I2C Master Write-Read command and print response" },
+ { ipmi_rawspd_main, "spd", "Print SPD info from remote I2C device" },
+ { ipmi_lanp_main, "lan", "Configure LAN Channels" },
+ { ipmi_chassis_main, "chassis", "Get chassis status and set power state" },
+ { ipmi_power_main, "power", "Shortcut to chassis power commands" },
+ { ipmi_event_main, "event", "Send pre-defined events to MC" },
+ { ipmi_mc_main, "mc", "Management Controller status and global enables" },
+ { ipmi_mc_main, "bmc", NULL }, /* for backwards compatibility */
+ { ipmi_sdr_main, "sdr", "Print Sensor Data Repository entries and readings" },
+ { ipmi_sensor_main, "sensor", "Print detailed sensor information" },
+ { ipmi_fru_main, "fru", "Print built-in FRU and scan SDR for FRU locators" },
+ { ipmi_gendev_main, "gendev", "Read/Write Device associated with Generic Device locators sdr" },
+ { ipmi_sel_main, "sel", "Print System Event Log (SEL)" },
+ { ipmi_pef_main, "pef", "Configure Platform Event Filtering (PEF)" },
+ { ipmi_sol_main, "sol", "Configure and connect IPMIv2.0 Serial-over-LAN" },
+ { ipmi_tsol_main, "tsol", "Configure and connect with Tyan IPMIv1.5 Serial-over-LAN" },
+ { ipmi_isol_main, "isol", "Configure IPMIv1.5 Serial-over-LAN" },
+ { ipmi_user_main, "user", "Configure Management Controller users" },
+ { ipmi_channel_main, "channel", "Configure Management Controller channels" },
+ { ipmi_session_main, "session", "Print session information" },
+ { ipmi_dcmi_main, "dcmi", "Data Center Management Interface"},
+ { ipmi_sunoem_main, "sunoem", "OEM Commands for Sun servers" },
+ { ipmi_kontronoem_main, "kontronoem", "OEM Commands for Kontron devices"},
+ { ipmi_picmg_main, "picmg", "Run a PICMG/ATCA extended cmd"},
+ { ipmi_fwum_main, "fwum", "Update IPMC using Kontron OEM Firmware Update Manager" },
+ { ipmi_firewall_main,"firewall","Configure Firmware Firewall" },
+ { ipmi_delloem_main, "delloem", "OEM Commands for Dell systems" },
+#ifdef HAVE_READLINE
+ { ipmi_shell_main, "shell", "Launch interactive IPMI shell" },
+#endif
+ { ipmi_exec_main, "exec", "Run list of commands from file" },
+ { ipmi_set_main, "set", "Set runtime variable for shell and exec" },
+ { ipmi_echo_main, "echo", NULL }, /* for echoing lines to stdout in scripts */
+ { ipmi_hpmfwupg_main,"hpm", "Update HPM components using PICMG HPM.1 file"},
+ { ipmi_ekanalyzer_main,"ekanalyzer", "run FRU-Ekeying analyzer using FRU files"},
+ { ipmi_ime_main, "ime", "Update Intel Manageability Engine Firmware"},
+ { NULL },
+};
+
+int
+main(int argc, char ** argv)
+{
+ int rc;
+
+ rc = ipmi_main(argc, argv, ipmitool_cmd_list, NULL);
+
+ if (rc < 0)
+ exit(EXIT_FAILURE);
+ else
+ exit(EXIT_SUCCESS);
+}
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
new file mode 100644
index 0000000..19b5f11
--- /dev/null
+++ b/src/plugins/Makefile.am
@@ -0,0 +1,43 @@
+# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Sun Microsystems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = -I$(top_srcdir)/include
+
+SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@ @INTF_DUMMY@
+DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial dummy
+
+noinst_LTLIBRARIES = libintf.la
+libintf_la_SOURCES = ipmi_intf.c
+libintf_la_LDFLAGS = -export-dynamic
+libintf_la_LIBADD = @IPMITOOL_INTF_LIB@
+libintf_la_DEPENDENCIES = @IPMITOOL_INTF_LIB@
+
diff --git a/src/plugins/Makefile.in b/src/plugins/Makefile.in
new file mode 100644
index 0000000..7cd39ca
--- /dev/null
+++ b/src/plugins/Makefile.in
@@ -0,0 +1,695 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 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.
+
+# 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@
+
+# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Sun Microsystems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+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@
+subdir = src/plugins
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+am_libintf_la_OBJECTS = ipmi_intf.lo
+libintf_la_OBJECTS = $(am_libintf_la_OBJECTS)
+libintf_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libintf_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+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 = $(libintf_la_SOURCES)
+DIST_SOURCES = $(libintf_la_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+ARCH = @ARCH@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASEDIR = @BASEDIR@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTRO = @DISTRO@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTF_BMC = @INTF_BMC@
+INTF_BMC_LIB = @INTF_BMC_LIB@
+INTF_DUMMY = @INTF_DUMMY@
+INTF_DUMMY_LIB = @INTF_DUMMY_LIB@
+INTF_FREE = @INTF_FREE@
+INTF_FREE_LIB = @INTF_FREE_LIB@
+INTF_IMB = @INTF_IMB@
+INTF_IMB_LIB = @INTF_IMB_LIB@
+INTF_LAN = @INTF_LAN@
+INTF_LANPLUS = @INTF_LANPLUS@
+INTF_LANPLUS_LIB = @INTF_LANPLUS_LIB@
+INTF_LAN_LIB = @INTF_LAN_LIB@
+INTF_LIPMI = @INTF_LIPMI@
+INTF_LIPMI_LIB = @INTF_LIPMI_LIB@
+INTF_OPEN = @INTF_OPEN@
+INTF_OPEN_LIB = @INTF_OPEN_LIB@
+INTF_SERIAL = @INTF_SERIAL@
+INTF_SERIAL_LIB = @INTF_SERIAL_LIB@
+IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OS = @OS@
+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@
+POW_LIB = @POW_LIB@
+PSTAMP = @PSTAMP@
+RANLIB = @RANLIB@
+RPMBUILD = @RPMBUILD@
+RPM_RELEASE = @RPM_RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_configure_args = @ac_configure_args@
+ac_ct_AR = @ac_ct_AR@
+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@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+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@
+MAINTAINERCLEANFILES = Makefile.in
+INCLUDES = -I$(top_srcdir)/include
+SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@ @INTF_DUMMY@
+DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial dummy
+noinst_LTLIBRARIES = libintf.la
+libintf_la_SOURCES = ipmi_intf.c
+libintf_la_LDFLAGS = -export-dynamic
+libintf_la_LIBADD = @IPMITOOL_INTF_LIB@
+libintf_la_DEPENDENCIES = @IPMITOOL_INTF_LIB@
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(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) --foreign src/plugins/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/plugins/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: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libintf.la: $(libintf_la_OBJECTS) $(libintf_la_DEPENDENCIES) $(EXTRA_libintf_la_DEPENDENCIES)
+ $(libintf_la_LINK) $(libintf_la_OBJECTS) $(libintf_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_intf.Plo@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
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+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: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ 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: ctags-recursive $(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
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES)
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ 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:
+
+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."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic clean-libtool \
+ clean-noinstLTLIBRARIES ctags ctags-recursive 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-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am
+
+
+# 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:
diff --git a/src/plugins/bmc/Makefile.am b/src/plugins/bmc/Makefile.am
new file mode 100644
index 0000000..66080d6
--- /dev/null
+++ b/src/plugins/bmc/Makefile.am
@@ -0,0 +1,41 @@
+# Copyright (c) 2004 Sun Microsystems, Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Sun Microsystems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = -I$(top_srcdir)/include
+
+EXTRA_LTLIBRARIES = libintf_bmc.la
+noinst_LTLIBRARIES = @INTF_BMC_LIB@
+libintf_bmc_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_bmc_la_SOURCES = \
+ bmc.c bmc.h \
+ bmc_intf.h
+
diff --git a/src/plugins/bmc/Makefile.in b/src/plugins/bmc/Makefile.in
new file mode 100644
index 0000000..0b67a01
--- /dev/null
+++ b/src/plugins/bmc/Makefile.in
@@ -0,0 +1,541 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 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.
+
+# 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@
+
+# Copyright (c) 2004 Sun Microsystems, Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Sun Microsystems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+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@
+subdir = src/plugins/bmc
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libintf_bmc_la_DEPENDENCIES = $(top_builddir)/lib/libipmitool.la
+am_libintf_bmc_la_OBJECTS = bmc.lo
+libintf_bmc_la_OBJECTS = $(am_libintf_bmc_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+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 = $(libintf_bmc_la_SOURCES)
+DIST_SOURCES = $(libintf_bmc_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+ARCH = @ARCH@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASEDIR = @BASEDIR@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTRO = @DISTRO@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTF_BMC = @INTF_BMC@
+INTF_BMC_LIB = @INTF_BMC_LIB@
+INTF_DUMMY = @INTF_DUMMY@
+INTF_DUMMY_LIB = @INTF_DUMMY_LIB@
+INTF_FREE = @INTF_FREE@
+INTF_FREE_LIB = @INTF_FREE_LIB@
+INTF_IMB = @INTF_IMB@
+INTF_IMB_LIB = @INTF_IMB_LIB@
+INTF_LAN = @INTF_LAN@
+INTF_LANPLUS = @INTF_LANPLUS@
+INTF_LANPLUS_LIB = @INTF_LANPLUS_LIB@
+INTF_LAN_LIB = @INTF_LAN_LIB@
+INTF_LIPMI = @INTF_LIPMI@
+INTF_LIPMI_LIB = @INTF_LIPMI_LIB@
+INTF_OPEN = @INTF_OPEN@
+INTF_OPEN_LIB = @INTF_OPEN_LIB@
+INTF_SERIAL = @INTF_SERIAL@
+INTF_SERIAL_LIB = @INTF_SERIAL_LIB@
+IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OS = @OS@
+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@
+POW_LIB = @POW_LIB@
+PSTAMP = @PSTAMP@
+RANLIB = @RANLIB@
+RPMBUILD = @RPMBUILD@
+RPM_RELEASE = @RPM_RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_configure_args = @ac_configure_args@
+ac_ct_AR = @ac_ct_AR@
+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@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+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@
+MAINTAINERCLEANFILES = Makefile.in
+INCLUDES = -I$(top_srcdir)/include
+EXTRA_LTLIBRARIES = libintf_bmc.la
+noinst_LTLIBRARIES = @INTF_BMC_LIB@
+libintf_bmc_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_bmc_la_SOURCES = \
+ bmc.c bmc.h \
+ bmc_intf.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(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) --foreign src/plugins/bmc/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/plugins/bmc/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: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libintf_bmc.la: $(libintf_bmc_la_OBJECTS) $(libintf_bmc_la_DEPENDENCIES) $(EXTRA_libintf_bmc_la_DEPENDENCIES)
+ $(LINK) $(libintf_bmc_la_OBJECTS) $(libintf_bmc_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bmc.Plo@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 $(LTLIBRARIES)
+installdirs:
+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:
+ 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:
+
+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."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ 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-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:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES 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-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
+
+
+# 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:
diff --git a/src/plugins/bmc/bmc.c b/src/plugins/bmc/bmc.c
new file mode 100644
index 0000000..b88b077
--- /dev/null
+++ b/src/plugins/bmc/bmc.c
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2004 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+/*
+ * interface routines between ipmitool and the bmc kernel driver
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stropts.h>
+#include <stddef.h>
+#include <stropts.h>
+
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_intf.h>
+#include "bmc_intf.h"
+
+#include "bmc.h"
+
+static int curr_seq;
+static int bmc_method(int fd, int *if_type);
+struct ipmi_rs *(*sendrecv_fn)(struct ipmi_intf *, struct ipmi_rq *) = NULL;
+extern int verbose;
+
+static void dump_request(bmc_req_t *request);
+static void dump_response(bmc_rsp_t *response);
+static struct ipmi_rs *ipmi_bmc_send_cmd_ioctl(struct ipmi_intf *intf,
+ struct ipmi_rq *req);
+static struct ipmi_rs *ipmi_bmc_send_cmd_putmsg(struct ipmi_intf *intf,
+ struct ipmi_rq *req);
+
+#define MESSAGE_BUFSIZE 1024
+
+struct ipmi_intf ipmi_bmc_intf = {
+ name: "bmc",
+ desc: "IPMI v2.0 BMC interface",
+ open: ipmi_bmc_open,
+ close: ipmi_bmc_close,
+ sendrecv: ipmi_bmc_send_cmd};
+
+void
+ipmi_bmc_close(struct ipmi_intf *intf)
+{
+ if (intf && intf->fd >= 0)
+ close(intf->fd);
+
+ intf->opened = 0;
+ intf->manufacturer_id = IPMI_OEM_UNKNOWN;
+ intf->fd = -1;
+}
+
+int
+ipmi_bmc_open(struct ipmi_intf *intf)
+{
+ int method;
+
+ if (!intf)
+ return -1;
+
+ /* Open local device */
+ intf->fd = open(BMC_DEV, O_RDWR);
+
+ if (intf->fd <= 0) {
+ perror("Could not open bmc device");
+ return (-1);
+ }
+ curr_seq = 0;
+
+ intf->opened = 1;
+
+ if (bmc_method(intf->fd, &method) < 0) {
+ perror("Could not determine bmc messaging interface");
+ return (-1);
+ }
+
+ sendrecv_fn = (method == BMC_PUTMSG_METHOD) ?
+ ipmi_bmc_send_cmd_putmsg : ipmi_bmc_send_cmd_ioctl;
+
+ intf->manufacturer_id = ipmi_get_oem(intf);
+ return (intf->fd);
+}
+
+struct ipmi_rs *
+ipmi_bmc_send_cmd(struct ipmi_intf *intf, struct ipmi_rq *req)
+{
+ /* If not already opened open the device or network connection */
+ if (!intf->opened && intf->open && intf->open(intf) < 0)
+ return NULL;
+
+ /* sendrecv_fn cannot be NULL at this point */
+ return ((*sendrecv_fn)(intf, req));
+}
+
+static struct ipmi_rs *
+ipmi_bmc_send_cmd_ioctl(struct ipmi_intf *intf, struct ipmi_rq *req)
+{
+ struct strioctl istr;
+ static struct bmc_reqrsp reqrsp;
+ static struct ipmi_rs rsp;
+
+ memset(&reqrsp, 0, sizeof (reqrsp));
+ reqrsp.req.fn = req->msg.netfn;
+ reqrsp.req.lun = 0;
+ reqrsp.req.cmd = req->msg.cmd;
+ reqrsp.req.datalength = req->msg.data_len;
+ memcpy(reqrsp.req.data, req->msg.data, req->msg.data_len);
+ reqrsp.rsp.datalength = RECV_MAX_PAYLOAD_SIZE;
+
+ istr.ic_cmd = IOCTL_IPMI_KCS_ACTION;
+ istr.ic_timout = 0;
+ istr.ic_dp = (char *)&reqrsp;
+ istr.ic_len = sizeof (struct bmc_reqrsp);
+
+ if (verbose) {
+ printf("--\n");
+ dump_request(&reqrsp.req);
+ printf("--\n");
+ }
+
+ if (ioctl(intf->fd, I_STR, &istr) < 0) {
+ perror("BMC IOCTL: I_STR");
+ return (NULL);
+ }
+
+ if (verbose > 2) {
+ dump_response(&reqrsp.rsp);
+ printf("--\n");
+ }
+
+ memset(&rsp, 0, sizeof (struct ipmi_rs));
+ rsp.ccode = reqrsp.rsp.ccode;
+ rsp.data_len = reqrsp.rsp.datalength;
+
+ /* Decrement for sizeof lun, cmd and ccode */
+ rsp.data_len -= 3;
+
+ if (!rsp.ccode && (rsp.data_len > 0))
+ memcpy(rsp.data, reqrsp.rsp.data, rsp.data_len);
+
+ return (&rsp);
+}
+
+static struct ipmi_rs *
+ipmi_bmc_send_cmd_putmsg(struct ipmi_intf *intf, struct ipmi_rq *req)
+{
+ struct strbuf sb;
+ int flags = 0;
+ static uint32_t msg_seq = 0;
+
+ /*
+ * The length of the message structure is equal to the size of the
+ * bmc_req_t structure, PLUS any additional data space in excess of
+ * the data space already reserved in the data member + <n> for
+ * the rest of the members in the bmc_msg_t structure.
+ */
+ int msgsz = offsetof(bmc_msg_t, msg) + sizeof(bmc_req_t) +
+ ((req->msg.data_len > SEND_MAX_PAYLOAD_SIZE) ?
+ (req->msg.data_len - SEND_MAX_PAYLOAD_SIZE) : 0);
+ bmc_msg_t *msg = malloc(msgsz);
+ bmc_req_t *request = (bmc_req_t *)&msg->msg[0];
+ bmc_rsp_t *response;
+ static struct ipmi_rs rsp;
+ struct ipmi_rs *ret = NULL;
+
+ msg->m_type = BMC_MSG_REQUEST;
+ msg->m_id = msg_seq++;
+ request->fn = req->msg.netfn;
+ request->lun = 0;
+ request->cmd = req->msg.cmd;
+ request->datalength = req->msg.data_len;
+ memcpy(request->data, req->msg.data, req->msg.data_len);
+
+ sb.len = msgsz;
+ sb.buf = (unsigned char *)msg;
+
+ if (verbose) {
+ printf("--\n");
+ dump_request(request);
+ printf("--\n");
+ }
+
+ if (putmsg(intf->fd, NULL, &sb, 0) < 0) {
+ perror("BMC putmsg: ");
+ free(msg);
+ msg = NULL;
+ return (NULL);
+ }
+
+ free(msg);
+ msg = NULL;
+
+ sb.buf = malloc(MESSAGE_BUFSIZE);
+ sb.maxlen = MESSAGE_BUFSIZE;
+
+ if (getmsg(intf->fd, NULL, &sb, &flags) < 0) {
+ perror("BMC getmsg: ");
+ free(sb.buf);
+ sb.buf = NULL;
+ return (NULL);
+ }
+
+ msg = (bmc_msg_t *)sb.buf;
+
+ if (verbose > 3) {
+ printf("Got msg (id 0x%x) type 0x%x\n", msg->m_id, msg->m_type);
+ }
+
+
+ /* Did we get an error back from the stream? */
+ switch (msg->m_type) {
+
+ case BMC_MSG_RESPONSE:
+ response = (bmc_rsp_t *)&msg->msg[0];
+
+ if (verbose > 2) {
+ dump_response(response);
+ printf("--\n");
+ }
+
+ memset(&rsp, 0, sizeof (struct ipmi_rs));
+ rsp.ccode = response->ccode;
+ rsp.data_len = response->datalength;
+
+ if (!rsp.ccode && (rsp.data_len > 0))
+ memcpy(rsp.data, response->data, rsp.data_len);
+
+ ret = &rsp;
+ break;
+
+ case BMC_MSG_ERROR:
+ /* In case of an error, msg->msg[0] has the error code */
+ printf("bmc_send_cmd: %s\n", strerror(msg->msg[0]));
+ break;
+
+ }
+
+ free(sb.buf);
+ sb.buf = NULL;
+ return (ret);
+}
+
+/*
+ * Determine which interface to use. Returns the interface method
+ * to use.
+ */
+static int
+bmc_method(int fd, int *if_type)
+{
+ struct strioctl istr;
+ int retval = 0;
+ uint8_t method = BMC_PUTMSG_METHOD;
+
+ istr.ic_cmd = IOCTL_IPMI_INTERFACE_METHOD;
+ istr.ic_timout = 0;
+ istr.ic_dp = (uint8_t *)&method;
+ istr.ic_len = 1;
+
+ /*
+ * If the ioctl doesn't exist, we should get an EINVAL back.
+ * Bail out on any other error.
+ */
+ if (ioctl(fd, I_STR, &istr) < 0) {
+
+ if (errno != EINVAL)
+ retval = -1;
+ else
+ method = BMC_IOCTL_METHOD;
+ }
+
+ if (retval == 0)
+ *if_type = method;
+
+ return (retval);
+}
+
+static void
+dump_request(bmc_req_t *request)
+{
+ int i;
+
+ printf("BMC req.fn : 0x%x\n", request->fn);
+ printf("BMC req.lun : 0x%x\n", request->lun);
+ printf("BMC req.cmd : 0x%x\n", request->cmd);
+ printf("BMC req.datalength : 0x%x\n", request->datalength);
+ printf("BMC req.data : ");
+
+ if (request->datalength > 0) {
+ for (i = 0; i < request->datalength; i++)
+ printf("0x%x ", request->data[i]);
+ } else {
+ printf("<NONE>");
+ }
+ printf("\n");
+}
+
+static void
+dump_response(bmc_rsp_t *response)
+{
+ int i;
+
+ printf("BMC rsp.fn : 0x%x\n", response->fn);
+ printf("BMC rsp.lun : 0x%x\n", response->lun);
+ printf("BMC rsp.cmd : 0x%x\n", response->cmd);
+ printf("BMC rsp.ccode : 0x%x\n", response->ccode);
+ printf("BMC rsp.datalength : 0x%x\n", response->datalength);
+ printf("BMC rsp.data : ");
+
+ if (response->datalength > 0) {
+ for (i = 0; i < response->datalength; i++)
+ printf("0x%x ", response->data[i]);
+ } else {
+ printf("<NONE>");
+ }
+ printf("\n");
+}
diff --git a/src/plugins/bmc/bmc.h b/src/plugins/bmc/bmc.h
new file mode 100644
index 0000000..0138710
--- /dev/null
+++ b/src/plugins/bmc/bmc.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2004 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef _IPMI_BMC_H_
+#define _IPMI_BMC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <ipmitool/ipmi.h>
+
+#define BMC_DEV "/dev/bmc"
+
+struct ipmi_rs *ipmi_bmc_send_cmd(struct ipmi_intf *intf, struct ipmi_rq *req);
+int ipmi_bmc_open(struct ipmi_intf *intf);
+void ipmi_bmc_close(struct ipmi_intf *intf);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _IPMI_BMC_H_ */
diff --git a/src/plugins/bmc/bmc_intf.h b/src/plugins/bmc/bmc_intf.h
new file mode 100644
index 0000000..c73e4c1
--- /dev/null
+++ b/src/plugins/bmc/bmc_intf.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2004 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef _BMC_INTF_H
+#define _BMC_INTF_H
+
+#pragma ident "@(#)bmc_intf.h 1.2 05/03/07 SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BMC_SUCCESS 0x0
+#define BMC_FAILURE 0x1
+
+#define BMC_NETFN_CHASSIS 0x0
+#define BMC_NETFN_BRIDGE 0x2
+#define BMC_NETFN_SE 0x4
+#define BMC_NETFN_APP 0x6
+#define BMC_NETFN_FIRMWARE 0x8
+#define BMC_NETFN_STORAGE 0xa
+#define BMC_NETFN_TRANSPORT 0xc
+
+#define SEND_MAX_PAYLOAD_SIZE 34 /* MAX payload */
+#define RECV_MAX_PAYLOAD_SIZE 33 /* MAX payload */
+#define BMC_MIN_RESPONSE_SIZE 3
+#define BMC_MIN_REQUEST_SIZE 2
+#define BMC_MAX_RESPONSE_SIZE (BMC_MIN_RESPONSE_SIZE + RECV_MAX_PAYLOAD_SIZE)
+#define BMC_MAX_REQUEST_SIZE (BMC_MIN_REQUEST_SIZE + BMC_MAX_RESPONSE_SIZE)
+
+#define BUF_SIZE 256
+#define MAX_BUF_SIZE 256
+
+/*
+ * Useful macros
+ */
+#define FORM_NETFNLUN(net, lun) ((((net) << 2) | ((lun) & 0x3)))
+#define GET_NETFN(netfn) (((netfn) >> 2) & 0x3f)
+#define GET_LUN(netfn) (netfn & 0x3)
+#define RESP_NETFN(nflun) ((nflun) | 1)
+#define ISREQUEST(nl) (((nl) & 1) == 0) /* test for request */
+#define ISRESPONSE(nl) (((nl) & 1) == 1) /* test for response */
+
+
+/* for checking BMC specific stuff */
+#define BMC_GET_DEVICE_ID 0x1 /* GET DEVICE ID COMMAND */
+#define BMC_IPMI_15_VER 0x51 /* IPMI 1.5 definion */
+
+/* BMC Completion Code and OEM Completion Code */
+#define BMC_IPMI_UNSPECIFIC_ERROR 0xFF /* Unspecific Error */
+#define BMC_IPMI_INVALID_COMMAND 0xC1 /* Invalid Command */
+#define BMC_IPMI_COMMAND_TIMEOUT 0xC3 /* Command Timeout */
+#define BMC_IPMI_DATA_LENGTH_EXCEED 0xC8 /* DataLength exceeded limit */
+#define BMC_IPMI_OEM_FAILURE_SENDBMC 0x7E /* Cannot send BMC req */
+
+
+#define IOCTL_IPMI_KCS_ACTION 0x01
+#define IOCTL_IPMI_INTERFACE_METHOD 0x02
+
+/* Interface methods returned from IOCTL_IPMI_INTERFACE_METHOD ioctl: */
+
+#define BMC_IOCTL_METHOD 0 /* Not returned from ioctl, */
+ /* but can be used by */
+ /* applications that want to */
+ /* compare against an */
+ /* alternative method. */
+#define BMC_PUTMSG_METHOD 1
+
+/*
+ * bmc_req_t is the data structure to send
+ * request packet from applications to the driver
+ * module.
+ *
+ * the request pkt is mainly for KCS-interface-BMC
+ * messages. Since the system interface is session-less
+ * connections, the packet won't have any session
+ * information.
+ *
+ * the data payload will be 2 bytes less than max
+ * BMC supported packet size.
+ * the address of the responder is always BMC and so
+ * rsSa field is not required.
+ */
+typedef struct bmc_req {
+ uint8_t fn; /* netFn for command */
+ uint8_t lun; /* logical unit on responder */
+ uint8_t cmd; /* command */
+ uint8_t datalength; /* length of following data */
+ uint8_t data[SEND_MAX_PAYLOAD_SIZE]; /* request data */
+} bmc_req_t;
+
+/*
+ * bmc_rsp_t is the data structure to send
+ * respond packet from applications to the driver
+ * module.
+ *
+ * the respond pkt is mainly for KCS-interface-BMC
+ * messages. Since the system interface is session-less
+ * connections, the packet won't have any session
+ * information.
+ *
+ * the data payload will be 2 bytes less than max
+ * BMC supported packet size.
+ */
+typedef struct bmc_rsp {
+ uint8_t fn; /* netFn for command */
+ uint8_t lun; /* logical unit on responder */
+ uint8_t cmd; /* command */
+ uint8_t ccode; /* completion code */
+ uint8_t datalength; /* Length */
+ uint8_t data[RECV_MAX_PAYLOAD_SIZE]; /* response */
+} bmc_rsp_t;
+
+/*
+ * the data structure for synchronous operation via ioctl (DEPRECATED)
+ */
+typedef struct bmc_reqrsp {
+ bmc_req_t req; /* request half */
+ bmc_rsp_t rsp; /* response half */
+} bmc_reqrsp_t;
+
+
+/*
+ * The new way of communicating with the bmc driver is to use putmsg() to
+ * send a message of a particular type. Replies from the driver also have this
+ * form, and will require the user to process the type field before examining
+ * the rest of the reply.
+ *
+ * The only change that must be observed when using the request and response
+ * structures defined above is as follows:
+ * when sending messages to the bmc driver, the data portion is now variable
+ * (the caller must allocate enough space to store the all structure members,
+ * plus enough space to cover the amount of data in the request), e.g.:
+ *
+ * bmc_msg_t *msg = malloc(offsetof(bmc_msg_t, msg) + sizeof(bmc_req_t) + 10);
+ *
+ * The amount allocated for the message is (# of bytes before the msg field) +
+ * the size of a bmc_req_t (which includes SEND_MAX_PAYLOAD_SIZE
+ * bytes in the data field), plus an additional 10 bytes for the data
+ * field (so the data field would occupy (SEND_MAX_PAYLOAD_SIZE + 10)
+ * bytes). The datalength member must reflect the amount of data in the
+ * request's data field (as was required when using the ioctl interface).
+ */
+typedef struct bmc_msg {
+ uint8_t m_type; /* Message type (see below) */
+ uint32_t m_id; /* Message ID */
+ uint8_t reserved[32];
+ uint8_t msg[1]; /* Variable length message data */
+} bmc_msg_t;
+
+
+/*
+ * An error response passed back from the bmc driver will have its m_id
+ * field set to BMC_UNKNOWN_MSG_ID if a message is sent to it that is not
+ * at least as large as a bmc_msg_t.
+ */
+#define BMC_UNKNOWN_MSG_ID ~((uint32_t)0)
+
+
+/*
+ * Possible values for the m_type field in bmc_msg_t:
+ */
+#define BMC_MSG_REQUEST 1 /* BMC request (as above, sent to the */
+ /* driver by the user), bmc_msg.msg */
+ /* begins with the bmc_req_t */
+ /* structure. */
+#define BMC_MSG_RESPONSE 2 /* BMC response (sent by the driver) */
+ /* bmc_msg.msg begins with the */
+ /* bmc_rsp_t structure. */
+#define BMC_MSG_ERROR 3 /* Error while processing a user msg */
+ /* msg[0] is the error code */
+ /* (interpret as an errno value) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BMC_INTF_H */
diff --git a/src/plugins/dummy/Makefile.am b/src/plugins/dummy/Makefile.am
new file mode 100644
index 0000000..8a53bbe
--- /dev/null
+++ b/src/plugins/dummy/Makefile.am
@@ -0,0 +1,8 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = -I$(top_srcdir)/include
+
+EXTRA_LTLIBRARIES = libintf_dummy.la
+noinst_LTLIBRARIES = @INTF_DUMMY_LIB@
+libintf_dummy_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_dummy_la_SOURCES = dummy.c
diff --git a/src/plugins/dummy/Makefile.in b/src/plugins/dummy/Makefile.in
new file mode 100644
index 0000000..944b2da
--- /dev/null
+++ b/src/plugins/dummy/Makefile.in
@@ -0,0 +1,508 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 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.
+
+# 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@
+
+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@
+subdir = src/plugins/dummy
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libintf_dummy_la_DEPENDENCIES = $(top_builddir)/lib/libipmitool.la
+am_libintf_dummy_la_OBJECTS = dummy.lo
+libintf_dummy_la_OBJECTS = $(am_libintf_dummy_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+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 = $(libintf_dummy_la_SOURCES)
+DIST_SOURCES = $(libintf_dummy_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+ARCH = @ARCH@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASEDIR = @BASEDIR@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTRO = @DISTRO@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTF_BMC = @INTF_BMC@
+INTF_BMC_LIB = @INTF_BMC_LIB@
+INTF_DUMMY = @INTF_DUMMY@
+INTF_DUMMY_LIB = @INTF_DUMMY_LIB@
+INTF_FREE = @INTF_FREE@
+INTF_FREE_LIB = @INTF_FREE_LIB@
+INTF_IMB = @INTF_IMB@
+INTF_IMB_LIB = @INTF_IMB_LIB@
+INTF_LAN = @INTF_LAN@
+INTF_LANPLUS = @INTF_LANPLUS@
+INTF_LANPLUS_LIB = @INTF_LANPLUS_LIB@
+INTF_LAN_LIB = @INTF_LAN_LIB@
+INTF_LIPMI = @INTF_LIPMI@
+INTF_LIPMI_LIB = @INTF_LIPMI_LIB@
+INTF_OPEN = @INTF_OPEN@
+INTF_OPEN_LIB = @INTF_OPEN_LIB@
+INTF_SERIAL = @INTF_SERIAL@
+INTF_SERIAL_LIB = @INTF_SERIAL_LIB@
+IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OS = @OS@
+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@
+POW_LIB = @POW_LIB@
+PSTAMP = @PSTAMP@
+RANLIB = @RANLIB@
+RPMBUILD = @RPMBUILD@
+RPM_RELEASE = @RPM_RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_configure_args = @ac_configure_args@
+ac_ct_AR = @ac_ct_AR@
+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@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+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@
+MAINTAINERCLEANFILES = Makefile.in
+INCLUDES = -I$(top_srcdir)/include
+EXTRA_LTLIBRARIES = libintf_dummy.la
+noinst_LTLIBRARIES = @INTF_DUMMY_LIB@
+libintf_dummy_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_dummy_la_SOURCES = dummy.c
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(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) --foreign src/plugins/dummy/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/plugins/dummy/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: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libintf_dummy.la: $(libintf_dummy_la_OBJECTS) $(libintf_dummy_la_DEPENDENCIES) $(EXTRA_libintf_dummy_la_DEPENDENCIES)
+ $(LINK) $(libintf_dummy_la_OBJECTS) $(libintf_dummy_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummy.Plo@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 $(LTLIBRARIES)
+installdirs:
+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:
+ 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:
+
+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."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ 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-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:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES 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-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
+
+
+# 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:
diff --git a/src/plugins/dummy/dummy.c b/src/plugins/dummy/dummy.c
new file mode 100644
index 0000000..eb2d086
--- /dev/null
+++ b/src/plugins/dummy/dummy.c
@@ -0,0 +1,286 @@
+/* Copyright (c) 2013 Zdenek Styblik, All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Zdenek Styblik or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * Zdenek Styblik SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * Zdenek Styblik BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF Zdenek Styblik HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_intf.h>
+#include <ipmitool/helper.h>
+#include <ipmitool/log.h>
+
+#include "dummy.h"
+
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+extern int verbose;
+
+/* data_read - read data from socket
+ *
+ * @data_ptr - pointer to memory where to store read data
+ * @data_len - how much to read from socket
+ *
+ * return 0 on success, otherwise (-1)
+ */
+int
+data_read(int fd, void *data_ptr, int data_len)
+{
+ int rc = 0;
+ int data_read = 0;
+ int data_total = 0;
+ int try = 1;
+ int errno_save = 0;
+ if (data_len < 0) {
+ return (-1);
+ }
+ while (data_total < data_len && try < 4) {
+ errno = 0;
+ /* TODO - add poll() */
+ data_read = read(fd, data_ptr, data_len);
+ errno_save = errno;
+ if (data_read > 0) {
+ data_total+= data_read;
+ }
+ if (errno_save != 0) {
+ if (errno_save == EINTR || errno_save == EAGAIN) {
+ try++;
+ sleep(2);
+ continue;
+ } else {
+ errno = errno_save;
+ perror("dummy failed on read(): ");
+ rc = (-1);
+ break;
+ }
+ }
+ }
+ if (try > 3 && data_total != data_len) {
+ rc = (-1);
+ }
+ return rc;
+}
+
+/* data_write - write data to the socket
+ *
+ * @data_ptr - ptr to data to send
+ * @data_len - how long is the data to send
+ *
+ * returns 0 on success, otherwise (-1)
+ */
+int
+data_write(int fd, void *data_ptr, int data_len)
+{
+ int rc = 0;
+ int data_written = 0;
+ int data_total = 0;
+ int try = 1;
+ int errno_save = 0;
+ if (data_len < 0) {
+ return (-1);
+ }
+ while (data_total < data_len && try < 4) {
+ errno = 0;
+ /* TODO - add poll() */
+ data_written = write(fd, data_ptr, data_len);
+ errno_save = errno;
+ if (data_read > 0) {
+ data_total+= data_written;
+ }
+ if (errno_save != 0) {
+ if (errno_save == EINTR || errno_save == EAGAIN) {
+ try++;
+ sleep(2);
+ continue;
+ } else {
+ errno = errno_save;
+ perror("dummy failed on read(): ");
+ rc = (-1);
+ break;
+ }
+ }
+ }
+ if (try > 3 && data_total != data_len) {
+ rc = (-1);
+ }
+ return rc;
+}
+
+/* ipmi_dummyipmi_close - send "BYE" and close socket
+ *
+ * @intf - ptr to initialize ipmi_intf struct
+ *
+ * returns void
+ */
+static void
+ipmi_dummyipmi_close(struct ipmi_intf *intf)
+{
+ struct dummy_rq req;
+ int data_total = 0;
+ int data_written = 0;
+ int try = 0;
+ if (intf->fd < 0) {
+ return;
+ }
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = 0x3f;
+ req.msg.cmd = 0xff;
+ if (data_write(intf->fd, &req, sizeof(req)) != 0) {
+ lprintf(LOG_ERR, "dummy failed to send 'BYE'");
+ }
+ close(intf->fd);
+ intf->fd = (-1);
+ intf->opened = 0;
+}
+
+/* ipmi_dummyipmi_open - open socket and prepare ipmi_intf struct
+ *
+ * @intf - ptr to ipmi_inf struct
+ *
+ * returns 0 on success, (-1) on error
+ */
+static int
+ipmi_dummyipmi_open(struct ipmi_intf *intf)
+{
+ struct sockaddr_un address;
+ int len;
+ int rc;
+
+ if (intf->opened == 1) {
+ return intf->fd;
+ }
+ intf->fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (intf->fd == (-1)) {
+ lprintf(LOG_ERR, "dummy failed on socket()");
+ return (-1);
+ }
+ address.sun_family = AF_UNIX;
+ strcpy(address.sun_path, DUMMY_SOCKET_PATH);
+ len = sizeof(address);
+ rc = connect(intf->fd, (struct sockaddr *)&address, len);
+ if (rc != 0) {
+ perror("dummy failed on connect(): ");
+ return (-1);
+ }
+ intf->opened = 1;
+ return intf->fd;
+}
+
+/* ipmi_dummyipmi_send_cmd - send IPMI payload and await reply
+ *
+ * @intf - ptr to initialized ipmi_intf struct
+ * @req - ptr to ipmi_rq struct to send
+ *
+ * return pointer to struct ipmi_rs OR NULL on error
+ */
+static struct ipmi_rs*
+ipmi_dummyipmi_send_cmd(struct ipmi_intf *intf, struct ipmi_rq *req)
+{
+ static struct ipmi_rs rsp;
+ struct dummy_rq req_dummy;
+ struct dummy_rs rsp_dummy;
+ if (intf == NULL || intf->fd < 0 || intf->opened != 1) {
+ lprintf(LOG_ERR, "dummy failed on intf check.");
+ return NULL;
+ }
+
+ memset(&req_dummy, 0, sizeof(req_dummy));
+ req_dummy.msg.netfn = req->msg.netfn;
+ req_dummy.msg.lun = req->msg.lun;
+ req_dummy.msg.cmd = req->msg.cmd;
+ req_dummy.msg.target_cmd = req->msg.target_cmd;
+ req_dummy.msg.data_len = req->msg.data_len;
+ req_dummy.msg.data = req->msg.data;
+ if (verbose) {
+ lprintf(LOG_NOTICE, ">>> IPMI req");
+ lprintf(LOG_NOTICE, "msg.data_len: %i",
+ req_dummy.msg.data_len);
+ lprintf(LOG_NOTICE, "msg.netfn: %x", req_dummy.msg.netfn);
+ lprintf(LOG_NOTICE, "msg.cmd: %x", req_dummy.msg.cmd);
+ lprintf(LOG_NOTICE, "msg.target_cmd: %x",
+ req_dummy.msg.target_cmd);
+ lprintf(LOG_NOTICE, "msg.lun: %x", req_dummy.msg.lun);
+ lprintf(LOG_NOTICE, ">>>");
+ }
+ if (data_write(intf->fd, &req_dummy,
+ sizeof(struct dummy_rq)) != 0) {
+ return NULL;
+ }
+ if (req->msg.data_len > 0) {
+ if (data_write(intf->fd, (uint8_t *)(req->msg.data),
+ req_dummy.msg.data_len) != 0) {
+ return NULL;
+ }
+ }
+
+ memset(&rsp_dummy, 0, sizeof(rsp_dummy));
+ if (data_read(intf->fd, &rsp_dummy, sizeof(struct dummy_rs)) != 0) {
+ return NULL;
+ }
+ if (rsp_dummy.data_len > 0) {
+ if (data_read(intf->fd, (uint8_t *)&rsp.data,
+ rsp_dummy.data_len) != 0) {
+ return NULL;
+ }
+ }
+ rsp.ccode = rsp_dummy.ccode;
+ rsp.data_len = rsp_dummy.data_len;
+ rsp.msg.netfn = rsp_dummy.msg.netfn;
+ rsp.msg.cmd = rsp_dummy.msg.cmd;
+ rsp.msg.seq = rsp_dummy.msg.seq;
+ rsp.msg.lun = rsp_dummy.msg.lun;
+ if (verbose) {
+ lprintf(LOG_NOTICE, "<<< IPMI rsp");
+ lprintf(LOG_NOTICE, "ccode: %x", rsp.ccode);
+ lprintf(LOG_NOTICE, "data_len: %i", rsp.data_len);
+ lprintf(LOG_NOTICE, "msg.netfn: %x", rsp.msg.netfn);
+ lprintf(LOG_NOTICE, "msg.cmd: %x", rsp.msg.cmd);
+ lprintf(LOG_NOTICE, "msg.seq: %x", rsp.msg.seq);
+ lprintf(LOG_NOTICE, "msg.lun: %x", rsp.msg.lun);
+ lprintf(LOG_NOTICE, "<<<");
+ }
+ return &rsp;
+}
+
+struct ipmi_intf ipmi_dummy_intf = {
+ name: "dummy",
+ desc: "Linux DummyIPMI Interface",
+ open: ipmi_dummyipmi_open,
+ close: ipmi_dummyipmi_close,
+ sendrecv: ipmi_dummyipmi_send_cmd,
+ my_addr: IPMI_BMC_SLAVE_ADDR,
+ target_addr: IPMI_BMC_SLAVE_ADDR,
+};
diff --git a/src/plugins/free/Makefile.am b/src/plugins/free/Makefile.am
new file mode 100644
index 0000000..028281f
--- /dev/null
+++ b/src/plugins/free/Makefile.am
@@ -0,0 +1,9 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = -I$(top_srcdir)/include
+
+EXTRA_LTLIBRARIES = libintf_free.la
+noinst_LTLIBRARIES = @INTF_FREE_LIB@
+libintf_free_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_free_la_SOURCES = free.c
+libintf_free_la_LDFLAGS = -lfreeipmi
diff --git a/src/plugins/free/Makefile.in b/src/plugins/free/Makefile.in
new file mode 100644
index 0000000..22d1938
--- /dev/null
+++ b/src/plugins/free/Makefile.in
@@ -0,0 +1,512 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 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.
+
+# 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@
+
+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@
+subdir = src/plugins/free
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libintf_free_la_DEPENDENCIES = $(top_builddir)/lib/libipmitool.la
+am_libintf_free_la_OBJECTS = free.lo
+libintf_free_la_OBJECTS = $(am_libintf_free_la_OBJECTS)
+libintf_free_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libintf_free_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+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 = $(libintf_free_la_SOURCES)
+DIST_SOURCES = $(libintf_free_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+ARCH = @ARCH@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASEDIR = @BASEDIR@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTRO = @DISTRO@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTF_BMC = @INTF_BMC@
+INTF_BMC_LIB = @INTF_BMC_LIB@
+INTF_DUMMY = @INTF_DUMMY@
+INTF_DUMMY_LIB = @INTF_DUMMY_LIB@
+INTF_FREE = @INTF_FREE@
+INTF_FREE_LIB = @INTF_FREE_LIB@
+INTF_IMB = @INTF_IMB@
+INTF_IMB_LIB = @INTF_IMB_LIB@
+INTF_LAN = @INTF_LAN@
+INTF_LANPLUS = @INTF_LANPLUS@
+INTF_LANPLUS_LIB = @INTF_LANPLUS_LIB@
+INTF_LAN_LIB = @INTF_LAN_LIB@
+INTF_LIPMI = @INTF_LIPMI@
+INTF_LIPMI_LIB = @INTF_LIPMI_LIB@
+INTF_OPEN = @INTF_OPEN@
+INTF_OPEN_LIB = @INTF_OPEN_LIB@
+INTF_SERIAL = @INTF_SERIAL@
+INTF_SERIAL_LIB = @INTF_SERIAL_LIB@
+IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OS = @OS@
+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@
+POW_LIB = @POW_LIB@
+PSTAMP = @PSTAMP@
+RANLIB = @RANLIB@
+RPMBUILD = @RPMBUILD@
+RPM_RELEASE = @RPM_RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_configure_args = @ac_configure_args@
+ac_ct_AR = @ac_ct_AR@
+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@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+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@
+MAINTAINERCLEANFILES = Makefile.in
+INCLUDES = -I$(top_srcdir)/include
+EXTRA_LTLIBRARIES = libintf_free.la
+noinst_LTLIBRARIES = @INTF_FREE_LIB@
+libintf_free_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_free_la_SOURCES = free.c
+libintf_free_la_LDFLAGS = -lfreeipmi
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(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) --foreign src/plugins/free/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/plugins/free/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: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libintf_free.la: $(libintf_free_la_OBJECTS) $(libintf_free_la_DEPENDENCIES) $(EXTRA_libintf_free_la_DEPENDENCIES)
+ $(libintf_free_la_LINK) $(libintf_free_la_OBJECTS) $(libintf_free_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/free.Plo@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 $(LTLIBRARIES)
+installdirs:
+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:
+ 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:
+
+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."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ 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-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:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES 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-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
+
+
+# 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:
diff --git a/src/plugins/free/free.c b/src/plugins/free/free.c
new file mode 100644
index 0000000..f89925d
--- /dev/null
+++ b/src/plugins/free/free.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ */
+
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_intf.h>
+
+#include <freeipmi/freeipmi.h>
+#if IPMI_INTF_FREE_0_3_0 || IPMI_INTF_FREE_0_4_0 || IPMI_INTF_FREE_0_5_0
+#include <freeipmi/udm/ipmi-udm.h>
+#endif
+
+#if IPMI_INTF_FREE_0_6_0
+ipmi_ctx_t dev = NULL;
+#else /* !IPMI_INTF_FREE_0_6_0 */
+ipmi_device_t dev = NULL;
+#endif /* !IPMI_INTF_FREE_0_6_0 */
+
+extern int verbose;
+
+static int ipmi_free_open(struct ipmi_intf * intf)
+{
+ int kcs_ret = -1, ssif_ret = -1;
+
+ if (getuid() != 0) {
+ fprintf(stderr, "Permission denied, must be root\n");
+ return -1;
+ }
+
+#if IPMI_INTF_FREE_0_3_0
+ if (!(dev = ipmi_open_inband (IPMI_DEVICE_KCS,
+ 0,
+ 0,
+ 0,
+ NULL,
+ IPMI_FLAGS_DEFAULT))) {
+ if (!(dev = ipmi_open_inband (IPMI_DEVICE_SSIF,
+ 0,
+ 0,
+ 0,
+ NULL,
+ IPMI_FLAGS_DEFAULT))) {
+ perror("ipmi_open_inband()");
+ goto cleanup;
+ }
+ }
+#elif IPMI_INTF_FREE_0_4_0
+ if (!(dev = ipmi_device_create())) {
+ perror("ipmi_device_create");
+ goto cleanup;
+ }
+ if (ipmi_open_inband (dev,
+ IPMI_DEVICE_KCS,
+ 0,
+ 0,
+ 0,
+ NULL,
+ IPMI_FLAGS_DEFAULT) < 0) {
+ if (ipmi_open_inband (dev,
+ IPMI_DEVICE_SSIF,
+ 0,
+ 0,
+ 0,
+ NULL,
+ IPMI_FLAGS_DEFAULT) < 0) {
+ fprintf(stderr,
+ "ipmi_open_inband(): %s\n",
+ ipmi_device_strerror(ipmi_device_errnum(dev)));
+ goto cleanup;
+ }
+ }
+#elif IPMI_INTF_FREE_0_5_0
+ if (!(dev = ipmi_device_create())) {
+ perror("ipmi_device_create");
+ goto cleanup;
+ }
+ if (ipmi_open_inband (dev,
+ IPMI_DEVICE_KCS,
+ 0,
+ 0,
+ 0,
+ NULL,
+ 0,
+ IPMI_FLAGS_DEFAULT) < 0) {
+ if (ipmi_open_inband (dev,
+ IPMI_DEVICE_SSIF,
+ 0,
+ 0,
+ 0,
+ NULL,
+ 0,
+ IPMI_FLAGS_DEFAULT) < 0) {
+ fprintf(stderr,
+ "ipmi_open_inband(): %s\n",
+ ipmi_device_strerror(ipmi_device_errnum(dev)));
+ goto cleanup;
+ }
+ }
+#elif IPMI_INTF_FREE_0_6_0
+ if (!(dev = ipmi_ctx_create())) {
+ perror("ipmi_ctx_create");
+ goto cleanup;
+ }
+ if (ipmi_ctx_open_inband (dev,
+ IPMI_DEVICE_KCS,
+ 0,
+ 0,
+ 0,
+ NULL,
+ 0,
+ IPMI_FLAGS_DEFAULT) < 0) {
+ if (ipmi_ctx_open_inband (dev,
+ IPMI_DEVICE_SSIF,
+ 0,
+ 0,
+ 0,
+ NULL,
+ 0,
+ IPMI_FLAGS_DEFAULT) < 0) {
+ fprintf(stderr,
+ "ipmi_open_inband(): %s\n",
+ ipmi_ctx_strerror(ipmi_ctx_errnum(dev)));
+ goto cleanup;
+ }
+ }
+#endif
+
+ intf->opened = 1;
+ intf->manufacturer_id = ipmi_get_oem(intf);
+ return 0;
+ cleanup:
+ if (dev) {
+#if IPMI_INTF_FREE_0_3_0
+ ipmi_close_device(dev);
+#elif IPMI_INTF_FREE_0_4_0 || IPMI_INTF_FREE_0_5_0
+ ipmi_close_device(dev);
+ ipmi_device_destroy(dev);
+#elif IPMI_INTF_FREE_0_6_0
+ ipmi_ctx_close(dev);
+ ipmi_ctx_destroy(dev);
+#endif
+ }
+ return -1;
+}
+
+static void ipmi_free_close(struct ipmi_intf * intf)
+{
+ if (dev) {
+#if IPMI_INTF_FREE_0_3_0
+ ipmi_close_device(dev);
+#elif IPMI_INTF_FREE_0_4_0 || IPMI_INTF_FREE_0_5_0
+ ipmi_close_device(dev);
+ ipmi_device_destroy(dev);
+#elif IPMI_INTF_FREE_0_6_0
+ ipmi_ctx_close(dev);
+ ipmi_ctx_destroy(dev);
+#endif
+ }
+ intf->opened = 0;
+ intf->manufacturer_id = IPMI_OEM_UNKNOWN;
+}
+
+static struct ipmi_rs * ipmi_free_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
+{
+ u_int8_t lun = req->msg.lun;
+ u_int8_t cmd = req->msg.cmd;
+ u_int8_t netfn = req->msg.netfn;
+ u_int8_t rq_buf[IPMI_BUF_SIZE];
+ u_int8_t rs_buf[IPMI_BUF_SIZE];
+ u_int32_t rs_buf_len = IPMI_BUF_SIZE;
+ int32_t rs_len;
+
+ static struct ipmi_rs rsp;
+
+ /* achu: FreeIPMI requests have the cmd as the first byte of
+ * the data. Responses have cmd as the first byte and
+ * completion code as the second byte. This differs from some
+ * other APIs, so it must be compensated for within the ipmitool
+ * interface.
+ */
+
+ if (!intf || !req)
+ return NULL;
+
+ if (!intf->opened && intf->open && intf->open(intf) < 0)
+ return NULL;
+
+ if (req->msg.data_len > IPMI_BUF_SIZE)
+ return NULL;
+
+ memset(rq_buf, '\0', IPMI_BUF_SIZE);
+ memset(rs_buf, '\0', IPMI_BUF_SIZE);
+ memcpy(rq_buf, &cmd, 1);
+
+ if (req->msg.data)
+ memcpy(rq_buf + 1, req->msg.data, req->msg.data_len);
+
+ if (intf->target_addr != 0
+ && intf->target_addr != IPMI_BMC_SLAVE_ADDR) {
+#if IPMI_INTF_FREE_BRIDGING
+ if ((rs_len = ipmi_cmd_raw_ipmb(dev,
+ intf->target_channel,
+ intf->target_addr,
+ lun,
+ netfn,
+ rq_buf,
+ req->msg.data_len + 1,
+ rs_buf,
+ rs_buf_len)) < 0) {
+ if (verbose > 3)
+ fprintf(stderr,
+ "ipmi_cmd_raw_ipmb: %s\n",
+ ipmi_ctx_strerror(ipmi_ctx_errnum(dev)));
+ /* Compared to FreeIPMI, user is expected to input
+ * the target channel on the command line, it is not automatically
+ * discovered. So that is the likely cause of an error.
+ *
+ * Instead of returning an error, return a bad response so output
+ * of ipmitool commands looks like other interfaces
+ */
+ rs_len = 2;
+ rs_buf[0] = 0;
+ rs_buf[1] = 0xC1; /* invalid command */
+ }
+#else /* !IPMI_INTF_FREE_BRIDGING */
+ if (verbose > 3)
+ fprintf(stderr, "sensor bridging not supported in this driver version");
+ /* instead of returning an error, return a bad response so output
+ * of ipmitool commands looks like other interfaces
+ */
+ rs_len = 2;
+ rs_buf[0] = 0;
+ rs_buf[1] = 0xC1; /* invalid command */
+#endif /* !IPMI_INTF_FREE_BRIDGING */
+ }
+ else {
+ if ((rs_len = ipmi_cmd_raw(dev,
+ lun,
+ netfn,
+ rq_buf,
+ req->msg.data_len + 1,
+ rs_buf,
+ rs_buf_len)) < 0) {
+#if IPMI_INTF_FREE_0_3_0
+ perror("ipmi_cmd_raw");
+#elif IPMI_INTF_FREE_0_4_0 || IPMI_INTF_FREE_0_5_0
+ fprintf(stderr,
+ "ipmi_cmd_raw: %s\n",
+ ipmi_device_strerror(ipmi_device_errnum(dev)));
+#elif IPMI_INTF_FREE_0_6_0
+ fprintf(stderr,
+ "ipmi_cmd_raw: %s\n",
+ ipmi_ctx_strerror(ipmi_ctx_errnum(dev)));
+#endif
+ return NULL;
+ }
+ }
+
+ memset(&rsp, 0, sizeof(struct ipmi_rs));
+ rsp.ccode = (unsigned char)rs_buf[1];
+ rsp.data_len = (int)rs_len - 2;
+
+ if (!rsp.ccode && rsp.data_len)
+ memcpy(rsp.data, rs_buf + 2, rsp.data_len);
+
+ return &rsp;
+}
+
+struct ipmi_intf ipmi_free_intf = {
+ name: "free",
+ desc: "FreeIPMI IPMI Interface",
+ open: ipmi_free_open,
+ close: ipmi_free_close,
+ sendrecv: ipmi_free_send_cmd,
+ target_addr: IPMI_BMC_SLAVE_ADDR,
+};
+
diff --git a/src/plugins/imb/Makefile.am b/src/plugins/imb/Makefile.am
new file mode 100644
index 0000000..91d5966
--- /dev/null
+++ b/src/plugins/imb/Makefile.am
@@ -0,0 +1,39 @@
+# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Sun Microsystems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = -I$(top_srcdir)/include
+
+EXTRA_LTLIBRARIES = libintf_imb.la
+noinst_LTLIBRARIES = @INTF_IMB_LIB@
+libintf_imb_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_imb_la_SOURCES = imbapi.c imbapi.h imb.c
+
diff --git a/src/plugins/imb/Makefile.in b/src/plugins/imb/Makefile.in
new file mode 100644
index 0000000..27cefb1
--- /dev/null
+++ b/src/plugins/imb/Makefile.in
@@ -0,0 +1,539 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 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.
+
+# 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@
+
+# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Sun Microsystems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+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@
+subdir = src/plugins/imb
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libintf_imb_la_DEPENDENCIES = $(top_builddir)/lib/libipmitool.la
+am_libintf_imb_la_OBJECTS = imbapi.lo imb.lo
+libintf_imb_la_OBJECTS = $(am_libintf_imb_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+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 = $(libintf_imb_la_SOURCES)
+DIST_SOURCES = $(libintf_imb_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+ARCH = @ARCH@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASEDIR = @BASEDIR@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTRO = @DISTRO@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTF_BMC = @INTF_BMC@
+INTF_BMC_LIB = @INTF_BMC_LIB@
+INTF_DUMMY = @INTF_DUMMY@
+INTF_DUMMY_LIB = @INTF_DUMMY_LIB@
+INTF_FREE = @INTF_FREE@
+INTF_FREE_LIB = @INTF_FREE_LIB@
+INTF_IMB = @INTF_IMB@
+INTF_IMB_LIB = @INTF_IMB_LIB@
+INTF_LAN = @INTF_LAN@
+INTF_LANPLUS = @INTF_LANPLUS@
+INTF_LANPLUS_LIB = @INTF_LANPLUS_LIB@
+INTF_LAN_LIB = @INTF_LAN_LIB@
+INTF_LIPMI = @INTF_LIPMI@
+INTF_LIPMI_LIB = @INTF_LIPMI_LIB@
+INTF_OPEN = @INTF_OPEN@
+INTF_OPEN_LIB = @INTF_OPEN_LIB@
+INTF_SERIAL = @INTF_SERIAL@
+INTF_SERIAL_LIB = @INTF_SERIAL_LIB@
+IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OS = @OS@
+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@
+POW_LIB = @POW_LIB@
+PSTAMP = @PSTAMP@
+RANLIB = @RANLIB@
+RPMBUILD = @RPMBUILD@
+RPM_RELEASE = @RPM_RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_configure_args = @ac_configure_args@
+ac_ct_AR = @ac_ct_AR@
+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@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+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@
+MAINTAINERCLEANFILES = Makefile.in
+INCLUDES = -I$(top_srcdir)/include
+EXTRA_LTLIBRARIES = libintf_imb.la
+noinst_LTLIBRARIES = @INTF_IMB_LIB@
+libintf_imb_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_imb_la_SOURCES = imbapi.c imbapi.h imb.c
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(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) --foreign src/plugins/imb/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/plugins/imb/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: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libintf_imb.la: $(libintf_imb_la_OBJECTS) $(libintf_imb_la_DEPENDENCIES) $(EXTRA_libintf_imb_la_DEPENDENCIES)
+ $(LINK) $(libintf_imb_la_OBJECTS) $(libintf_imb_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imbapi.Plo@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 $(LTLIBRARIES)
+installdirs:
+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:
+ 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:
+
+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."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ 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-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:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES 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-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
+
+
+# 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:
diff --git a/src/plugins/imb/imb.c b/src/plugins/imb/imb.c
new file mode 100644
index 0000000..cb97e81
--- /dev/null
+++ b/src/plugins/imb/imb.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_intf.h>
+#include <ipmitool/helper.h>
+
+#include "imbapi.h"
+
+#define IPMI_IMB_TIMEOUT (1000 * 1000)
+#define IPMI_IMB_MAX_RETRY 3
+#define IPMI_IMB_DEV "/dev/imb"
+#define IPMI_IMB_BUF_SIZE 64
+
+extern int verbose;
+
+static int ipmi_imb_open(struct ipmi_intf * intf)
+{
+ struct stat stbuf;
+
+ if (stat(IPMI_IMB_DEV, &stbuf) < 0) {
+ printf("Error: no IMB driver found at %s!\n", IPMI_IMB_DEV);
+ return -1;
+ }
+
+ intf->opened = 1;
+ intf->manufacturer_id = ipmi_get_oem(intf);
+
+ return 0;
+}
+
+static void ipmi_imb_close(struct ipmi_intf * intf)
+{
+ intf->opened = 0;
+ intf->manufacturer_id = IPMI_OEM_UNKNOWN;
+}
+
+static struct ipmi_rs * ipmi_imb_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
+{
+ IMBPREQUESTDATA imbreq;
+ static struct ipmi_rs rsp;
+ int status, i;
+ unsigned char ccode;
+
+ imbreq.rsSa = IPMI_BMC_SLAVE_ADDR;
+ imbreq.rsLun = 0;
+ imbreq.busType = 0;
+ imbreq.netFn = req->msg.netfn;
+ imbreq.cmdType = req->msg.cmd;
+
+ imbreq.data = req->msg.data;
+ imbreq.dataLength = req->msg.data_len;
+
+ if (verbose > 1) {
+ printf("IMB rsSa : %x\n", imbreq.rsSa);
+ printf("IMB netFn : %x\n", imbreq.netFn);
+ printf("IMB cmdType : %x\n", imbreq.cmdType);
+ printf("IMB dataLength : %d\n", imbreq.dataLength);
+ }
+
+ rsp.data_len = IPMI_IMB_BUF_SIZE;
+ memset(rsp.data, 0, rsp.data_len);
+
+ for (i=0; i<IPMI_IMB_MAX_RETRY; i++) {
+ if (verbose > 2)
+ printbuf(imbreq.data, imbreq.dataLength, "ipmi_imb request");
+ status = SendTimedImbpRequest(&imbreq, IPMI_IMB_TIMEOUT,
+ rsp.data, &rsp.data_len, &ccode);
+ if (status == 0) {
+ if (verbose > 2)
+ printbuf(rsp.data, rsp.data_len, "ipmi_imb response");
+ break;
+ }
+ /* error */
+ printf("Error sending IMB request, status=%x ccode=%x\n",
+ status, ccode);
+ }
+
+ rsp.ccode = ccode;
+
+ return &rsp;
+}
+
+struct ipmi_intf ipmi_imb_intf = {
+ name: "imb",
+ desc: "Intel IMB Interface",
+ open: ipmi_imb_open,
+ close: ipmi_imb_close,
+ sendrecv: ipmi_imb_send_cmd,
+ target_addr: IPMI_BMC_SLAVE_ADDR,
+};
+
diff --git a/src/plugins/imb/imbapi.c b/src/plugins/imb/imbapi.c
new file mode 100644
index 0000000..37d3abe
--- /dev/null
+++ b/src/plugins/imb/imbapi.c
@@ -0,0 +1,2090 @@
+/*M*
+// PVCS:
+// $Workfile: imbapi.c $
+// $Revision: 1.5 $
+// $Modtime: 06 Aug 2001 13:16:56 $
+// $Author: stybla $
+//
+// Purpose: This file contains the entry point that opens the IMB device in
+// order to issue the IMB driver API related IOCTLs.
+// This file implements the IMB driver API for the Server
+// Management Agents
+//
+//
+*M*/
+/*----------------------------------------------------------------------*
+The BSD License
+Copyright (c) 2002, Intel Corporation
+All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ a.. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ b.. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ c.. Neither the name of Intel Corporation nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *----------------------------------------------------------------------*/
+/*
+ * $Log: imbapi.c,v $
+ * Revision 1.5 2013/07/22 08:35:23 stybla
+ * ID: 65 - Fixes for configure.in for cross compilation
+ *
+ * 'src/plugins/imb/imbapi.c' - don't cast NULL to int, ever!!!
+ *
+ * Revision 1.4 2013/07/21 11:33:57 stybla
+ * ID: 65 - Fixes for configure.in for cross compilation
+ *
+ * NULL should never be cast to an int.
+ *
+ * Commit for Dan Gora
+ *
+ * Revision 1.3 2013/01/18 12:46:52 ledva
+ * 3600962 descriptor leaks
+ *
+ * Revision 1.2 2004/08/31 23:52:58 iceblink
+ * fix lots of little errors that show up with -Werror -Wall
+ *
+ * Revision 1.1 2004/08/27 16:33:25 iceblink
+ * add support for Intel IMB kernel driver (for legacy kernel support)
+ * imbapi.[ch] code is BSD licensed and taken from panicsel.sf.net
+ *
+ *
+ * Rev 1.12ac 04 Apr 2002 13:17:58 arcress
+ * Mods for open-source & various compile cleanup mods
+ *
+ * Rev 1.12 06 Aug 2001 13:17:58 spoola
+ * Fixed tracker items #15667, #15666, #15664
+ *
+ * Rev 1.0 05 Sep 1999 17:20:30 mramacha
+ * Linux checkin
+ *
+ * Note: This file is derived from the NTWORK version of the imbapi.c
+ * It was decided to create OS specific ones for Linux and Solaris.
+ * It has all the fixes that went into the imbapi.c up to Rev 1.12
+ * in the 2.2 NTWORK branch.
+ */
+
+#define IMB_API
+
+#ifdef WIN32
+#define NO_MACRO_ARGS 1
+#include <windows.h>
+#include <stdio.h>
+
+#else /* LINUX, SCO_UW, UNIX */
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#endif
+#include "imbapi.h"
+
+#ifdef SCO_UW
+#define NO_MACRO_ARGS 1
+#define __FUNCTION__ "func"
+#define IMB_DEVICE "/dev/instru/mismic"
+#else
+#define IMB_DEVICE "/dev/imb"
+#define PAGESIZE EXEC_PAGESIZE
+#endif
+
+/*Just to make the DEBUG code cleaner.*/
+#ifndef NO_MACRO_ARGS
+#ifdef LINUX_DEBUG
+#define DEBUG(format, args...) printf(format, ##args)
+#else
+#define DEBUG(format, args...)
+#endif
+#endif
+
+/* uncomment out the #define below or use -DLINUX_DEBUG_MAX in the makefile
+// if you want a dump of the memory to debug mmap system call in
+// MapPhysicalMemory() below.
+//
+//#define LINUX_DEBUG_MAX */
+
+
+/*keep it simple. use global varibles for event objects and handles
+//pai 10/8 */
+
+/* UnixWare should eventually have its own source code file. Right now
+// new code has been added based on the exsisting policy of using
+// pre-processor directives to separate os-specific code (pai 11/21) */
+
+HANDLE AsyncEventHandle = 0;
+//static void * AsyncEventObject = 0;
+static int IpmiVersion;
+
+/*////////////////////////////////////////////////////////////////////////////
+// GLOBAL VARIABLES
+///////////////////////////////////////////////////////////////////////////// */
+
+IO_STATUS_BLOCK NTstatus; /*dummy place holder. See deviceiocontrol. */
+static HANDLE hDevice1;
+static HANDLE hDevice;
+/*mutex_t deviceMutex; */
+static int fDriverTyp; /*from ipmicmd.c*/
+
+/*////////////////////////////////////////////////////////////////////
+// open_imb
+////////////////////////////////////////////////////////////////////// */
+/*F*
+// Name: open_imb
+// Purpose: To open imb device
+// Context: Called from each routine to make sure that open is done.
+// Returns: returns 0 for Fail and 1 for Success, sets hDevice to open
+// handle.
+// Parameters: none
+// Notes: none
+*F*/
+#ifdef WIN32
+int open_imb(void)
+{
+/* This routine will be called from all other routines before doing any
+ interfacing with imb driver. It will open only once. */
+ IMBPREQUESTDATA requestData;
+ BYTE respBuffer[16];
+ DWORD respLength;
+ BYTE completionCode;
+
+ if (hDevice1 == 0) /*INVALID_HANDLE_VALUE*/
+ {
+ //
+ // Open IMB driver device
+ //
+ hDevice = CreateFile( "\\\\.\\Imb",
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+ if (hDevice == NULL || hDevice == INVALID_HANDLE_VALUE)
+ return (0); /*FALSE*/
+
+ // Detect the IPMI version for processing requests later.
+ // This is a crude but most reliable method to differentiate
+ // between old IPMI versions and the 1.0 version. If we had used the
+ // version field instead then we would have had to revalidate all the
+ // older platforms (pai 4/27/99)
+ requestData.cmdType = GET_DEVICE_ID;
+ requestData.rsSa = BMC_SA;
+ requestData.rsLun = BMC_LUN;
+ requestData.netFn = APP_NETFN ;
+ requestData.busType = PUBLIC_BUS;
+ requestData.data = NULL;
+ requestData.dataLength = 0;
+ respLength = 16;
+ if ( (SendTimedImbpRequest ( &requestData, (DWORD)400,
+ respBuffer, &respLength, &completionCode
+ ) != ACCESN_OK ) || ( completionCode != 0) )
+ {
+ CloseHandle(hDevice);
+ return (0); /*FALSE*/
+ }
+ hDevice1 = hDevice;
+
+ if (respLength < (IPMI10_GET_DEVICE_ID_RESP_LENGTH-1))
+ IpmiVersion = IPMI_09_VERSION;
+ else {
+ if ( respBuffer[4] == 0x51 )
+ IpmiVersion = IPMI_15_VERSION;
+ else
+ IpmiVersion = IPMI_10_VERSION;
+ }
+ }
+ return (1); /*TRUE*/
+
+} /*end open_imb for Win32 */
+
+#else /* LINUX, SCO_UW, etc. */
+
+int open_imb(void)
+{
+/* This routine will be called from all other routines before doing any
+ interfacing with imb driver. It will open only once. */
+ IMBPREQUESTDATA requestData;
+ BYTE respBuffer[16];
+ DWORD respLength;
+ BYTE completionCode;
+
+ int my_ret_code;
+
+ if (hDevice1 == 0)
+ {
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: opening the driver\n", __FUNCTION__);
+#endif
+ /*
+ printf("open_imb: "
+ "IOCTL_IMB_SEND_MESSAGE =%x \n" "IOCTL_IMB_GET_ASYNC_MSG=%x \n"
+ "IOCTL_IMB_MAP_MEMORY = %x \n" "IOCTL_IMB_UNMAP_MEMORY= %x \n"
+ "IOCTL_IMB_SHUTDOWN_CODE=%x \n" "IOCTL_IMB_REGISTER_ASYNC_OBJ =%x \n"
+ "IOCTL_IMB_DEREGISTER_ASYNC_OBJ=%x \n"
+ "IOCTL_IMB_CHECK_EVENT =%x \n" "IOCTL_IMB_POLL_ASYNC =%x \n",
+ IOCTL_IMB_SEND_MESSAGE, IOCTL_IMB_GET_ASYNC_MSG,
+ IOCTL_IMB_MAP_MEMORY, IOCTL_IMB_UNMAP_MEMORY, IOCTL_IMB_SHUTDOWN_CODE,
+ IOCTL_IMB_REGISTER_ASYNC_OBJ, IOCTL_IMB_DEREGISTER_ASYNC_OBJ,
+ IOCTL_IMB_CHECK_EVENT , IOCTL_IMB_POLL_ASYNC); *%%%%*/
+
+ /*O_NDELAY flag will cause problems later when driver makes
+ //you wait. Hence removing it. */
+ /*if ((hDevice1 = open(IMB_DEVICE,O_RDWR|O_NDELAY)) <0) */
+ if ((hDevice1 = open(IMB_DEVICE,O_RDWR)) <0)
+ {
+ char buf[128];
+
+ hDevice1 = 0;
+ if (fDriverTyp != 0) { /*not 1st time*/
+ sprintf(buf,"%s %s: open(%s) failed",
+ __FILE__,__FUNCTION__,IMB_DEVICE);
+ perror(buf);
+ }
+ return (0);
+ }
+
+ /* Detect the IPMI version for processing requests later.
+ // This is a crude but most reliable method to differentiate
+ // between old IPMI versions and the 1.0 version. If we had used the
+ // version field instead then we would have had to revalidate all
+ // the older platforms (pai 4/27/99) */
+ requestData.cmdType = GET_DEVICE_ID;
+ requestData.rsSa = BMC_SA;
+ requestData.rsLun = BMC_LUN;
+ requestData.netFn = APP_NETFN ;
+ requestData.busType = PUBLIC_BUS;
+ requestData.data = NULL;
+ requestData.dataLength = 0;
+ respLength = 16;
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: opened driver, getting IPMI version\n", __FUNCTION__);
+#endif
+ if ( ((my_ret_code = SendTimedImbpRequest(&requestData, (DWORD)400,
+ respBuffer, (int *)&respLength, &completionCode)
+ ) != ACCESN_OK ) || ( completionCode != 0) )
+ {
+ printf("%s: SendTimedImbpRequest error. Ret = %d CC = 0x%X\n",
+ __FUNCTION__, my_ret_code, completionCode);
+ close(hDevice1);
+ hDevice1 = 0;
+ return (0);
+ }
+
+ if (respLength < (IPMI10_GET_DEVICE_ID_RESP_LENGTH-1))
+ IpmiVersion = IPMI_09_VERSION;
+ else {
+ if ( respBuffer[4] == 0x51 )
+ IpmiVersion = IPMI_15_VERSION;
+ else
+ IpmiVersion = IPMI_10_VERSION;
+ }
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: IPMI version 0x%x\n", __FUNCTION__, IpmiVersion);
+#endif
+
+/*
+//initialise a mutex
+ if(mutex_init(&deviceMutex , USYNC_THREAD, NULL) != 0)
+ {
+ return(0);
+ }
+*/
+
+ }
+
+ return (1);
+} /*end open_imb()*/
+#endif
+
+/*---------------------------------------------------------------------*
+ * ipmi_open_ia & ipmi_close_ia
+ *---------------------------------------------------------------------*/
+int ipmi_open_ia(void)
+{
+ int rc = 0;
+ rc = open_imb(); /*sets hDevice1*/
+ if (rc == 1) rc = 0;
+ else rc = -1;
+ return(rc);
+}
+
+int ipmi_close_ia(void)
+{
+ int rc = 0;
+ if (hDevice1 != 0) {
+#ifdef WIN32
+ CloseHandle(hDevice1);
+#else
+ rc = close(hDevice1);
+#endif
+ }
+ return(rc);
+}
+
+#ifndef WIN32
+/*///////////////////////////////////////////////////////////////////////////
+// DeviceIoControl
+///////////////////////////////////////////////////////////////////////////// */
+/*F*
+// Name: DeviceIoControl
+// Purpose: Simulate NT DeviceIoControl using unix calls and structures.
+// Context: called for every NT DeviceIoControl
+// Returns: FALSE for fail and TRUE for success. Same as standarad NTOS call
+// as it also sets Ntstatus.status.
+// Parameters: Standard NT call parameters, see below.
+// Notes: none
+*F*/
+static BOOL
+DeviceIoControl(
+ HANDLE dummey_hDevice, /* handle of device */
+ DWORD dwIoControlCode, /* control code of operation to perform*/
+ LPVOID lpvInBuffer, /* address of buffer for input data */
+ DWORD cbInBuffer, /* size of input buffer */
+ LPVOID lpvOutBuffer, /* address of output buffer */
+ DWORD cbOutBuffer, /* size of output buffer */
+ LPDWORD lpcbBytesReturned, /* address of actual bytes of output */
+ LPOVERLAPPED lpoOverlapped /* address of overlapped struct */
+ )
+{
+ struct smi s;
+ int rc;
+ int ioctl_status;
+
+ rc = open_imb();
+ if (rc == 0) {
+ return FALSE;
+ }
+
+ /*
+ //lock the mutex, before making the request....
+ if(mutex_lock(&deviceMutex) != 0)
+ {
+ return(FALSE);
+ }
+ */
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: ioctl cmd = 0x%lx ", __FUNCTION__,dwIoControlCode);
+ DEBUG("cbInBuffer %d cbOutBuffer %d\n", cbInBuffer, cbOutBuffer);
+#endif
+ if (cbInBuffer > 41) cbInBuffer = 41; /* Intel driver max buf */
+
+ s.lpvInBuffer = lpvInBuffer;
+ s.cbInBuffer = cbInBuffer;
+ s.lpvOutBuffer = lpvOutBuffer;
+ s.cbOutBuffer = cbOutBuffer;
+ s.lpcbBytesReturned = lpcbBytesReturned;
+ s.lpoOverlapped = lpoOverlapped;
+ s.ntstatus = (LPVOID)&NTstatus; /*dummy place holder. Linux IMB driver
+ //doesnt return status or info via it.*/
+
+ if ( (ioctl_status = ioctl(hDevice1, dwIoControlCode,&s) ) <0) {
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s %s: ioctl cmd = 0x%x failed",
+ __FILE__,__FUNCTION__,dwIoControlCode);
+#endif
+ /* mutex_unlock(&deviceMutex); */
+ return FALSE;
+ }
+ /* mutex_unlock(&deviceMutex); */
+
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: ioctl_status %d bytes returned = %d \n",
+ __FUNCTION__, ioctl_status, *lpcbBytesReturned);
+#endif
+
+/*MR commented this just as in Sol1.10. lpcbBytesReturned has the right data
+// *lpcbBytesReturned = NTstatus.Information; */
+
+ if (ioctl_status == STATUS_SUCCESS) {
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s returning true\n", __FUNCTION__);
+#endif
+ return (TRUE);
+ }
+ else {
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s returning false\n", __FUNCTION__);
+#endif
+ return (FALSE);
+ }
+}
+#endif
+
+/*Used only by UW. Left here for now. IMB driver will not accept this
+//ioctl. */
+ACCESN_STATUS
+StartAsyncMesgPoll()
+{
+
+ DWORD retLength;
+ BOOL status;
+
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: DeviceIoControl cmd = %x\n",__FUNCTION__,IOCTL_IMB_POLL_ASYNC);
+#endif
+ status = DeviceIoControl ( hDevice,
+ IOCTL_IMB_POLL_ASYNC,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ & retLength,
+ 0
+ );
+
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
+#endif
+
+ if( status == TRUE ) {
+ return ACCESN_OK;
+ } else {
+ return ACCESN_ERROR;
+ }
+
+}
+
+/*/////////////////////////////////////////////////////////////////////////////
+// SendTimedI2cRequest
+///////////////////////////////////////////////////////////////////////////// */
+/*F*
+// Name: SendTimedI2cRequest
+// Purpose: This function sends a request to a I2C device
+// Context: Used by Upper level agents (sis modules) to access dumb I2c devices
+// Returns: ACCESN_OK else error status code
+// Parameters:
+// reqPtr
+// timeOut
+// respDataPtr
+// respLen
+// Notes: none
+*F*/
+
+ACCESN_STATUS
+SendTimedI2cRequest (
+ I2CREQUESTDATA *reqPtr, /* I2C request */
+ int timeOut, /* how long to wait, mSec units */
+ BYTE *respDataPtr, /* where to put response data */
+ int *respDataLen, /* size of response buffer and */
+ /* size of returned data */
+ BYTE *completionCode /* request status from BMC */
+ )
+{
+ BOOL status;
+ BYTE responseData[MAX_IMB_RESP_SIZE];
+ ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData;
+ DWORD respLength = sizeof( responseData );
+ BYTE requestData[MAX_IMB_RESP_SIZE];
+ ImbRequestBuffer * req = (ImbRequestBuffer *) requestData;
+
+ struct WriteReadI2C { /* format of a write/read I2C request */
+ BYTE busType;
+ BYTE rsSa;
+ BYTE count;
+ BYTE data[1];
+ } * wrReq = (struct WriteReadI2C *) req->req.data;
+
+#define MIN_WRI2C_SIZE 3 /* size of write/read request minus any data */
+
+
+ /*
+ // If the Imb driver is not present return AccessFailed
+ */
+
+ req->req.rsSa = BMC_SA;
+ req->req.cmd = WRITE_READ_I2C;
+ req->req.netFn = APP_NETFN;
+ req->req.rsLun = BMC_LUN;
+ req->req.dataLength = reqPtr->dataLength + MIN_WRI2C_SIZE;
+
+ wrReq->busType = reqPtr->busType;
+ wrReq->rsSa = reqPtr->rsSa;
+ wrReq->count = reqPtr->numberOfBytesToRead;
+
+ memcpy( wrReq->data, reqPtr->data, reqPtr->dataLength );
+
+ req->flags = 0;
+ req->timeOut = timeOut * 1000; /* convert to uSec units */
+
+ status = DeviceIoControl( hDevice,
+ IOCTL_IMB_SEND_MESSAGE,
+ requestData,
+ sizeof( requestData ),
+ & responseData,
+ sizeof( responseData ),
+ & respLength,
+ NULL
+ );
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
+#endif
+
+ if( status != TRUE ) {
+ DWORD error;
+ error = GetLastError();
+ return ACCESN_ERROR;
+ }
+ if( respLength == 0 ) {
+ return ACCESN_ERROR;
+ }
+
+ /*
+ // give the caller his response
+ */
+ *completionCode = resp->cCode;
+ *respDataLen = respLength - 1;
+
+ if(( *respDataLen ) && (respDataPtr))
+ memcpy( respDataPtr, resp->data, *respDataLen);
+
+ return ACCESN_OK;
+
+}
+
+/*This is not a API exported by the driver in stricter sense. It is
+//added to support EMP functionality. Upper level software could have
+//implemented this function.(pai 5/4/99) */
+/*/////////////////////////////////////////////////////////////////////////////
+// SendTimedEmpMessageResponse
+///////////////////////////////////////////////////////////////////////////// */
+
+/*F*
+// Name: SendTimedEmpMessageResponse
+// Purpose: This function sends a response message to the EMP port
+// Context:
+// Returns: OK else error status code
+// Parameters:
+//
+// Notes: none
+*F*/
+
+ACCESN_STATUS
+SendTimedEmpMessageResponse (
+ ImbPacket *ptr, /* pointer to the original request from EMP */
+ char *responseDataBuf,
+ int responseDataLen,
+ int timeOut /* how long to wait, in mSec units */
+ )
+{
+ BOOL status;
+ BYTE responseData[MAX_IMB_RESP_SIZE];
+ /*ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; */
+ DWORD respLength = sizeof( responseData );
+ BYTE requestData[MAX_IMB_RESP_SIZE];
+ ImbRequestBuffer * req = (ImbRequestBuffer *) requestData;
+ int i,j;
+
+ /*form the response packet first */
+ req->req.rsSa = BMC_SA;
+ if (IpmiVersion == IPMI_09_VERSION)
+ req->req.cmd = WRITE_EMP_BUFFER;
+ else
+ req->req.cmd = SEND_MESSAGE;
+ req->req.netFn = APP_NETFN;
+ req->req.rsLun = 0;
+
+ i = 0;
+ if (IpmiVersion != IPMI_09_VERSION)
+ req->req.data[i++] = EMP_CHANNEL;
+
+ req->req.data[i++] = ptr->rqSa;
+ req->req.data[i++] = (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3));
+ if (IpmiVersion == IPMI_09_VERSION)
+ req->req.data[i++] = ((~(req->req.data[0] + req->req.data[1])) +1);
+ else
+ req->req.data[i++] = ((~(req->req.data[1] + req->req.data[2])) +1);
+
+ req->req.data[i++] = BMC_SA; /*though software is responding, we have to
+ //provide BMCs slave address as responder
+ //address. */
+
+ req->req.data[i++] = ( (ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3) );
+
+ req->req.data[i++] = ptr->cmd;
+ for ( j = 0 ; j < responseDataLen ; ++j,++i)
+ req->req.data[i] = responseDataBuf[j];
+
+ req->req.data[i] = 0;
+ if (IpmiVersion == IPMI_09_VERSION)
+ j = 0;
+ else
+ j = 1;
+ for ( ; j < ( i -3); ++j)
+ req->req.data[i] += req->req.data[j+3];
+ req->req.data[i] = ~(req->req.data[i]) +1;
+ ++i;
+ req->req.dataLength = i;
+
+ req->flags = 0;
+ req->timeOut = timeOut * 1000; /* convert to uSec units */
+
+
+ status = DeviceIoControl( hDevice,
+ IOCTL_IMB_SEND_MESSAGE,
+ requestData,
+ sizeof(requestData),
+ responseData,
+ sizeof( responseData ),
+ & respLength,
+ NULL
+ );
+
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
+#endif
+
+
+ if ( (status != TRUE) || (respLength != 1) || (responseData[0] != 0) )
+ {
+ return ACCESN_ERROR;
+ }
+ return ACCESN_OK;
+}
+
+
+/*This is not a API exported by the driver in stricter sense. It is added to support
+// EMP functionality. Upper level software could have implemented this function.(pai 5/4/99) */
+/*///////////////////////////////////////////////////////////////////////////
+// SendTimedEmpMessageResponse_Ex
+//////////////////////////////////////////////////////////////////////////// */
+
+/*F*
+// Name: SendTimedEmpMessageResponse_Ex
+// Purpose: This function sends a response message to the EMP port
+// Context:
+// Returns: OK else error status code
+// Parameters:
+//
+// Notes: none
+*F*/
+
+
+
+ACCESN_STATUS
+SendTimedEmpMessageResponse_Ex (
+
+ ImbPacket * ptr, /* pointer to the original request from EMP */
+ char *responseDataBuf,
+ int responseDataLen,
+ int timeOut, /* how long to wait, in mSec units*/
+ BYTE sessionHandle, /*This is introduced in IPMI1.5,this is required to be sent in
+ //send message command as a parameter,which is then used by BMC
+ //to identify the correct DPC session to send the mesage to. */
+ BYTE channelNumber /*There are 3 different channels on which DPC communication goes on
+ //Emp - 1,Lan channel one - 6,Lan channel two(primary channel) - 7. */
+ )
+{
+ BOOL status;
+ BYTE responseData[MAX_IMB_RESP_SIZE];
+ /* ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; */
+ DWORD respLength = sizeof( responseData );
+ BYTE requestData[MAX_IMB_RESP_SIZE];
+ ImbRequestBuffer * req = (ImbRequestBuffer *) requestData;
+ int i,j;
+
+ /*form the response packet first */
+ req->req.rsSa = BMC_SA;
+ if (IpmiVersion == IPMI_09_VERSION)
+ req->req.cmd = WRITE_EMP_BUFFER;
+ else
+ req->req.cmd = SEND_MESSAGE;
+ req->req.netFn = APP_NETFN;
+ req->req.rsLun = 0;
+
+ i = 0;
+
+ /*checking for the IPMI version & then assigning the channel number for EMP
+ //Actually the channel number is same in both the versions.This is just to
+ //maintain the consistancy with the same method for LAN.
+ //This is the 1st byte of the SEND MESSAGE command. */
+ if (IpmiVersion == IPMI_10_VERSION)
+ req->req.data[i++] = EMP_CHANNEL;
+ else if (IpmiVersion == IPMI_15_VERSION)
+ req->req.data[i++] = channelNumber;
+
+ /*The second byte of data for SEND MESSAGE starts with session handle */
+ req->req.data[i++] = sessionHandle;
+
+ /*Then it is the response slave address for SEND MESSAGE. */
+ req->req.data[i++] = ptr->rqSa;
+
+ /*Then the net function + lun for SEND MESSAGE command. */
+ req->req.data[i++] = (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3));
+
+ /*Here the checksum is calculated.The checksum calculation starts after the channel number.
+ //so for the IPMI 1.5 version its a checksum of 3 bytes that is session handle,response slave
+ //address & netfun+lun. */
+ if (IpmiVersion == IPMI_09_VERSION)
+ req->req.data[i++] = ((~(req->req.data[0] + req->req.data[1])) +1);
+ else
+ {
+ if (IpmiVersion == IPMI_10_VERSION)
+ req->req.data[i++] = ((~(req->req.data[1] + req->req.data[2])) +1);
+ else
+ req->req.data[i++] = ((~(req->req.data[2]+ req->req.data[3])) +1);
+ }
+
+ /*This is the next byte of the message data for SEND MESSAGE command.It is the request
+ //slave address. */
+ req->req.data[i++] = BMC_SA; /*though software is responding, we have to
+ //provide BMCs slave address as responder
+ //address. */
+
+ /*This is just the sequence number,which is the next byte of data for SEND MESSAGE */
+ req->req.data[i++] = ( (ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3) );
+
+ /*The next byte is the command like get software ID(00).*/
+ req->req.data[i++] = ptr->cmd;
+
+ /*after the cmd the data ,which is sent by DPC & is retrived using the get message earlier
+ // is sent back to DPC. */
+ for ( j = 0 ; j < responseDataLen ; ++j,++i)
+ req->req.data[i] = responseDataBuf[j];
+
+ req->req.data[i] = 0;
+
+ /*The last byte of data for SEND MESSAGE command is the check sum ,which is calculated
+ //from the next byte of the previous checksum that is the request slave address. */
+ if (IpmiVersion == IPMI_09_VERSION)
+ j = 0;
+ else
+ {
+ if (IpmiVersion == IPMI_10_VERSION)
+ j = 1;
+ else
+ j = 2;
+ }
+ for ( ; j < ( i -3); ++j)
+ req->req.data[i] += req->req.data[j+3];
+ req->req.data[i] = ~(req->req.data[i]) +1;
+ ++i;
+ req->req.dataLength = i;
+
+ /*The flags & timeouts are used by the driver internally. */
+ req->flags = 0;
+ req->timeOut = timeOut * 1000; /* convert to uSec units */
+
+ status = DeviceIoControl( hDevice,
+ IOCTL_IMB_SEND_MESSAGE,
+ requestData,
+ sizeof(requestData),
+ responseData,
+ sizeof( responseData ),
+ & respLength,
+ NULL
+ );
+
+
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
+#endif
+
+
+ if ( (status != TRUE) || (respLength != 1) || (responseData[0] != 0) )
+ {
+ return ACCESN_ERROR;
+ }
+ return ACCESN_OK;
+
+
+
+}
+
+/*This is not a API exported by the driver in stricter sense. It is
+//added to support EMP functionality. Upper level software could have
+//implemented this function.(pai 5/4/99) */
+/*///////////////////////////////////////////////////////////////////////////
+// SendTimedLanMessageResponse
+///////////////////////////////////////////////////////////////////////////// */
+
+/*F*
+// Name: SendTimedLanMessageResponse
+// Purpose: This function sends a response message to the DPC Over Lan
+// Context:
+// Returns: OK else error status code
+// Parameters:
+//
+// Notes: none
+*F*/
+
+ACCESN_STATUS
+SendTimedLanMessageResponse(
+ ImbPacket *ptr, /* pointer to the original request from EMP */
+ char *responseDataBuf,
+ int responseDataLen,
+ int timeOut /* how long to wait, in mSec units */
+ )
+{
+ BOOL status;
+ BYTE responseData[MAX_IMB_RESP_SIZE];
+ /* ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; */
+ DWORD respLength = sizeof( responseData );
+ BYTE requestData[MAX_IMB_RESP_SIZE];
+ ImbRequestBuffer * req = (ImbRequestBuffer *) requestData;
+ int i,j;
+
+ /*form the response packet first */
+ req->req.rsSa = BMC_SA;
+ if (IpmiVersion == IPMI_09_VERSION)
+ req->req.cmd = WRITE_EMP_BUFFER;
+ else
+ req->req.cmd = SEND_MESSAGE;
+ req->req.netFn = APP_NETFN;
+
+ /* After discussion with firmware team (Shailendra), the lun number needs to stay at 0
+ // even though the DPC over Lan firmware EPS states that the lun should be 1 for DPC
+ // Over Lan. - Simont (5/17/00) */
+ req->req.rsLun = 0;
+
+ i = 0;
+ if (IpmiVersion != IPMI_09_VERSION)
+ req->req.data[i++] = LAN_CHANNEL;
+
+ req->req.data[i++] = ptr->rqSa;
+ req->req.data[i++] = (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3));
+ if (IpmiVersion == IPMI_09_VERSION)
+ req->req.data[i++] = ((~(req->req.data[0] + req->req.data[1])) +1);
+ else
+ req->req.data[i++] = ((~(req->req.data[1] + req->req.data[2])) +1);
+
+ req->req.data[i++] = BMC_SA; /*though software is responding, we have to
+ //provide BMCs slave address as responder
+ //address. */
+
+ req->req.data[i++] = ( (ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3) );
+
+ req->req.data[i++] = ptr->cmd;
+ for ( j = 0 ; j < responseDataLen ; ++j,++i)
+ req->req.data[i] = responseDataBuf[j];
+
+ req->req.data[i] = 0;
+ if (IpmiVersion == IPMI_09_VERSION)
+ j = 0;
+ else
+ j = 1;
+ for ( ; j < ( i -3); ++j)
+ req->req.data[i] += req->req.data[j+3];
+ req->req.data[i] = ~(req->req.data[i]) +1;
+ ++i;
+ req->req.dataLength = i;
+
+ req->flags = 0;
+ req->timeOut = timeOut * 1000; /* convert to uSec units */
+
+
+ status = DeviceIoControl( hDevice,
+ IOCTL_IMB_SEND_MESSAGE,
+ requestData,
+ sizeof(requestData),
+ responseData,
+ sizeof( responseData ),
+ & respLength,
+ NULL
+ );
+
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
+#endif
+
+ if ( (status != TRUE) || (respLength != 1) || (responseData[0] != 0) )
+ {
+ return ACCESN_ERROR;
+ }
+ return ACCESN_OK;
+}
+
+/*This is not a API exported by the driver in stricter sense. It is
+//added to support EMP functionality. Upper level software could have
+//implemented this function.(pai 5/4/99) */
+/*///////////////////////////////////////////////////////////////////////////
+// SendTimedLanMessageResponse_Ex
+///////////////////////////////////////////////////////////////////////////// */
+
+/*F*
+// Name: SendTimedLanMessageResponse_Ex
+// Purpose: This function sends a response message to the DPC Over Lan
+// Context:
+// Returns: OK else error status code
+// Parameters:
+//
+// Notes: none
+*F*/
+
+ACCESN_STATUS
+SendTimedLanMessageResponse_Ex(
+ ImbPacket *ptr, /* pointer to the original request from EMP */
+ char *responseDataBuf,
+ int responseDataLen,
+ int timeOut , /* how long to wait, in mSec units */
+ BYTE sessionHandle, /*This is introduced in IPMI1.5,this is required to be sent in
+ //send message command as a parameter,which is then used by BMC
+ //to identify the correct DPC session to send the mesage to. */
+ BYTE channelNumber /*There are 3 different channels on which DPC communication goes on
+ //Emp - 1,Lan channel one - 6,Lan channel two(primary channel) - 7. */
+ )
+{
+ BOOL status;
+ BYTE responseData[MAX_IMB_RESP_SIZE];
+ /* ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; */
+ DWORD respLength = sizeof( responseData );
+ BYTE requestData[MAX_IMB_RESP_SIZE];
+ ImbRequestBuffer * req = (ImbRequestBuffer *) requestData;
+ int i,j;
+
+ /*form the response packet first */
+ req->req.rsSa = BMC_SA;
+ if (IpmiVersion == IPMI_09_VERSION)
+ req->req.cmd = WRITE_EMP_BUFFER;
+ else
+ req->req.cmd = SEND_MESSAGE;
+ req->req.netFn = APP_NETFN;
+
+ /* After discussion with firmware team (Shailendra), the lun number needs to stay at 0
+ // even though the DPC over Lan firmware EPS states that the lun should be 1 for DPC
+ // Over Lan. - Simont (5/17/00) */
+ req->req.rsLun = 0;
+
+ i = 0;
+
+ /*checking for the IPMI version & then assigning the channel number for Lan accordingly.
+ //This is the 1st byte of the SEND MESSAGE command. */
+ if (IpmiVersion == IPMI_10_VERSION)
+ req->req.data[i++] = LAN_CHANNEL;
+ else if (IpmiVersion == IPMI_15_VERSION)
+ req->req.data[i++] = channelNumber;
+
+ /*The second byte of data for SEND MESSAGE starts with session handle */
+ req->req.data[i++] = sessionHandle;
+
+ /*Then it is the response slave address for SEND MESSAGE. */
+ req->req.data[i++] = ptr->rqSa;
+
+ /*Then the net function + lun for SEND MESSAGE command. */
+ req->req.data[i++] = (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3));
+
+ /*Here the checksum is calculated.The checksum calculation starts after the channel number.
+ //so for the IPMI 1.5 version its a checksum of 3 bytes that is session handle,response slave
+ //address & netfun+lun. */
+ if (IpmiVersion == IPMI_09_VERSION)
+ req->req.data[i++] = ((~(req->req.data[0] + req->req.data[1])) +1);
+ else
+ {
+ if (IpmiVersion == IPMI_10_VERSION)
+ req->req.data[i++] = ((~(req->req.data[1] + req->req.data[2])) +1);
+ else
+ req->req.data[i++] = ((~(req->req.data[2]+ req->req.data[3])) +1);
+ }
+
+ /*This is the next byte of the message data for SEND MESSAGE command.It is the request
+ //slave address. */
+ req->req.data[i++] = BMC_SA; /*though software is responding, we have to
+ //provide BMC's slave address as responder
+ //address. */
+
+ /*This is just the sequence number,which is the next byte of data for SEND MESSAGE */
+ req->req.data[i++] = ( (ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3) );
+
+ /*The next byte is the command like get software ID(00). */
+ req->req.data[i++] = ptr->cmd;
+
+ /*after the cmd the data ,which is sent by DPC & is retrived using the get message earlier
+ // is sent back to DPC. */
+ for ( j = 0 ; j < responseDataLen ; ++j,++i)
+ req->req.data[i] = responseDataBuf[j];
+
+ req->req.data[i] = 0;
+
+ /*The last byte of data for SEND MESSAGE command is the check sum ,which is calculated
+ //from the next byte of the previous checksum that is the request slave address. */
+ if (IpmiVersion == IPMI_09_VERSION)
+ j = 0;
+ else
+ {
+ if (IpmiVersion == IPMI_10_VERSION)
+ j = 1;
+ else
+ j = 2;
+ }
+ for ( ; j < ( i -3); ++j)
+ req->req.data[i] += req->req.data[j+3];
+ req->req.data[i] = ~(req->req.data[i]) +1;
+ ++i;
+ req->req.dataLength = i;
+
+ /*The flags & timeouts are used by the driver internally */
+ req->flags = 0;
+ req->timeOut = timeOut * 1000; /* convert to uSec units */
+
+
+ status = DeviceIoControl( hDevice,
+ IOCTL_IMB_SEND_MESSAGE,
+ requestData,
+ sizeof(requestData),
+ responseData,
+ sizeof( responseData ),
+ & respLength,
+ NULL
+ );
+
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
+#endif
+
+ if ( (status != TRUE) || (respLength != 1) || (responseData[0] != 0) )
+ {
+ return ACCESN_ERROR;
+ }
+ return ACCESN_OK;
+}
+
+/*///////////////////////////////////////////////////////////////////////////
+// SendTimedImbpRequest
+///////////////////////////////////////////////////////////////////////////// */
+/*F*
+// Name: SendTimedImbpRequest
+// Purpose: This function sends a request for BMC implemented function
+// Context: Used by Upper level agents (sis modules) to access BMC implemented functionality.
+// Returns: OK else error status code
+// Parameters:
+// reqPtr
+// timeOut
+// respDataPtr
+// respLen
+// Notes: none
+*F*/
+ACCESN_STATUS
+SendTimedImbpRequest (
+ IMBPREQUESTDATA *reqPtr, /* request info and data */
+ int timeOut, /* how long to wait, in mSec units */
+ BYTE *respDataPtr, /* where to put response data */
+ int *respDataLen, /* how much response data there is */
+ BYTE *completionCode /* request status from dest controller */
+ )
+{
+ BYTE responseData[MAX_BUFFER_SIZE];
+ ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData;
+ DWORD respLength = sizeof( responseData );
+ BYTE requestData[MAX_BUFFER_SIZE];
+ ImbRequestBuffer * req = (ImbRequestBuffer *) requestData;
+ BOOL status;
+
+
+ req->req.rsSa = reqPtr->rsSa;
+ req->req.cmd = reqPtr->cmdType;
+ req->req.netFn = reqPtr->netFn;
+ req->req.rsLun = reqPtr->rsLun;
+ req->req.dataLength = reqPtr->dataLength;
+
+#ifndef NO_MACRO_ARGS
+ DEBUG("cmd=%02x, pdata=%p, datalen=%x\n", req->req.cmd,
+ reqPtr->data, reqPtr->dataLength );
+#endif
+ memcpy( req->req.data, reqPtr->data, reqPtr->dataLength );
+
+ req->flags = 0;
+ req->timeOut = timeOut * 1000; /* convert to uSec units */
+
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: rsSa 0x%x cmd 0x%x netFn 0x%x rsLun 0x%x\n", __FUNCTION__,
+ req->req.rsSa, req->req.cmd, req->req.netFn, req->req.rsLun);
+#endif
+
+
+ status = DeviceIoControl( hDevice,
+ IOCTL_IMB_SEND_MESSAGE,
+ requestData,
+ sizeof( requestData ),
+ & responseData,
+ sizeof( responseData ),
+ & respLength,
+ NULL
+ );
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: DeviceIoControl returned status = %d\n",__FUNCTION__, status);
+#endif
+#ifdef DBG_IPMI
+ printf("%s: rsSa %x cmd %x netFn %x lun %x, status=%d, cc=%x, rlen=%d\n",
+ __FUNCTION__, req->req.rsSa, req->req.cmd, req->req.netFn,
+ req->req.rsLun, status, resp->cCode, respLength );
+#endif
+
+ if( status != TRUE ) {
+ DWORD error;
+ error = GetLastError();
+ return ACCESN_ERROR;
+ }
+ if( respLength == 0 ) {
+ return ACCESN_ERROR;
+ }
+
+ /*
+ * give the caller his response
+ */
+ *completionCode = resp->cCode;
+ *respDataLen = 0;
+
+ if(( respLength > 1 ) && ( respDataPtr))
+ {
+ *respDataLen = respLength - 1;
+ memcpy( respDataPtr, resp->data, *respDataLen);
+ }
+
+
+ return ACCESN_OK;
+}
+
+
+/*/////////////////////////////////////////////////////////////////////////
+//SendAsyncImbpRequest
+/////////////////////////////////////////////////////////////////////////// */
+/*F*
+// Name: SendAsyncImbpRequest
+// Purpose: This function sends a request for Asynchronous IMB implemented function
+// Context: Used by Upper level agents (sis modules) to access Asynchronous IMB implemented functionality.
+// Returns: OK else error status code
+// Parameters:
+// reqPtr Pointer to Async IMB request
+// seqNo Sequence Munber
+// Notes: none
+*F*/
+ACCESN_STATUS
+SendAsyncImbpRequest (
+ IMBPREQUESTDATA *reqPtr, /* request info and data */
+ BYTE * seqNo /* sequence number used in creating IMB msg */
+ )
+{
+
+ BOOL status;
+ BYTE responseData[MAX_IMB_RESP_SIZE];
+ ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData;
+ DWORD respLength = sizeof( responseData );
+ BYTE requestData[MAX_IMB_RESP_SIZE];
+ ImbRequestBuffer * req = (ImbRequestBuffer *) requestData;
+
+ req->req.rsSa = reqPtr->rsSa;
+ req->req.cmd = reqPtr->cmdType;
+ req->req.netFn = reqPtr->netFn;
+ req->req.rsLun = reqPtr->rsLun;
+ req->req.dataLength = reqPtr->dataLength;
+
+ memcpy( req->req.data, reqPtr->data, reqPtr->dataLength );
+
+ req->flags = NO_RESPONSE_EXPECTED;
+ req->timeOut = 0; /* no timeouts for async sends */
+
+ status = DeviceIoControl( hDevice,
+ IOCTL_IMB_SEND_MESSAGE,
+ requestData,
+ sizeof( requestData ),
+ & responseData,
+ sizeof( responseData ),
+ & respLength,
+ NULL
+ );
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
+#endif
+
+ if( status != TRUE ) {
+ DWORD error;
+ error = GetLastError();
+ return ACCESN_ERROR;
+ }
+ if( respLength != 2 ) {
+ return ACCESN_ERROR;
+ }
+ /*
+ // give the caller his sequence number
+ */
+ *seqNo = resp->data[0];
+
+ return ACCESN_OK;
+
+}
+
+/*///////////////////////////////////////////////////////////////////////////
+//GetAsyncImbpMessage
+///////////////////////////////////////////////////////////////////////////// */
+/*F*
+// Name: GetAsyncImbpMessage
+// Purpose: This function gets the next available async message with a message id
+// greater than SeqNo. The message looks like an IMB packet
+// and the length and Sequence number is returned
+// Context: Used by Upper level agents (sis modules) to access Asynchronous IMB implemented functionality.
+// Returns: OK else error status code
+// Parameters:
+// msgPtr Pointer to Async IMB request
+// msgLen Length
+// timeOut Time to wait
+// seqNo Sequence Munber
+// Notes: none
+*F*/
+
+ACCESN_STATUS
+GetAsyncImbpMessage (
+ ImbPacket * msgPtr, /* request info and data */
+ DWORD *msgLen, /* IN - length of buffer, OUT - msg len */
+ DWORD timeOut, /* how long to wait for the message */
+ ImbAsyncSeq *seqNo, /* previously returned seq number */
+ /* (or ASYNC_SEQ_START) */
+ DWORD channelNumber
+ )
+{
+
+ BOOL status;
+ BYTE responseData[MAX_ASYNC_RESP_SIZE], lun;
+ ImbAsyncResponse * resp = (ImbAsyncResponse *) responseData;
+ DWORD respLength = sizeof( responseData );
+ ImbAsyncRequest req;
+
+ while(1)
+ {
+
+
+ if( (msgPtr == NULL) || (msgLen == NULL) || ( seqNo == NULL) )
+ return ACCESN_ERROR;
+
+ req.timeOut = timeOut * 1000; /* convert to uSec units */
+ req.lastSeq = *seqNo;
+
+
+ status = DeviceIoControl( hDevice,
+ IOCTL_IMB_GET_ASYNC_MSG,
+ & req,
+ sizeof( req ),
+ & responseData,
+ sizeof( responseData ),
+ & respLength,
+ NULL
+ );
+
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
+#endif
+
+ if( status != TRUE ) {
+ DWORD error = GetLastError();
+ /*
+ // handle "msg not available" specially. it is
+ // different from a random old error.
+ */
+ switch( error ) {
+ case IMB_MSG_NOT_AVAILABLE:
+ return ACCESN_END_OF_DATA;
+ default:
+ return ACCESN_ERROR;
+ }
+ return ACCESN_ERROR;
+ }
+ if( respLength < MIN_ASYNC_RESP_SIZE ) {
+ return ACCESN_ERROR;
+ }
+ respLength -= MIN_ASYNC_RESP_SIZE;
+
+ if( *msgLen < respLength ) {
+ return ACCESN_ERROR;
+ }
+
+
+ /*same code as in NT section */
+ if ( IpmiVersion == IPMI_09_VERSION)
+ {
+
+ switch( channelNumber) {
+ case IPMB_CHANNEL:
+ lun = IPMB_LUN;
+ break;
+
+ case EMP_CHANNEL:
+ lun = EMP_LUN;
+ break;
+
+ default:
+ lun = RESERVED_LUN;
+ break;
+ }
+
+ if ( (lun == RESERVED_LUN) ||
+ (lun != ((((ImbPacket *)(resp->data))->nfLn) & 0x3 ))
+ )
+ {
+ *seqNo = resp->thisSeq;
+ continue;
+ }
+
+
+ memcpy( msgPtr, resp->data, respLength );
+ *msgLen = respLength;
+
+ }
+ else
+ {
+ /* it is a 1.0 or above version */
+
+ if (resp->data[0] != (BYTE)channelNumber)
+ {
+ *seqNo = resp->thisSeq;
+ continue;
+ }
+
+ memcpy( msgPtr, &(resp->data[1]), respLength-1 );
+ *msgLen = respLength-1;
+
+
+ }
+
+ /*
+ // give the caller his sequence number
+ */
+ *seqNo = resp->thisSeq;
+
+ return ACCESN_OK;
+
+ } /*while (1) */
+}
+
+
+/*///////////////////////////////////////////////////////////////////////////
+//GetAsyncImbpMessage_Ex
+///////////////////////////////////////////////////////////////////////////// */
+/*F*
+// Name: GetAsyncImbpMessage_Ex
+// Purpose: This function gets the next available async message with a message id
+// greater than SeqNo. The message looks like an IMB packet
+// and the length and Sequence number is returned
+// Context: Used by Upper level agents (sis modules) to access Asynchronous IMB implemented functionality.
+// Returns: OK else error status code
+// Parameters:
+// msgPtr Pointer to Async IMB request
+// msgLen Length
+// timeOut Time to wait
+// seqNo Sequence Munber
+// Notes: none
+*F*/
+
+ACCESN_STATUS
+GetAsyncImbpMessage_Ex (
+ ImbPacket * msgPtr, /* request info and data */
+ DWORD *msgLen, /* IN - length of buffer, OUT - msg len */
+ DWORD timeOut, /* how long to wait for the message */
+ ImbAsyncSeq *seqNo, /* previously returned seq number */
+ /* (or ASYNC_SEQ_START) */
+ DWORD channelNumber,
+ BYTE * sessionHandle,
+ BYTE * privilege
+ )
+{
+
+ BOOL status;
+ BYTE responseData[MAX_ASYNC_RESP_SIZE], lun;
+ ImbAsyncResponse * resp = (ImbAsyncResponse *) responseData;
+ DWORD respLength = sizeof( responseData );
+ ImbAsyncRequest req;
+
+ while(1)
+ {
+
+
+ if( (msgPtr == NULL) || (msgLen == NULL) || ( seqNo == NULL) )
+ return ACCESN_ERROR;
+
+ req.timeOut = timeOut * 1000; /* convert to uSec units */
+ req.lastSeq = *seqNo;
+
+
+ status = DeviceIoControl( hDevice,
+ IOCTL_IMB_GET_ASYNC_MSG,
+ & req,
+ sizeof( req ),
+ & responseData,
+ sizeof( responseData ),
+ & respLength,
+ NULL
+ );
+
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
+#endif
+
+ if( status != TRUE ) {
+ DWORD error = GetLastError();
+ /*
+ // handle "msg not available" specially. it is
+ // different from a random old error.
+ */
+ switch( error ) {
+ case IMB_MSG_NOT_AVAILABLE:
+ return ACCESN_END_OF_DATA;
+ default:
+ return ACCESN_ERROR;
+ }
+ return ACCESN_ERROR;
+ }
+ if( respLength < MIN_ASYNC_RESP_SIZE ) {
+ return ACCESN_ERROR;
+ }
+ respLength -= MIN_ASYNC_RESP_SIZE;
+
+ if( *msgLen < respLength ) {
+ return ACCESN_ERROR;
+ }
+
+
+ /*same code as in NT section */
+ if ( IpmiVersion == IPMI_09_VERSION)
+ {
+
+ switch( channelNumber) {
+ case IPMB_CHANNEL:
+ lun = IPMB_LUN;
+ break;
+
+ case EMP_CHANNEL:
+ lun = EMP_LUN;
+ break;
+
+ default:
+ lun = RESERVED_LUN;
+ break;
+ }
+
+ if ( (lun == RESERVED_LUN) ||
+ (lun != ((((ImbPacket *)(resp->data))->nfLn) & 0x3 ))
+ )
+ {
+ *seqNo = resp->thisSeq;
+ continue;
+ }
+
+
+ memcpy( msgPtr, resp->data, respLength );
+ *msgLen = respLength;
+
+ }
+ else
+ {
+ if((sessionHandle ==NULL) || (privilege ==NULL))
+ return ACCESN_ERROR;
+
+ /*With the new IPMI version the get message command returns the
+ //channel number along with the privileges.The 1st 4 bits of the
+ //second byte of the response data for get message command represent
+ //the channel number & the last 4 bits are the privileges. */
+ *privilege = (resp->data[0] & 0xf0)>> 4;
+
+ if ((resp->data[0] & 0x0f) != (BYTE)channelNumber)
+ {
+ *seqNo = resp->thisSeq;
+ continue;
+ }
+
+
+ /*The get message command according to IPMI 1.5 spec now even
+ //returns the session handle.This is required to be captured
+ //as it is required as request data for send message command. */
+ *sessionHandle = resp->data[1];
+ memcpy( msgPtr, &(resp->data[2]), respLength-1 );
+ *msgLen = respLength-1;
+
+
+ }
+
+ /*
+ // give the caller his sequence number
+ */
+ *seqNo = resp->thisSeq;
+
+ return ACCESN_OK;
+
+ } /*while (1) */
+}
+
+
+
+/*//////////////////////////////////////////////////////////////////////////////
+//IsAsyncMessageAvailable
+///////////////////////////////////////////////////////////////////////////// */
+/*F*
+// Name: IsMessageAvailable
+// Purpose: This function waits for an Async Message
+//
+// Context: Used by Upper level agents access Asynchronous IMB based
+// messages
+// Returns: OK else error status code
+// Parameters:
+// eventId
+//
+// Notes: This call will block the calling thread if no Async events are
+// are available in the queue.
+//
+*F*/
+ACCESN_STATUS
+IsAsyncMessageAvailable (unsigned int eventId )
+{
+ int dummy;
+ int respLength = 0;
+ BOOL status;
+
+ /* confirm that app is not using a bad Id */
+
+
+ if ( AsyncEventHandle != (HANDLE) eventId)
+ return ACCESN_ERROR;
+
+ status = DeviceIoControl(hDevice,
+ IOCTL_IMB_CHECK_EVENT,
+ &AsyncEventHandle,
+ sizeof(HANDLE ),
+ &dummy,
+ sizeof(int),
+ (LPDWORD) & respLength,
+ NULL
+ );
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
+#endif
+
+ if( status != TRUE )
+ return ACCESN_ERROR;
+
+
+ return ACCESN_OK;
+}
+
+
+/*I have retained this commented code because later we may want to use
+//DPC message specific Processing (pai 11/21) */
+
+#ifdef NOT_COMPILED_BUT_LEFT_HERE_FOR_NOW
+
+/*//////////////////////////////////////////////////////////////////////////////
+//GetAsyncDpcMessage
+///////////////////////////////////////////////////////////////////////////// */
+/*F*
+// Name: GetAsyncDpcMessage
+// Purpose: This function gets the next available async message from
+// the DPC client.
+//
+// Context: Used by Upper level agents access Asynchronous IMB based
+// messages sent by the DPC client.
+// Returns: OK else error status code
+// Parameters:
+// msgPtr Pointer to Async IMB request
+// msgLen Length
+// timeOut Time to wait
+// seqNo Sequence Munber
+// Notes: This call will block the calling thread if no Async events are
+// are available in the queue.
+//
+*F*/
+
+ACCESN_STATUS
+GetAsyncDpcMessage (
+ ImbPacket * msgPtr, /* request info and data */
+ DWORD * msgLen, /* IN - length of buffer, OUT - msg len */
+ DWORD timeOut, /* how long to wait for the message */
+ ImbAsyncSeq * seqNo, /* previously returned seq number (or ASYNC_SEQ_START) */
+ )
+{
+ BOOL status;
+ BYTE responseData[MAX_ASYNC_RESP_SIZE];
+ ImbAsyncResponse * resp = (ImbAsyncResponse *) responseData;
+ DWORD respLength = sizeof( responseData );
+ ImbAsyncRequest req;
+
+ if( msgPtr == NULL || msgLen == NULL || seqNo == NULL )
+ return ACCESN_ERROR;
+
+ req.lastSeq = *seqNo;
+
+
+ hEvt = CreateEvent (NULL, TRUE, FALSE, NULL) ;
+ if (!hEvt) {
+ return ACCESN_ERROR;
+ }
+
+ status = DeviceIoControl( hDevice,
+ IOCTL_IMB_GET_DPC_MSG,
+ & req,
+ sizeof( req ),
+ & responseData,
+ sizeof( responseData ),
+ & respLength,
+ &ovl
+ );
+
+ if( status != TRUE ) {
+ DWORD error = GetLastError();
+ /*
+ // handle "msg not available" specially. it is different from
+ // a random old error.
+ //
+ */
+ if (!status)
+ {
+ switch (error )
+ {
+ case ERROR_IO_PENDING:
+
+ WaitForSingleObject (hEvt, INFINITE) ;
+ ResetEvent (hEvt) ;
+ break;
+
+ case IMB_MSG_NOT_AVAILABLE:
+
+ CloseHandle(hEvt);
+ return ACCESN_END_OF_DATA;
+
+ default:
+ CloseHandle(hEvt);
+ return ACCESN_ERROR;
+
+ }
+ }
+
+
+
+ if (
+ ( GetOverlappedResult(hDevice,
+ &ovl,
+ (LPDWORD)&respLength,
+ TRUE
+ ) == 0 ) || (respLength <= 0)
+ )
+
+ {
+
+ CloseHandle(hEvt);
+ return ACCESN_ERROR;
+
+ }
+
+
+ }
+
+ if( respLength < MIN_ASYNC_RESP_SIZE ) {
+ CloseHandle(hEvt);
+ return ACCESN_ERROR;
+ }
+
+ respLength -= MIN_ASYNC_RESP_SIZE;
+
+ if( *msgLen < respLength ) {
+
+ /* The following code should have been just return ACCESN_out_of_range */
+ CloseHandle(hEvt);
+ return ACCESN_ERROR;
+ }
+
+ memcpy( msgPtr, resp->data, respLength );
+
+ *msgLen = respLength;
+ /*
+ // give the caller his sequence number
+ */
+ *seqNo = resp->thisSeq;
+
+ CloseHandle(hEvt);
+
+
+ return ACCESN_OK;
+
+}
+#endif /*NOT_COMPILED_BUT_LEFT_HERE_FOR_NOW*/
+
+
+
+/*/////////////////////////////////////////////////////////////////////////////
+//RegisterForImbAsyncMessageNotification
+///////////////////////////////////////////////////////////////////////////// */
+/*F*
+// Name: RegisterForImbAsyncMessageNotification
+// Purpose: This function Registers the calling application
+// for Asynchronous notification when a sms message
+// is available with the IMB driver.
+//
+// Context: Used by Upper level agents to know that an async
+// SMS message is available with the driver.
+// Returns: OK else error status code
+// Parameters:
+// handleId pointer to the registration handle
+//
+// Notes: The calling application should use the returned handle to
+// get the Async messages..
+*F*/
+ACCESN_STATUS
+RegisterForImbAsyncMessageNotification (unsigned int *handleId)
+
+{
+ BOOL status;
+ DWORD respLength ;
+ int dummy;
+
+ /*allow only one app to register */
+
+ if( (handleId == NULL ) || (AsyncEventHandle) )
+ return ACCESN_ERROR;
+
+
+ status = DeviceIoControl(hDevice,
+ IOCTL_IMB_REGISTER_ASYNC_OBJ,
+ &dummy,
+ sizeof( int ),
+ &AsyncEventHandle,
+ (DWORD)sizeof(HANDLE ),
+ (LPDWORD) & respLength,
+ NULL
+ );
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
+#endif
+
+ if( (respLength != sizeof(int)) || (status != TRUE ))
+ return ACCESN_ERROR;
+
+ /* printf("imbapi: Register handle = %x\n",AsyncEventHandle); *//*++++*/
+ *handleId = (unsigned int) AsyncEventHandle;
+
+#ifndef NO_MACRO_ARGS
+ DEBUG("handleId = %x AsyncEventHandle %x\n", *handleId, AsyncEventHandle);
+#endif
+ return ACCESN_OK;
+}
+
+
+
+
+
+/*/////////////////////////////////////////////////////////////////////////////
+//UnRegisterForImbAsyncMessageNotification
+///////////////////////////////////////////////////////////////////////////// */
+/*F*
+// Name: UnRegisterForImbAsyncMessageNotification
+// Purpose: This function un-registers the calling application
+// for Asynchronous notification when a sms message
+// is available with the IMB driver.
+//
+// Context: Used by Upper level agents to un-register
+// for async. notification of sms messages
+// Returns: OK else error status code
+// Parameters:
+// handleId pointer to the registration handle
+// iFlag value used to determine where this function was called from
+// _it is used currently on in NetWare environment_
+//
+// Notes:
+*F*/
+ACCESN_STATUS
+UnRegisterForImbAsyncMessageNotification (unsigned int handleId, int iFlag)
+
+{
+ BOOL status;
+ DWORD respLength ;
+ int dummy;
+
+ iFlag = iFlag; /* to keep compiler happy We are not using this flag*/
+
+ if ( AsyncEventHandle != (HANDLE) handleId)
+ return ACCESN_ERROR;
+
+ status = DeviceIoControl(hDevice,
+ IOCTL_IMB_DEREGISTER_ASYNC_OBJ,
+ &AsyncEventHandle,
+ (DWORD)sizeof(HANDLE ),
+ &dummy,
+ (DWORD)sizeof(int ),
+ (LPDWORD) & respLength,
+ NULL
+ );
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
+#endif
+
+ if( status != TRUE )
+ return ACCESN_ERROR;
+
+ return ACCESN_OK;
+}
+
+
+/*///////////////////////////////////////////////////////////////////////////
+// SetShutDownCode
+///////////////////////////////////////////////////////////////////////////// */
+/*F*
+// Name: SetShutDownCode
+// Purpose: To set the shutdown action code
+// Context: Called by the System Control Subsystem
+// Returns: none
+// Parameters:
+// code shutdown action code which can be either
+// SD_NO_ACTION, SD_RESET, SD_POWER_OFF as defined in imb_if.h
+*F*/
+
+ACCESN_STATUS
+SetShutDownCode (
+ int delayTime, /* time to delay in 100ms units */
+ int code /* what to do when time expires */
+ )
+{
+ DWORD retLength;
+ BOOL status;
+ ShutdownCmdBuffer cmd;
+
+ /*
+ // If Imb driver is not present return AccessFailed
+ */
+ if(hDevice == INVALID_HANDLE_VALUE)
+ return ACCESN_ERROR;
+
+ cmd.code = code;
+ cmd.delayTime = delayTime;
+
+ status = DeviceIoControl( hDevice,
+ IOCTL_IMB_SHUTDOWN_CODE,
+ & cmd,
+ sizeof( cmd ),
+ NULL,
+ 0,
+ & retLength,
+ NULL
+ );
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status);
+#endif
+
+ if(status == TRUE)
+ return ACCESN_OK;
+ else
+ return ACCESN_ERROR;
+}
+
+/*/////////////////////////////////////////////////////////////////////////
+// MapPhysicalMemory
+/////////////////////////////////////////////////////////////////////////// */
+/*F*
+// Name: MapPhysicalMemory
+// Purpose: This function maps specified range of physical memory in calling
+// pocesse's address space
+// Context: Used by Upper level agents (sis modules) to access
+// system physical memory
+// Returns: ACCESN_OK else error status code
+// Parameters:
+//
+// startAddress starting physical address of the memory to be mapped
+// addressLength length of the physical memory to be mapped
+// virtualAddress pointer to the mapped virtual address
+// Notes: none
+*F*/
+/*///////////////////////////////////////////////////////////////////////////
+// UnmapPhysicalMemory
+//////////////////////////////////////////////////////////////////////////// */
+/*F*
+// Name: UnMapPhysicalMemory
+// Purpose: This function unmaps the previously mapped physical memory
+// Context: Used by Upper level agents (sis modules)
+// Returns: ACCESN_OK else error status code
+// Parameters:
+//
+// addressLength length of the physical memory to be mapped
+// virtualAddress pointer to the mapped virtual address
+// Notes: none
+*F*/
+#ifdef WIN32
+ACCESN_STATUS
+MapPhysicalMemory (
+ int startAddress, // physical address to map in
+ int addressLength, // how much to map
+ int *virtualAddress // where it got mapped to
+ )
+{
+ DWORD retLength;
+ BOOL status;
+ PHYSICAL_MEMORY_INFO pmi;
+
+ if (startAddress == 0 || addressLength <= 0)
+ return ACCESN_OUT_OF_RANGE;
+
+ pmi.InterfaceType = Internal;
+ pmi.BusNumber = 0;
+ pmi.BusAddress.HighPart = (LONG)0x0;
+ pmi.BusAddress.LowPart = (LONG)startAddress;
+ pmi.AddressSpace = (LONG) 0;
+ pmi.Length = addressLength;
+
+ status = DeviceIoControl ( hDevice,
+ IOCTL_IMB_MAP_MEMORY,
+ & pmi,
+ sizeof(PHYSICAL_MEMORY_INFO),
+ virtualAddress,
+ sizeof(PVOID),
+ & retLength,
+ 0
+ );
+ if( status == TRUE ) {
+ return ACCESN_OK;
+ } else {
+ return ACCESN_ERROR;
+ }
+}
+
+ACCESN_STATUS
+UnmapPhysicalMemory (
+ int virtualAddress, // what memory to unmap
+ int Length )
+{
+ DWORD retLength;
+ BOOL status;
+
+ status = DeviceIoControl ( hDevice,
+ IOCTL_IMB_UNMAP_MEMORY,
+ & virtualAddress,
+ sizeof(PVOID),
+ NULL,
+ 0,
+ & retLength,
+ 0
+ );
+
+ if( status == TRUE ) {
+ return ACCESN_OK;
+ } else {
+ return ACCESN_ERROR;
+ }
+}
+
+#else /*Linux, SCO, UNIX, etc.*/
+
+ACCESN_STATUS
+MapPhysicalMemory(int startAddress,int addressLength, int *virtualAddress )
+{
+ int fd;
+ unsigned int length = addressLength;
+ off_t startpAddress = (off_t)startAddress;
+ unsigned int diff;
+ caddr_t startvAddress;
+
+ if ((startAddress == 0) || (addressLength <= 0))
+ return ACCESN_ERROR;
+
+ if ( (fd = open("/dev/mem", O_RDONLY)) < 0) {
+ char buf[128];
+
+ sprintf(buf,"%s %s: open(%s) failed",
+ __FILE__,__FUNCTION__,IMB_DEVICE);
+ perror(buf);
+ return ACCESN_ERROR ;
+ }
+
+ /* aliging the offset to a page boundary and adjusting the length */
+ diff = (int)startpAddress % PAGESIZE;
+ startpAddress -= diff;
+ length += diff;
+
+ if ( (startvAddress = mmap( (caddr_t)0,
+ length,
+ PROT_READ,
+ MAP_SHARED,
+ fd,
+ startpAddress
+ ) ) == (caddr_t)-1)
+ {
+ char buf[128];
+
+ sprintf(buf,"%s %s: mmap failed", __FILE__,__FUNCTION__);
+ perror(buf);
+ close(fd);
+ return ACCESN_ERROR;
+ }
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: mmap of 0x%x success\n",__FUNCTION__,startpAddress);
+#endif
+#ifdef LINUX_DEBUG_MAX
+/* dont want this memory dump for normal level of debugging.
+// So, I have put it under a stronger debug symbol. mahendra */
+
+ for(i=0; i < length; i++)
+ {
+ printf("0x%x ", (startvAddress[i]));
+ if(isascii(startvAddress[i])) {
+ printf("%c ", (startvAddress[i]));
+ }
+ }
+#endif /*LINUX_DEBUG_MAX */
+
+ *virtualAddress = (long)(startvAddress + diff);
+ close(fd);
+ return ACCESN_OK;
+}
+
+ACCESN_STATUS
+UnmapPhysicalMemory( int virtualAddress, int Length )
+{
+ unsigned int diff = 0;
+
+ /* page align the virtual address and adjust length accordingly */
+ diff = ((unsigned int) virtualAddress) % PAGESIZE;
+ virtualAddress -= diff;
+ Length += diff;
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: calling munmap(0x%x,%d)\n",__FUNCTION__,virtualAddress,Length);
+#endif
+
+ if(munmap(&virtualAddress, Length) != 0)
+ {
+ char buf[128];
+
+ sprintf(buf,"%s %s: munmap failed", __FILE__,__FUNCTION__);
+ perror(buf);
+ return ACCESN_ERROR;
+
+ }
+#ifndef NO_MACRO_ARGS
+ DEBUG("%s: munmap(0x%x,%d) success\n",__FUNCTION__,virtualAddress,Length);
+#endif
+
+ return ACCESN_OK;
+}
+#endif /*unix*/
+
+
+/*/////////////////////////////////////////////////////////////////////////////
+// GetIpmiVersion
+//////////////////////////////////////////////////////////////////////////// */
+
+/*F*
+// Name: GetIpmiVersion
+// Purpose: This function returns current IPMI version
+// Context:
+// Returns: IPMI version
+// Parameters:
+// reqPtr
+// timeOut
+// respDataPtr
+// respLen
+// Notes: svuppula
+*F*/
+BYTE GetIpmiVersion()
+{
+ return IpmiVersion;
+}
+
diff --git a/src/plugins/imb/imbapi.h b/src/plugins/imb/imbapi.h
new file mode 100644
index 0000000..74975c6
--- /dev/null
+++ b/src/plugins/imb/imbapi.h
@@ -0,0 +1,652 @@
+/*M*
+// PVCS:
+// $Workfile: imb_api.h $
+// $Revision: 1.2 $
+// $Modtime: Jul 22 2002 16:40:32 $
+// $Author: iceblink $
+//
+// Combined include files needed for imbapi.c
+//
+ *M*/
+/*----------------------------------------------------------------------*
+The BSD License
+Copyright (c) 2002, Intel Corporation
+All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ a.. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ b.. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ c.. Neither the name of Intel Corporation nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *----------------------------------------------------------------------*/
+#ifndef _WINDEFS_H
+#define _WINDEFS_H
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef NULL
+#define NULL 0
+#endif
+#ifndef WIN32
+/* WIN32 defines this in stdio.h */
+#ifndef _WCHAR_T
+#define _WCHAR_T
+typedef long wchar_t;
+#endif
+#endif
+#define far
+#define near
+#define FAR far
+#define NEAR near
+#ifndef CONST
+#define CONST const
+#endif
+typedef unsigned long DWORD;
+typedef int BOOL;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef float FLOAT;
+typedef FLOAT *PFLOAT;
+typedef BOOL near *PBOOL;
+typedef BOOL far *LPBOOL;
+typedef BYTE near *PBYTE;
+typedef BYTE far *LPBYTE;
+typedef int near *PINT;
+typedef int far *LPINT;
+typedef WORD near *PWORD;
+typedef WORD far *LPWORD;
+typedef long far *LPLONG;
+typedef DWORD near *PDWORD;
+typedef DWORD far *LPDWORD;
+typedef void far *LPVOID;
+typedef CONST void far *LPCVOID;
+typedef int INT;
+typedef unsigned int UINT;
+typedef unsigned int *PUINT;
+typedef DWORD NTSTATUS;
+/*
+ File structures
+*/
+#ifndef WIN32
+typedef struct _OVERLAPPED {
+ DWORD Internal;
+ DWORD InternalHigh;
+ DWORD Offset;
+ DWORD OffsetHigh;
+/* HANDLE hEvent; */
+} OVERLAPPED, *LPOVERLAPPED;
+#endif
+/*
+ * Data structure redefines
+ */
+typedef char CHAR;
+typedef short SHORT;
+typedef long LONG;
+typedef char * PCHAR;
+typedef short * PSHORT;
+typedef long * PLONG;
+typedef unsigned char UCHAR;
+typedef unsigned short USHORT;
+typedef unsigned long ULONG;
+typedef unsigned char * PUCHAR;
+typedef unsigned short * PUSHORT;
+typedef unsigned long * PULONG;
+typedef char CCHAR;
+typedef short CSHORT;
+typedef ULONG CLONG;
+typedef CCHAR * PCCHAR;
+typedef CSHORT * PCSHORT;
+typedef CLONG * PCLONG;
+typedef void * PVOID;
+#ifndef WIN32
+typedef void VOID;
+typedef struct _LARGE_INTEGER {
+ ULONG LowPart;
+ LONG HighPart;
+} LARGE_INTEGER;
+typedef struct _ULARGE_INTEGER {
+ ULONG LowPart;
+ ULONG HighPart;
+} ULARGE_INTEGER;
+#endif
+typedef LARGE_INTEGER * PLARGE_INTEGER;
+typedef LARGE_INTEGER PHYSICAL_ADDRESS;
+typedef LARGE_INTEGER * PPHYSICAL_ADDRESS;
+typedef ULARGE_INTEGER * PULARGE_INTEGER;
+typedef UCHAR BOOLEAN;
+typedef BOOLEAN *PBOOLEAN;
+typedef wchar_t WCHAR;
+typedef WCHAR *PWCHAR, *PWSTR;
+typedef CONST WCHAR *LPCWSTR, *PCWSTR;
+
+#ifndef _SYS_TYPES_H
+#ifndef _CADDR_T
+#define _CADDR_T
+ typedef char * caddr_t;
+#endif
+#endif
+/*
+ Unicode strings are counted 16-bit character strings. If they are
+ NULL terminated, Length does not include trailing NULL.
+*/
+typedef struct _UNICODE_STRING {
+ USHORT Length;
+ USHORT MaximumLength;
+ PWSTR Buffer;
+} UNICODE_STRING;
+typedef UNICODE_STRING *PUNICODE_STRING;
+#define UNICODE_NULL ((WCHAR)0) /* winnt*/
+#define IN /* */
+#define OUT /* */
+#define OPTIONAL /* */
+
+#ifndef WIN32
+#define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field))
+#define UNREFERENCED_PARAMETER(x)
+typedef int HANDLE;
+#define INVALID_HANDLE_VALUE ((HANDLE)-1)
+#endif
+typedef HANDLE *PHANDLE;
+/*
+ Define the method codes for how buffers are passed for I/O and FS controls
+*/
+#define METHOD_BUFFERED 0
+/*
+ Define the access check value for any access
+ The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in
+ ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these
+ constants *MUST* always be in sync.
+*/
+#define FILE_ANY_ACCESS 0
+/*
+ These are the generic rights.
+*/
+#define MAX_PATH 260
+#define GetLastError() (NTstatus.Status)
+/*
+ Macro definition for defining IOCTL and FSCTL function control codes. Note
+ that function codes 0-2047 are reserved for Microsoft Corporation, and
+ 2048-4095 are reserved for customers.
+*/
+/*
+ * Linux drivers expect ioctls defined using macros defined in ioctl.h.
+ * So, instead of using the CTL_CODE defined for NT and UW, I define CTL_CODE
+ * using these macros. That way imb_if.h, where the ioctls are defined get
+ * to use the correct ioctl command we expect.
+ * Notes: I am using the generic _IO macro instead of the more specific
+ * ones. The macros expect 8bit entities, so I am cleaning what is sent to
+ * us from imb_if.h - Mahendra
+ */
+#ifndef WIN32
+#define CTL_CODE(DeviceType, Function, Method, Access)\
+ _IO(DeviceType & 0x00FF, Function & 0x00FF)
+#else
+#define CTL_CODE( DeviceType, Function, Method, Access ) ((ULONG)( \
+ ((ULONG)(DeviceType) << 16) | ((ULONG)(Access) << 14) | ((ULONG)(Function) << 2) | ((ULONG)Method) \
+))
+#endif
+#endif /*_WINDEFS_H */
+/*----------------------------------------------------------------------*/
+#ifndef _SMI_H
+#define _SMI_H
+#define SMI_Version1_00 0x00001000
+struct smi {
+ DWORD smi_VersionNo;
+ DWORD smi_Reserved1;
+ DWORD smi_Reserved2;
+ LPVOID ntstatus; /* address of NT status block*/
+ LPVOID lpvInBuffer; /* address of buffer for input data*/
+ DWORD cbInBuffer; /* size of input buffer*/
+ LPVOID lpvOutBuffer; /* address of output buffer*/
+ DWORD cbOutBuffer; /* size of output buffer*/
+ LPDWORD lpcbBytesReturned; /* address of actual bytes of output*/
+ LPOVERLAPPED lpoOverlapped; /* address of overlapped structure*/
+};
+#ifndef STATUS_SUCCESS
+typedef struct _IO_STATUS_BLOCK {
+ ULONG Status;
+ ULONG Information;
+} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
+/*
+ * I2C ioctl's return NTStatus codes
+ */
+#define STATUS_SUCCESS (0x00000000U)
+#define STATUS_UNSUCCESSFUL (0xC0000001U)
+#define STATUS_DEVICE_BUSY (0x80000011U)
+#ifndef WIN32
+#define STATUS_PENDING (0x00000103U)
+// see <win2000ddk>\inc\winnt.h(1171)
+#endif
+#define STATUS_INVALID_PARAMETER (0xC000000DU)
+#define STATUS_INVALID_DEVICE_REQUEST (0xC0000010U)
+#define STATUS_BUFFER_TOO_SMALL (0xC0000023U)
+#define STATUS_FILE_CLOSED (0xC0000128U)
+#define STATUS_INSUFFICIENT_RESOURCES (0xC000009AU)
+#define STATUS_NO_DATA_DETECTED (0x80000022U)
+#define STATUS_NO_SUCH_DEVICE (0xC000000EU)
+#define STATUS_ALLOTTED_EXCEEDED (0xC000000FU)
+#define STATUS_IO_DEVICE_ERROR (0xC0000185U)
+#define STATUS_TOO_MANY_OPEN_FILES (0xC000011FU)
+#define STATUS_ACCESS_DENIED (0xC0000022U)
+#define STATUS_BUFFER_OVERFLOW (0x80000005U)
+#define STATUS_CANCELLED (0xC0000120U)
+#endif /* STATUS_SUCCESS*/
+#endif /* _SMI_H*/
+/*----------------------------------------------------------------------*/
+#ifndef IMB_IF__
+#define IMB_IF__
+/*
+ * This is the structure passed in to the IOCTL_IMB_SHUTDOWN_CODE request
+ */
+typedef struct {
+ int code;
+ int delayTime;
+} ShutdownCmdBuffer;
+#define SD_NO_ACTION 0
+#define SD_RESET 1
+#define SD_POWER_OFF 2
+#pragma pack(1)
+/*
+ * This is the generic IMB packet format, the final checksum cant be
+ * represented in this structure and will show up as the last data byte
+ */
+typedef struct {
+ BYTE rsSa;
+ BYTE nfLn;
+ BYTE cSum1;
+ BYTE rqSa;
+ BYTE seqLn;
+ BYTE cmd;
+ BYTE data[1];
+} ImbPacket;
+#define MIN_IMB_PACKET_SIZE 7
+#define MAX_IMB_PACKET_SIZE 33
+/*
+ * This is the standard IMB response format where the first byte of
+ * IMB packet data is interpreted as a command completion code.
+*/
+typedef struct {
+ BYTE rsSa;
+ BYTE nfLn;
+ BYTE cSum1;
+ BYTE rqSa;
+ BYTE seqLn;
+ BYTE cmd;
+ BYTE cCode;
+ BYTE data[1];
+} ImbRespPacket;
+#define MIN_IMB_RESPONSE_SIZE 7 /* min packet + completion code */
+#define MAX_IMB_RESPONSE_SIZE MAX_IMB_PACKET_SIZE
+/************************
+ * ImbRequestBuffer
+ ************************/
+/*D*
+// Name: ImbRequestBuffer
+// Purpose: Structure definition for holding IMB message data
+// Context: Used by SendTimedImbpMessage and SendTimedI2cMessge
+// functions in the library interface. In use, it is overlayed on a
+// char buffer of size MIN_IMB_REQ_BUF_SIZE +
+// Fields:
+// respBufSize size of the response buffer
+//
+// timeout timeout value in milli seconds
+//
+// req body of request to send
+//
+*D*/
+typedef struct {
+ BYTE rsSa;
+ BYTE cmd;
+ BYTE netFn;
+ BYTE rsLun;
+ BYTE dataLength;
+ BYTE data[1];
+} ImbRequest;
+typedef struct {
+ DWORD flags; /* request flags*/
+#define NO_RESPONSE_EXPECTED 0x01 /*dont wait around for an IMB response*/
+ DWORD timeOut; /* in uSec units*/
+ ImbRequest req; /* message buffer*/
+} ImbRequestBuffer;
+#define MIN_IMB_REQ_BUF_SIZE 13 /* a buffer without any request data*/
+/************************
+ * ImbResponseBuffer
+ ************************/
+/*D*
+// Name: ImbResponseBuffer
+// Purpose: Structure definition for response of a previous send
+// Context: Used by DeviceIoControl to pass the message to be sent to
+// MISSMIC port
+// Fields:
+// cCode completion code returned by firmware
+// data buffer for response data from firmware
+*D*/
+typedef struct {
+ BYTE cCode;
+ BYTE data[1];
+} ImbResponseBuffer;
+#define MIN_IMB_RESP_BUF_SIZE 1
+#define MAX_IMB_RESP_SIZE (MIN_IMB_RESP_BUF_SIZE + MAX_IMB_RESPONSE_SIZE)
+#pragma pack()
+/*
+ * Async message access structures and types
+ */
+typedef DWORD ImbAsyncSeq;
+/*
+ * This is the structure passed in to IOCTL_IMB_GET_ASYNC_MSG
+*/
+typedef struct {
+ DWORD timeOut;
+ ImbAsyncSeq lastSeq;
+} ImbAsyncRequest;
+#define ASYNC_SEQ_START 0
+typedef struct {
+ ImbAsyncSeq thisSeq;
+ BYTE data[1];
+} ImbAsyncResponse;
+#define MIN_ASYNC_RESP_SIZE sizeof( ImbAsyncSeq )
+#define MAX_ASYNC_RESP_SIZE (MIN_ASYNC_RESP_SIZE + MAX_IMB_PACKET_SIZE)
+/*
+** Driver Ioctls
+** In Linux, these calculate to:
+** IOCTL_IMB_SEND_MESSAGE =1082
+** IOCTL_IMB_GET_ASYNC_MSG =1088
+** IOCTL_IMB_MAP_MEMORY =108e
+** IOCTL_IMB_UNMAP_MEMORY =1090
+** IOCTL_IMB_SHUTDOWN_CODE =1092
+** IOCTL_IMB_REGISTER_ASYNC_OBJ =1098
+** IOCTL_IMB_DEREGISTER_ASYNC_OBJ=109a
+** IOCTL_IMB_CHECK_EVENT =109c
+** IOCTL_IMB_POLL_ASYNC =1094
+*/
+#define FILE_DEVICE_IMB 0x00008010
+#define IOCTL_IMB_BASE 0x00000880
+#define IOCTL_IMB_SEND_MESSAGE CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 2), METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_IMB_GET_ASYNC_MSG CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 8), METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_IMB_MAP_MEMORY CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 14), METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_IMB_UNMAP_MEMORY CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 16), METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_IMB_SHUTDOWN_CODE CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 18), METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_IMB_REGISTER_ASYNC_OBJ CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 24), METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_IMB_DEREGISTER_ASYNC_OBJ CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 26), METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_IMB_CHECK_EVENT CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 28), METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_IMB_POLL_ASYNC CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 20), METHOD_BUFFERED, FILE_ANY_ACCESS)
+#endif /* IMB_IF__ */
+/*----------------------------------------------------------------------*/
+/* No asynchronous messages available */
+#define IMB_MSG_NOT_AVAILABLE ((NTSTATUS)0xE0070012L)
+#ifdef IMBLOG_H__
+/* Define the facility codes */
+#define FACILITY_RPC_STUBS 0x3
+#define FACILITY_RPC_RUNTIME 0x2
+#define FACILITY_IO_ERROR_CODE 0x4
+#define IMB_IO_ERROR_CODE 0x7
+
+#define STATUS_SEVERITY_WARNING 0x2
+#define STATUS_SEVERITY_SUCCESS 0x0
+#define STATUS_SEVERITY_INFORMATIONAL 0x1
+#define STATUS_SEVERITY_ERROR 0x3
+/* Not enough memory for internal storage of device %1. */
+#define INSUFFICIENT_RESOURCES ((NTSTATUS)0xE0070001L)
+
+#define INVALID_INPUT_BUFFER ((NTSTATUS)0xE0070002L)
+
+#define INVALID_OUTPUT_BUFFER ((NTSTATUS)0xE0070003L)
+
+#define IMB_SEND_TIMEOUT ((NTSTATUS)0xE0070004L)
+
+#define IMB_RECEIVE_TIMEOUT ((NTSTATUS)0xE0070005L)
+
+#define IMB_IF_SEND_TIMEOUT ((NTSTATUS)0xE0070006L)
+
+#define IMB_IF_RECEIVE_TIMEOUT ((NTSTATUS)0xE0040007L)
+
+#define HARDWARE_FAILURE ((NTSTATUS)0xE0040008L)
+
+#define DRIVER_FAILURE ((NTSTATUS)0xE0040009L)
+
+#define IMB_INVALID_IF_RESPONSE ((NTSTATUS)0xE004000AL)
+
+#define IMB_INVALID_PACKET ((NTSTATUS)0xE004000BL)
+
+#define IMB_RESPONSE_DATA_OVERFLOW ((NTSTATUS)0xE004000CL)
+
+#define IMB_INVALID_REQUEST ((NTSTATUS)0xE007000DL)
+
+#define INVALID_DRIVER_IOCTL ((NTSTATUS)0xE007000EL)
+
+#define INVALID_DRIVER_REQUEST ((NTSTATUS)0xE007000FL)
+
+#define IMB_CANT_GET_SMS_BUFFER ((NTSTATUS)0xE0070010L)
+
+#define INPUT_BUFFER_TOO_SMALL ((NTSTATUS)0xE0070011L)
+
+#define IMB_SEND_ERROR ((NTSTATUS)0xE0070013L)
+#endif /* IMBLOG_H__ */
+/*----------------------------------------------------------------------*/
+#ifndef IMBAPI_H__
+#define IMBAPI_H__
+#include <sys/types.h>
+#define WRITE_READ_I2C 0x52
+#define WRITE_EMP_BUFFER 0x7a
+#define GET_DEVICE_ID 0x1
+#define SEND_MESSAGE 0x34
+#define BMC_SA 0x20
+#define BMC_LUN 0
+#define APP_NETFN 0x06
+#define IPMI_09_VERSION 0x90
+#define IPMI_10_VERSION 0x01
+
+#define IPMI_15_VERSION 0x51
+
+#ifndef IPMI10_GET_DEVICE_ID_RESP_LENGTH
+#define IPMI10_GET_DEVICE_ID_RESP_LENGTH 12
+#endif
+
+#define IPMB_CHANNEL 0x0
+#define EMP_CHANNEL 0x1
+#define LAN_CHANNEL 0x2
+#define RESERVED_LUN 0x3
+#define IPMB_LUN 0x2
+#define EMP_LUN 0x0
+
+#define PUBLIC_BUS 0
+
+#define BMC_CONTROLLER 0x20
+#define FPC_CONTROLLER 0x22
+typedef enum {
+ ACCESN_OK,
+ ACCESN_ERROR,
+ ACCESN_OUT_OF_RANGE,
+ ACCESN_END_OF_DATA,
+ ACCESN_UNSUPPORTED,
+ ACCESN_INVALID_TRANSACTION,
+ ACCESN_TIMED_OUT
+} ACCESN_STATUS;
+#pragma pack(1)
+/*
+ * Request structure provided to SendTimedImbpRequest()
+*/
+typedef struct {
+ unsigned char cmdType;
+ unsigned char rsSa;
+ unsigned char busType;
+ unsigned char netFn;
+ unsigned char rsLun;
+ unsigned char * data;
+ int dataLength;
+} IMBPREQUESTDATA;
+/*
+ * Request structure provided to SendTimedI2cRequest()
+*/
+typedef struct {
+ unsigned char rsSa;
+ unsigned char busType;
+ unsigned char numberOfBytesToRead;
+ unsigned char * data;
+ int dataLength;
+} I2CREQUESTDATA;
+#pragma pack()
+/*#ifdef IMB_API
+ *
+ * This section is provided to be able to compile using imb_if.h
+ *
+ *
+ * function return type. This is also defined in the local instrumentation
+ * so we ifdef here to avoid conflict.
+*/
+#define METHOD_BUFFERED 0
+#define FILE_ANY_ACCESS 0
+/*
+ * This is necessary to compile using memIf.h
+ */
+typedef enum _INTERFACE_TYPE
+{
+ Internal,
+ Isa,
+ Eisa,
+ MicroChannel,
+ TurboChannel,
+ MaximumInterfaceType
+} INTERFACE_TYPE, * PINTERFACE_TYPE;
+#ifdef WIN32
+/* From memIf.h */
+#pragma pack(1)
+typedef struct
+{
+ INTERFACE_TYPE InterfaceType; // Isa, Eisa, etc....
+ ULONG BusNumber; // Bus number
+ PHYSICAL_ADDRESS BusAddress; // Bus-relative address
+ ULONG AddressSpace; // 0 is memory, 1 is I/O
+ ULONG Length; // Length of section to map
+} PHYSICAL_MEMORY_INFO, * PPHYSICAL_MEMORY_INFO;
+#pragma pack()
+#endif
+/*#else // not IMB_API */
+/*
+ * These are defined in imb_if.h but are needed by users of the imbapi library
+*/
+#define ASYNC_SEQ_START 0
+/*
+ * This is the generic IMB packet format, the final checksum cant be
+ * represented in this structure and will show up as the last data byte
+ */
+/*
+ #define MIN_IMB_PACKET_SIZE 7
+ #define MAX_IMB_PACKET_SIZE 33
+*/
+#define MAX_BUFFER_SIZE 64
+/*#endif // IMB_API */
+/******************************
+ * FUNCTION PROTOTYPES
+ ******************************/
+ACCESN_STATUS
+SendTimedImbpRequest (
+ IMBPREQUESTDATA *reqPtr,
+ int timeOut,
+ BYTE * respDataPtr,
+ int * respDataLen,
+ BYTE * completionCode
+ );
+ACCESN_STATUS
+SendTimedI2cRequest (
+ I2CREQUESTDATA *reqPtr,
+ int timeOut,
+ BYTE * respDataPtr,
+ int * respDataLen,
+ BYTE * completionCode
+ );
+ACCESN_STATUS
+SendAsyncImbpRequest (
+ IMBPREQUESTDATA *reqPtr,
+ BYTE * seqNo
+ );
+ACCESN_STATUS
+GetAsyncImbpMessage (
+ ImbPacket * msgPtr,
+ DWORD * msgLen,
+ DWORD timeOut,
+ ImbAsyncSeq * seqNo,
+ DWORD channelNumber
+ );
+ACCESN_STATUS
+GetAsyncImbpMessage_Ex (
+ ImbPacket * msgPtr,
+ DWORD * msgLen,
+ DWORD timeOut,
+ ImbAsyncSeq * seqNo,
+ DWORD channelNumber,
+ BYTE * sessionHandle,
+ BYTE * privilege
+ );
+ACCESN_STATUS
+UnmapPhysicalMemory( int virtualAddress, int Length );
+ACCESN_STATUS
+StartAsyncMesgPoll(void);
+ACCESN_STATUS
+MapPhysicalMemory (
+ int startAddress,
+ int addressLength,
+ int *virtualAddress
+ );
+ACCESN_STATUS
+SetShutDownCode (
+ int delayTime,
+ int code
+ );
+ACCESN_STATUS
+SendTimedEmpMessageResponse (
+ ImbPacket * ptr,
+ char *responseDataBuf,
+ int responseDataLen,
+ int timeOut
+ );
+ACCESN_STATUS
+SendTimedEmpMessageResponse_Ex (
+ ImbPacket * ptr,
+ char *responseDataBuf,
+ int responseDataLen,
+ int timeOut,
+ BYTE sessionHandle,
+ BYTE channelNumber
+ );
+ACCESN_STATUS
+SendTimedLanMessageResponse (
+ ImbPacket * ptr,
+ char *responseDataBuf,
+ int responseDataLen,
+ int timeOut
+ );
+ACCESN_STATUS
+SendTimedLanMessageResponse_Ex (
+ ImbPacket * ptr,
+ char *responseDataBuf,
+ int responseDataLen,
+ int timeOut ,
+ BYTE sessionHandle,
+ BYTE channelNumber
+ );
+ACCESN_STATUS
+IsAsyncMessageAvailable (unsigned int eventId );
+ACCESN_STATUS
+RegisterForImbAsyncMessageNotification (unsigned int *handleId);
+ACCESN_STATUS
+UnRegisterForImbAsyncMessageNotification (unsigned int handleId,int iFlag);
+BYTE GetIpmiVersion(void);
+#endif /* IMBAPI_H__ */
diff --git a/src/plugins/ipmi_intf.c b/src/plugins/ipmi_intf.c
new file mode 100644
index 0000000..0fa76be
--- /dev/null
+++ b/src/plugins/ipmi_intf.c
@@ -0,0 +1,651 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#if defined(IPMI_INTF_LAN) || defined (IPMI_INTF_LANPLUS)
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <unistd.h>
+#include <netdb.h>
+#endif
+
+
+#include <ipmitool/ipmi_intf.h>
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_sdr.h>
+#include <ipmitool/log.h>
+
+#define IPMI_DEFAULT_PAYLOAD_SIZE 25
+
+#ifdef IPMI_INTF_OPEN
+extern struct ipmi_intf ipmi_open_intf;
+#endif
+#ifdef IPMI_INTF_IMB
+extern struct ipmi_intf ipmi_imb_intf;
+#endif
+#ifdef IPMI_INTF_LIPMI
+extern struct ipmi_intf ipmi_lipmi_intf;
+#endif
+#ifdef IPMI_INTF_BMC
+extern struct ipmi_intf ipmi_bmc_intf;
+#endif
+#ifdef IPMI_INTF_LAN
+extern struct ipmi_intf ipmi_lan_intf;
+#endif
+#ifdef IPMI_INTF_LANPLUS
+extern struct ipmi_intf ipmi_lanplus_intf;
+#endif
+#ifdef IPMI_INTF_FREE
+extern struct ipmi_intf ipmi_free_intf;
+#endif
+#ifdef IPMI_INTF_SERIAL
+extern struct ipmi_intf ipmi_serial_term_intf;
+extern struct ipmi_intf ipmi_serial_bm_intf;
+#endif
+#ifdef IPMI_INTF_DUMMY
+extern struct ipmi_intf ipmi_dummy_intf;
+#endif
+
+struct ipmi_intf * ipmi_intf_table[] = {
+#ifdef IPMI_INTF_OPEN
+ &ipmi_open_intf,
+#endif
+#ifdef IPMI_INTF_IMB
+ &ipmi_imb_intf,
+#endif
+#ifdef IPMI_INTF_LIPMI
+ &ipmi_lipmi_intf,
+#endif
+#ifdef IPMI_INTF_BMC
+ &ipmi_bmc_intf,
+#endif
+#ifdef IPMI_INTF_LAN
+ &ipmi_lan_intf,
+#endif
+#ifdef IPMI_INTF_LANPLUS
+ &ipmi_lanplus_intf,
+#endif
+#ifdef IPMI_INTF_FREE
+ &ipmi_free_intf,
+#endif
+#ifdef IPMI_INTF_SERIAL
+ &ipmi_serial_term_intf,
+ &ipmi_serial_bm_intf,
+#endif
+#ifdef IPMI_INTF_DUMMY
+ &ipmi_dummy_intf,
+#endif
+ NULL
+};
+
+/* ipmi_intf_print - Print list of interfaces
+ *
+ * no meaningful return code
+ */
+void ipmi_intf_print(struct ipmi_intf_support * intflist)
+{
+ struct ipmi_intf ** intf;
+ struct ipmi_intf_support * sup;
+ int def = 1;
+ int found;
+
+ lprintf(LOG_NOTICE, "Interfaces:");
+
+ for (intf = ipmi_intf_table; intf && *intf; intf++) {
+
+ if (intflist != NULL) {
+ found = 0;
+ for (sup=intflist; sup->name != NULL; sup++) {
+ if (strncmp(sup->name, (*intf)->name, strlen(sup->name)) == 0 &&
+ strncmp(sup->name, (*intf)->name, strlen((*intf)->name)) == 0 &&
+ sup->supported == 1)
+ found = 1;
+ }
+ if (found == 0)
+ continue;
+ }
+
+ lprintf(LOG_NOTICE, "\t%-12s %s %s",
+ (*intf)->name, (*intf)->desc,
+ def ? "[default]" : "");
+ def = 0;
+ }
+ lprintf(LOG_NOTICE, "");
+}
+
+/* ipmi_intf_load - Load an interface from the interface table above
+ * If no interface name is given return first entry
+ *
+ * @name: interface name to try and load
+ *
+ * returns pointer to inteface structure if found
+ * returns NULL on error
+ */
+struct ipmi_intf * ipmi_intf_load(char * name)
+{
+ struct ipmi_intf ** intf;
+ struct ipmi_intf * i;
+
+ if (name == NULL) {
+ i = ipmi_intf_table[0];
+ if (i->setup != NULL && (i->setup(i) < 0)) {
+ lprintf(LOG_ERR, "Unable to setup "
+ "interface %s", name);
+ return NULL;
+ }
+ return i;
+ }
+
+ for (intf = ipmi_intf_table;
+ ((intf != NULL) && (*intf != NULL));
+ intf++) {
+ i = *intf;
+ if (strncmp(name, i->name, strlen(name)) == 0) {
+ if (i->setup != NULL && (i->setup(i) < 0)) {
+ lprintf(LOG_ERR, "Unable to setup "
+ "interface %s", name);
+ return NULL;
+ }
+ return i;
+ }
+ }
+
+ return NULL;
+}
+
+void
+ipmi_intf_session_set_hostname(struct ipmi_intf * intf, char * hostname)
+{
+ if (intf->session == NULL)
+ return;
+
+ memset(intf->session->hostname, 0, 16);
+
+ if (hostname != NULL) {
+ memcpy(intf->session->hostname, hostname,
+ __min(strlen(hostname), 64));
+ }
+}
+
+void
+ipmi_intf_session_set_username(struct ipmi_intf * intf, char * username)
+{
+ if (intf->session == NULL)
+ return;
+
+ memset(intf->session->username, 0, 17);
+
+ if (username == NULL)
+ return;
+
+ memcpy(intf->session->username, username, __min(strlen(username), 16));
+}
+
+void
+ipmi_intf_session_set_password(struct ipmi_intf * intf, char * password)
+{
+ if (intf->session == NULL)
+ return;
+
+ memset(intf->session->authcode, 0, IPMI_AUTHCODE_BUFFER_SIZE);
+
+ if (password == NULL) {
+ intf->session->password = 0;
+ return;
+ }
+
+ intf->session->password = 1;
+ memcpy(intf->session->authcode, password,
+ __min(strlen(password), IPMI_AUTHCODE_BUFFER_SIZE));
+}
+
+void
+ipmi_intf_session_set_privlvl(struct ipmi_intf * intf, uint8_t level)
+{
+ if (intf->session == NULL)
+ return;
+
+ intf->session->privlvl = level;
+}
+
+void
+ipmi_intf_session_set_lookupbit(struct ipmi_intf * intf, uint8_t lookupbit)
+{
+ if (intf->session == NULL)
+ return;
+
+ intf->session->v2_data.lookupbit = lookupbit;
+}
+
+void
+ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf, uint8_t cipher_suite_id)
+{
+ if (intf->session == NULL)
+ return;
+
+ intf->session->cipher_suite_id = cipher_suite_id;
+}
+
+void
+ipmi_intf_session_set_sol_escape_char(struct ipmi_intf * intf, char sol_escape_char)
+{
+ if (intf->session == NULL)
+ return;
+
+ intf->session->sol_escape_char = sol_escape_char;
+}
+
+void
+ipmi_intf_session_set_kgkey(struct ipmi_intf * intf, char * kgkey)
+{
+ if (intf->session == NULL)
+ return;
+
+ memset(intf->session->v2_data.kg, 0, IPMI_KG_BUFFER_SIZE);
+
+ if (kgkey == NULL)
+ return;
+
+ memcpy(intf->session->v2_data.kg, kgkey,
+ __min(strlen(kgkey), IPMI_KG_BUFFER_SIZE));
+}
+
+void
+ipmi_intf_session_set_port(struct ipmi_intf * intf, int port)
+{
+ if (intf->session == NULL)
+ return;
+
+ intf->session->port = port;
+}
+
+void
+ipmi_intf_session_set_authtype(struct ipmi_intf * intf, uint8_t authtype)
+{
+ if (intf->session == NULL)
+ return;
+
+ /* clear password field if authtype NONE specified */
+ if (authtype == IPMI_SESSION_AUTHTYPE_NONE) {
+ memset(intf->session->authcode, 0, IPMI_AUTHCODE_BUFFER_SIZE);
+ intf->session->password = 0;
+ }
+
+ intf->session->authtype_set = authtype;
+}
+
+void
+ipmi_intf_session_set_timeout(struct ipmi_intf * intf, uint32_t timeout)
+{
+ if (intf->session == NULL)
+ return;
+
+ intf->session->timeout = timeout;
+}
+
+void
+ipmi_intf_session_set_retry(struct ipmi_intf * intf, int retry)
+{
+ if (intf->session == NULL)
+ return;
+
+ intf->session->retry = retry;
+}
+
+void
+ipmi_cleanup(struct ipmi_intf * intf)
+{
+ ipmi_sdr_list_empty(intf);
+}
+
+#if defined(IPMI_INTF_LAN) || defined (IPMI_INTF_LANPLUS)
+int
+ipmi_intf_socket_connect(struct ipmi_intf * intf)
+{
+ struct ipmi_session *session;
+
+ struct sockaddr_storage addr;
+ struct addrinfo hints;
+ struct addrinfo *rp0 = NULL, *rp;
+ char service[NI_MAXSERV];
+ int rc;
+
+ if (!intf || intf->session == NULL) {
+ return -1;
+ }
+
+ session = intf->session;
+
+ if (session->hostname == NULL || strlen((const char *)session->hostname) == 0) {
+ lprintf(LOG_ERR, "No hostname specified!");
+ return -1;
+ }
+
+ /* open port to BMC */
+ memset(&addr, 0, sizeof(addr));
+
+ sprintf(service, "%d", session->port);
+ /* Obtain address(es) matching host/port */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
+ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
+ hints.ai_flags = 0; /* use AI_NUMERICSERV for no name resolution */
+ hints.ai_protocol = IPPROTO_UDP; /* */
+
+ if (getaddrinfo(session->hostname, service, &hints, &rp0) != 0) {
+ lprintf(LOG_ERR, "Address lookup for %s failed",
+ session->hostname);
+ return -1;
+ }
+
+ /* getaddrinfo() returns a list of address structures.
+ * Try each address until we successfully connect(2).
+ * If socket(2) (or connect(2)) fails, we (close the socket
+ * and) try the next address.
+ */
+
+ session->ai_family = AF_UNSPEC;
+ for (rp = rp0; rp != NULL; rp = rp->ai_next) {
+ /* We are only interested in IPv4 and IPv6 */
+ if ((rp->ai_family != AF_INET6) && (rp->ai_family != AF_INET)) {
+ continue;
+ }
+
+ intf->fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+ if (intf->fd == -1) {
+ continue;
+ }
+
+ if (rp->ai_family == AF_INET) {
+ if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
+ memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen);
+ session->addrlen = rp->ai_addrlen;
+ session->ai_family = rp->ai_family;
+ break; /* Success */
+ }
+ } else if (rp->ai_family == AF_INET6) {
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)rp->ai_addr;
+ char hbuf[NI_MAXHOST];
+ socklen_t len;
+
+ /* The scope was specified on the command line e.g. with -H FE80::219:99FF:FEA0:BD95%eth0 */
+ if (addr6->sin6_scope_id != 0) {
+ len = sizeof(struct sockaddr_in6);
+ if (getnameinfo((struct sockaddr *)addr6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) {
+ lprintf(LOG_DEBUG, "Trying address: %s scope=%d",
+ hbuf,
+ addr6->sin6_scope_id);
+ }
+ if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
+ memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen);
+ session->addrlen = rp->ai_addrlen;
+ session->ai_family = rp->ai_family;
+ break; /* Success */
+ }
+ } else {
+ /* No scope specified, try to get this from the list of interfaces */
+ struct ifaddrs *ifaddrs = NULL;
+ struct ifaddrs *ifa = NULL;
+
+ if (getifaddrs(&ifaddrs) < 0) {
+ lprintf(LOG_ERR, "Interface address lookup for %s failed",
+ session->hostname);
+ break;
+ }
+
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr == NULL) {
+ continue;
+ }
+
+ if (ifa->ifa_addr->sa_family == AF_INET6) {
+ struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *)ifa->ifa_addr;
+
+ /* Skip unwanted addresses */
+ if (IN6_IS_ADDR_MULTICAST(&tmp6->sin6_addr)) {
+ continue;
+ }
+ if (IN6_IS_ADDR_LOOPBACK(&tmp6->sin6_addr)) {
+ continue;
+ }
+ len = sizeof(struct sockaddr_in6);
+ if ( getnameinfo((struct sockaddr *)tmp6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) {
+ lprintf(LOG_DEBUG, "Testing %s interface address: %s scope=%d",
+ ifa->ifa_name != NULL ? ifa->ifa_name : "???",
+ hbuf,
+ tmp6->sin6_scope_id);
+ }
+
+ if (tmp6->sin6_scope_id != 0) {
+ addr6->sin6_scope_id = tmp6->sin6_scope_id;
+ } else {
+ /*
+ * No scope information in interface address information
+ * On some OS'es, getifaddrs() is returning out the 'kernel' representation
+ * of scoped addresses which stores the scope in the 3rd and 4th
+ * byte. See also this page:
+ * http://www.freebsd.org/doc/en/books/developers-handbook/ipv6.html
+ */
+ if (IN6_IS_ADDR_LINKLOCAL(&tmp6->sin6_addr)
+ && (tmp6->sin6_addr.s6_addr16[1] != 0)) {
+ addr6->sin6_scope_id = ntohs(tmp6->sin6_addr.s6_addr16[1]);
+ }
+ }
+
+ /* OK, now try to connect with the scope id from this interface address */
+ if (addr6->sin6_scope_id != 0) {
+ if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
+ memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen);
+ session->addrlen = rp->ai_addrlen;
+ session->ai_family = rp->ai_family;
+ lprintf(LOG_DEBUG, "Successful connected on %s interface with scope id %d", ifa->ifa_name, tmp6->sin6_scope_id);
+ break; /* Success */
+ }
+ }
+ }
+ }
+ freeifaddrs(ifaddrs);
+ }
+ }
+ if (session->ai_family != AF_UNSPEC) {
+ break;
+ }
+ close(intf->fd);
+ intf->fd = -1;
+ }
+
+ /* No longer needed */
+ freeaddrinfo(rp0);
+
+ return ((intf->fd != -1) ? 0 : -1);
+}
+#endif
+
+uint16_t
+ipmi_intf_get_max_request_data_size(struct ipmi_intf * intf)
+{
+ int16_t size;
+
+ size = intf->max_request_data_size;
+
+ /* check if request size is not specified */
+ if (!size) {
+ /*
+ * The IPMB standard overall message length for ‘non -bridging’
+ * messages is specified as 32 bytes, maximum, including slave
+ * address. This sets the upper limit for typical IPMI messages.
+ * With the exception of messages used for bridging messages to
+ * other busses or interfaces (e.g. Master Write-Read and Send Message)
+ * IPMI messages should be designed to fit within this 32-byte maximum.
+ * In order to support bridging, the Master Write -Read and Send Message
+ * commands are allowed to exceed the 32-byte maximum transaction on IPMB
+ */
+
+ size = IPMI_DEFAULT_PAYLOAD_SIZE;
+
+ /* check if message is forwarded */
+ if (intf->target_addr && intf->target_addr != intf->my_addr) {
+ /* add Send Message request size */
+ size += 8;
+ }
+ }
+
+ /* check if message is forwarded */
+ if (intf->target_addr && intf->target_addr != intf->my_addr) {
+ /* subtract send message request size */
+ size -= 8;
+
+ /*
+ * Check that forwarded request size is not greater
+ * than the default payload size.
+ */
+ if (size > IPMI_DEFAULT_PAYLOAD_SIZE) {
+ size = IPMI_DEFAULT_PAYLOAD_SIZE;
+ }
+
+ /* check for double bridging */
+ if (intf->transit_addr && intf->transit_addr != intf->target_addr) {
+ /* subtract inner send message request size */
+ size -= 8;
+ }
+ }
+
+ /* check for underflow */
+ if (size < 0) {
+ return 0;
+ }
+
+ return size;
+}
+
+uint16_t
+ipmi_intf_get_max_response_data_size(struct ipmi_intf * intf)
+{
+ int16_t size;
+
+ size = intf->max_response_data_size;
+
+ /* check if response size is not specified */
+ if (!size) {
+ /*
+ * The IPMB standard overall message length for ‘non -bridging’
+ * messages is specified as 32 bytes, maximum, including slave
+ * address. This sets the upper limit for typical IPMI messages.
+ * With the exception of messages used for bridging messages to
+ * other busses or interfaces (e.g. Master Write-Read and Send Message)
+ * IPMI messages should be designed to fit within this 32-byte maximum.
+ * In order to support bridging, the Master Write -Read and Send Message
+ * commands are allowed to exceed the 32-byte maximum transaction on IPMB
+ */
+
+ size = IPMI_DEFAULT_PAYLOAD_SIZE; /* response length with subtracted header and checksum byte */
+
+ /* check if message is forwarded */
+ if (intf->target_addr && intf->target_addr != intf->my_addr) {
+ /* add Send Message header size */
+ size += 7;
+ }
+ }
+
+ /* check if message is forwarded */
+ if (intf->target_addr && intf->target_addr != intf->my_addr) {
+ /*
+ * Some IPMI controllers like PICMG AMC Carriers embed responses
+ * to the forwarded messages into the Send Message response.
+ * In order to be sure that the response is not truncated,
+ * subtract the internal message header size.
+ */
+ size -= 8;
+
+ /*
+ * Check that forwarded response is not greater
+ * than the default payload size.
+ */
+ if (size > IPMI_DEFAULT_PAYLOAD_SIZE) {
+ size = IPMI_DEFAULT_PAYLOAD_SIZE;
+ }
+
+ /* check for double bridging */
+ if (intf->transit_addr && intf->transit_addr != intf->target_addr) {
+ /* subtract inner send message header size */
+ size -= 8;
+ }
+ }
+
+ /* check for underflow */
+ if (size < 0) {
+ return 0;
+ }
+
+ return size;
+}
+
+void
+ipmi_intf_set_max_request_data_size(struct ipmi_intf * intf, uint16_t size)
+{
+ if (size < IPMI_DEFAULT_PAYLOAD_SIZE) {
+ lprintf(LOG_ERR, "Request size is too small (%d), leave default size",
+ size);
+ return;
+ }
+
+ if (intf->set_max_request_data_size) {
+ intf->set_max_request_data_size(intf, size);
+ } else {
+ intf->max_request_data_size = size;
+ }
+}
+
+void
+ipmi_intf_set_max_response_data_size(struct ipmi_intf * intf, uint16_t size)
+{
+ if (size < IPMI_DEFAULT_PAYLOAD_SIZE - 1) {
+ lprintf(LOG_ERR, "Response size is too small (%d), leave default size",
+ size);
+ return;
+ }
+
+ if (intf->set_max_response_data_size) {
+ intf->set_max_response_data_size(intf, size);
+ } else {
+ intf->max_response_data_size = size;
+ }
+}
diff --git a/src/plugins/lan/Makefile.am b/src/plugins/lan/Makefile.am
new file mode 100644
index 0000000..70e320f
--- /dev/null
+++ b/src/plugins/lan/Makefile.am
@@ -0,0 +1,39 @@
+# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Sun Microsystems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = -I$(top_srcdir)/include
+
+EXTRA_LTLIBRARIES = libintf_lan.la
+noinst_LTLIBRARIES = @INTF_LAN_LIB@
+libintf_lan_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_lan_la_SOURCES = lan.c lan.h asf.h rmcp.h auth.c auth.h md5.c md5.h
+
diff --git a/src/plugins/lan/Makefile.in b/src/plugins/lan/Makefile.in
new file mode 100644
index 0000000..5674953
--- /dev/null
+++ b/src/plugins/lan/Makefile.in
@@ -0,0 +1,540 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 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.
+
+# 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@
+
+# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Sun Microsystems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+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@
+subdir = src/plugins/lan
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libintf_lan_la_DEPENDENCIES = $(top_builddir)/lib/libipmitool.la
+am_libintf_lan_la_OBJECTS = lan.lo auth.lo md5.lo
+libintf_lan_la_OBJECTS = $(am_libintf_lan_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+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 = $(libintf_lan_la_SOURCES)
+DIST_SOURCES = $(libintf_lan_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+ARCH = @ARCH@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASEDIR = @BASEDIR@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTRO = @DISTRO@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTF_BMC = @INTF_BMC@
+INTF_BMC_LIB = @INTF_BMC_LIB@
+INTF_DUMMY = @INTF_DUMMY@
+INTF_DUMMY_LIB = @INTF_DUMMY_LIB@
+INTF_FREE = @INTF_FREE@
+INTF_FREE_LIB = @INTF_FREE_LIB@
+INTF_IMB = @INTF_IMB@
+INTF_IMB_LIB = @INTF_IMB_LIB@
+INTF_LAN = @INTF_LAN@
+INTF_LANPLUS = @INTF_LANPLUS@
+INTF_LANPLUS_LIB = @INTF_LANPLUS_LIB@
+INTF_LAN_LIB = @INTF_LAN_LIB@
+INTF_LIPMI = @INTF_LIPMI@
+INTF_LIPMI_LIB = @INTF_LIPMI_LIB@
+INTF_OPEN = @INTF_OPEN@
+INTF_OPEN_LIB = @INTF_OPEN_LIB@
+INTF_SERIAL = @INTF_SERIAL@
+INTF_SERIAL_LIB = @INTF_SERIAL_LIB@
+IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OS = @OS@
+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@
+POW_LIB = @POW_LIB@
+PSTAMP = @PSTAMP@
+RANLIB = @RANLIB@
+RPMBUILD = @RPMBUILD@
+RPM_RELEASE = @RPM_RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_configure_args = @ac_configure_args@
+ac_ct_AR = @ac_ct_AR@
+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@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+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@
+MAINTAINERCLEANFILES = Makefile.in
+INCLUDES = -I$(top_srcdir)/include
+EXTRA_LTLIBRARIES = libintf_lan.la
+noinst_LTLIBRARIES = @INTF_LAN_LIB@
+libintf_lan_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_lan_la_SOURCES = lan.c lan.h asf.h rmcp.h auth.c auth.h md5.c md5.h
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(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) --foreign src/plugins/lan/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/plugins/lan/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: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libintf_lan.la: $(libintf_lan_la_OBJECTS) $(libintf_lan_la_DEPENDENCIES) $(EXTRA_libintf_lan_la_DEPENDENCIES)
+ $(LINK) $(libintf_lan_la_OBJECTS) $(libintf_lan_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lan.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Plo@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 $(LTLIBRARIES)
+installdirs:
+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:
+ 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:
+
+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."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ 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-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:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES 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-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
+
+
+# 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:
diff --git a/src/plugins/lan/asf.h b/src/plugins/lan/asf.h
new file mode 100644
index 0000000..ab36d6f
--- /dev/null
+++ b/src/plugins/lan/asf.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IPMI_ASF_H
+#define IPMI_ASF_H
+
+#include <ipmitool/helper.h>
+#include "lan.h"
+
+#define ASF_RMCP_IANA 0x000011be
+
+#define ASF_TYPE_PING 0x80
+#define ASF_TYPE_PONG 0x40
+
+static const struct valstr asf_type_vals[] __attribute__((unused)) = {
+ { 0x10, "Reset" },
+ { 0x11, "Power-up" },
+ { 0x12, "Unconditional Power-down" },
+ { 0x13, "Power Cycle" },
+ { 0x40, "Presence Pong" },
+ { 0x41, "Capabilities Response" },
+ { 0x42, "System State Response" },
+ { 0x80, "Presence Ping" },
+ { 0x81, "Capabilities Request" },
+ { 0x82, "System State Request" },
+ { 0x00, NULL }
+};
+
+/* ASF message header */
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct asf_hdr {
+ uint32_t iana;
+ uint8_t type;
+ uint8_t tag;
+ uint8_t __reserved;
+ uint8_t len;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+int handle_asf(struct ipmi_intf * intf, uint8_t * data, int data_len);
+
+#endif /* IPMI_ASF_H */
diff --git a/src/plugins/lan/auth.c b/src/plugins/lan/auth.c
new file mode 100644
index 0000000..7410e3c
--- /dev/null
+++ b/src/plugins/lan/auth.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <ipmitool/helper.h>
+#include <ipmitool/bswap.h>
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_intf.h>
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_CRYPTO_MD2
+# include <openssl/md2.h>
+#endif
+
+#ifdef HAVE_CRYPTO_MD5
+# include <openssl/md5.h>
+#else
+# include "md5.h"
+#endif
+
+/*
+ * multi-session authcode generation for MD5
+ * H(password + session_id + msg + session_seq + password)
+ *
+ * Use OpenSSL implementation of MD5 algorithm if found
+ */
+uint8_t * ipmi_auth_md5(struct ipmi_session * s, uint8_t * data, int data_len)
+{
+#ifdef HAVE_CRYPTO_MD5
+ MD5_CTX ctx;
+ static uint8_t md[16];
+ uint32_t temp;
+
+#if WORDS_BIGENDIAN
+ temp = BSWAP_32(s->in_seq);
+#else
+ temp = s->in_seq;
+#endif
+ memset(md, 0, 16);
+ memset(&ctx, 0, sizeof(MD5_CTX));
+
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, (const uint8_t *)s->authcode, 16);
+ MD5_Update(&ctx, (const uint8_t *)&s->session_id, 4);
+ MD5_Update(&ctx, (const uint8_t *)data, data_len);
+ MD5_Update(&ctx, (const uint8_t *)&temp, sizeof(uint32_t));
+ MD5_Update(&ctx, (const uint8_t *)s->authcode, 16);
+ MD5_Final(md, &ctx);
+
+ if (verbose > 3)
+ printf(" MD5 AuthCode : %s\n", buf2str(md, 16));
+
+ return md;
+#else /*HAVE_CRYPTO_MD5*/
+ md5_state_t state;
+ static md5_byte_t digest[16];
+ uint32_t temp;
+
+ memset(digest, 0, 16);
+ memset(&state, 0, sizeof(md5_state_t));
+
+ md5_init(&state);
+
+ md5_append(&state, (const md5_byte_t *)s->authcode, 16);
+ md5_append(&state, (const md5_byte_t *)&s->session_id, 4);
+ md5_append(&state, (const md5_byte_t *)data, data_len);
+
+#if WORDS_BIGENDIAN
+ temp = BSWAP_32(s->in_seq);
+#else
+ temp = s->in_seq;
+#endif
+ md5_append(&state, (const md5_byte_t *)&temp, 4);
+ md5_append(&state, (const md5_byte_t *)s->authcode, 16);
+
+ md5_finish(&state, digest);
+
+ if (verbose > 3)
+ printf(" MD5 AuthCode : %s\n", buf2str(digest, 16));
+ return digest;
+#endif /*HAVE_CRYPTO_MD5*/
+}
+
+/*
+ * multi-session authcode generation for MD2
+ * H(password + session_id + msg + session_seq + password)
+ *
+ * Use OpenSSL implementation of MD2 algorithm if found.
+ * This function is analogous to ipmi_auth_md5
+ */
+uint8_t * ipmi_auth_md2(struct ipmi_session * s, uint8_t * data, int data_len)
+{
+#ifdef HAVE_CRYPTO_MD2
+ MD2_CTX ctx;
+ static uint8_t md[16];
+ uint32_t temp;
+
+#if WORDS_BIGENDIAN
+ temp = BSWAP_32(s->in_seq);
+#else
+ temp = s->in_seq;
+#endif
+ memset(md, 0, 16);
+ memset(&ctx, 0, sizeof(MD2_CTX));
+
+ MD2_Init(&ctx);
+ MD2_Update(&ctx, (const uint8_t *)s->authcode, 16);
+ MD2_Update(&ctx, (const uint8_t *)&s->session_id, 4);
+ MD2_Update(&ctx, (const uint8_t *)data, data_len);
+ MD2_Update(&ctx, (const uint8_t *)&temp, sizeof(uint32_t));
+ MD2_Update(&ctx, (const uint8_t *)s->authcode, 16);
+ MD2_Final(md, &ctx);
+
+ if (verbose > 3)
+ printf(" MD2 AuthCode : %s\n", buf2str(md, 16));
+
+ return md;
+#else /*HAVE_CRYPTO_MD2*/
+ static uint8_t md[16];
+ memset(md, 0, 16);
+ printf("WARNING: No internal support for MD2! "
+ "Please re-compile with OpenSSL.\n");
+ return md;
+#endif /*HAVE_CRYPTO_MD2*/
+}
+
+/* special authentication method */
+uint8_t * ipmi_auth_special(struct ipmi_session * s)
+{
+#ifdef HAVE_CRYPTO_MD5
+ MD5_CTX ctx;
+ static uint8_t md[16];
+ uint8_t challenge[16];
+ int i;
+
+ memset(challenge, 0, 16);
+ memset(md, 0, 16);
+ memset(&ctx, 0, sizeof(MD5_CTX));
+
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, (const uint8_t *)s->authcode, strlen((const char *)s->authcode));
+ MD5_Final(md, &ctx);
+
+ for (i=0; i<16; i++)
+ challenge[i] = s->challenge[i] ^ md[i];
+
+ memset(md, 0, 16);
+ memset(&ctx, 0, sizeof(MD5_CTX));
+
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, (const uint8_t *)challenge, 16);
+ MD5_Final(md, &ctx);
+
+ return md;
+#else /*HAVE_CRYPTO_MD5*/
+ int i;
+ md5_state_t state;
+ static md5_byte_t digest[16];
+ uint8_t challenge[16];
+
+ memset(challenge, 0, 16);
+ memset(digest, 0, 16);
+ memset(&state, 0, sizeof(md5_state_t));
+
+ md5_init(&state);
+ md5_append(&state, (const md5_byte_t *)s->authcode, strlen(s->authcode));
+ md5_finish(&state, digest);
+
+ for (i=0; i<16; i++)
+ challenge[i] = s->challenge[i] ^ digest[i];
+
+ memset(digest, 0, 16);
+ memset(&state, 0, sizeof(md5_state_t));
+
+ md5_init(&state);
+ md5_append(&state, (const md5_byte_t *)challenge, 16);
+ md5_finish(&state, digest);
+
+ return digest;
+#endif /*HAVE_CRYPTO_MD5*/
+}
+
diff --git a/src/plugins/lan/auth.h b/src/plugins/lan/auth.h
new file mode 100644
index 0000000..b9866ba
--- /dev/null
+++ b/src/plugins/lan/auth.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IPMI_AUTH_H
+#define IPMI_AUTH_H
+
+uint8_t * ipmi_auth_md2(struct ipmi_session * s, uint8_t * data, int data_len);
+uint8_t * ipmi_auth_md5(struct ipmi_session * s, uint8_t * data, int data_len);
+uint8_t * ipmi_auth_special(struct ipmi_session * s);
+
+#endif /*IPMI_AUTH_H*/
diff --git a/src/plugins/lan/lan.c b/src/plugins/lan/lan.c
new file mode 100644
index 0000000..fb1a633
--- /dev/null
+++ b/src/plugins/lan/lan.c
@@ -0,0 +1,2112 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <fcntl.h>
+
+#include <ipmitool/helper.h>
+#include <ipmitool/log.h>
+#include <ipmitool/bswap.h>
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_sel.h>
+#include <ipmitool/ipmi_intf.h>
+#include <ipmitool/ipmi_oem.h>
+#include <ipmitool/ipmi_strings.h>
+#include <ipmitool/ipmi_constants.h>
+#include <ipmitool/hpm2.h>
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "lan.h"
+#include "rmcp.h"
+#include "asf.h"
+#include "auth.h"
+
+#define IPMI_LAN_TIMEOUT 2
+#define IPMI_LAN_RETRY 4
+#define IPMI_LAN_PORT 0x26f
+#define IPMI_LAN_CHANNEL_E 0x0e
+
+/*
+ * LAN interface is required to support 45 byte request transactions and
+ * 42 byte response transactions.
+ */
+#define IPMI_LAN_MAX_REQUEST_SIZE 38 /* 45 - 7 */
+#define IPMI_LAN_MAX_RESPONSE_SIZE 34 /* 42 - 8 */
+
+extern const struct valstr ipmi_privlvl_vals[];
+extern const struct valstr ipmi_authtype_session_vals[];
+extern int verbose;
+
+struct ipmi_rq_entry * ipmi_req_entries;
+static struct ipmi_rq_entry * ipmi_req_entries_tail;
+static uint8_t bridge_possible = 0;
+
+static int ipmi_lan_send_packet(struct ipmi_intf * intf, uint8_t * data, int data_len);
+static struct ipmi_rs * ipmi_lan_recv_packet(struct ipmi_intf * intf);
+static struct ipmi_rs * ipmi_lan_poll_recv(struct ipmi_intf * intf);
+static int ipmi_lan_setup(struct ipmi_intf * intf);
+static int ipmi_lan_keepalive(struct ipmi_intf * intf);
+static struct ipmi_rs * ipmi_lan_recv_sol(struct ipmi_intf * intf);
+static struct ipmi_rs * ipmi_lan_send_sol(struct ipmi_intf * intf,
+ struct ipmi_v2_payload * payload);
+static struct ipmi_rs * ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req);
+static int ipmi_lan_send_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp);
+static int ipmi_lan_open(struct ipmi_intf * intf);
+static void ipmi_lan_close(struct ipmi_intf * intf);
+static int ipmi_lan_ping(struct ipmi_intf * intf);
+static void ipmi_lan_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size);
+static void ipmi_lan_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size);
+
+struct ipmi_intf ipmi_lan_intf = {
+ name: "lan",
+ desc: "IPMI v1.5 LAN Interface",
+ setup: ipmi_lan_setup,
+ open: ipmi_lan_open,
+ close: ipmi_lan_close,
+ sendrecv: ipmi_lan_send_cmd,
+ sendrsp: ipmi_lan_send_rsp,
+ recv_sol: ipmi_lan_recv_sol,
+ send_sol: ipmi_lan_send_sol,
+ keepalive: ipmi_lan_keepalive,
+ set_max_request_data_size: ipmi_lan_set_max_rq_data_size,
+ set_max_response_data_size: ipmi_lan_set_max_rp_data_size,
+ target_addr: IPMI_BMC_SLAVE_ADDR,
+};
+
+static struct ipmi_rq_entry *
+ipmi_req_add_entry(struct ipmi_intf * intf, struct ipmi_rq * req, uint8_t req_seq)
+{
+ struct ipmi_rq_entry * e;
+
+ e = malloc(sizeof(struct ipmi_rq_entry));
+ if (e == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return NULL;
+ }
+
+ memset(e, 0, sizeof(struct ipmi_rq_entry));
+ memcpy(&e->req, req, sizeof(struct ipmi_rq));
+
+ e->intf = intf;
+ e->rq_seq = req_seq;
+
+ if (ipmi_req_entries == NULL)
+ ipmi_req_entries = e;
+ else
+ ipmi_req_entries_tail->next = e;
+
+ ipmi_req_entries_tail = e;
+ lprintf(LOG_DEBUG+3, "added list entry seq=0x%02x cmd=0x%02x",
+ e->rq_seq, e->req.msg.cmd);
+ return e;
+}
+
+static struct ipmi_rq_entry *
+ipmi_req_lookup_entry(uint8_t seq, uint8_t cmd)
+{
+ struct ipmi_rq_entry * e = ipmi_req_entries;
+ while (e && (e->rq_seq != seq || e->req.msg.cmd != cmd)) {
+ if (e->next == NULL || e == e->next)
+ return NULL;
+ e = e->next;
+ }
+ return e;
+}
+
+static void
+ipmi_req_remove_entry(uint8_t seq, uint8_t cmd)
+{
+ struct ipmi_rq_entry * p, * e, * saved_next_entry;
+
+ e = p = ipmi_req_entries;
+
+ while (e && (e->rq_seq != seq || e->req.msg.cmd != cmd)) {
+ p = e;
+ e = e->next;
+ }
+ if (e) {
+ lprintf(LOG_DEBUG+3, "removed list entry seq=0x%02x cmd=0x%02x",
+ seq, cmd);
+ saved_next_entry = e->next;
+ p->next = (p->next == e->next) ? NULL : e->next;
+ /* If entry being removed is first in list, fix up list head */
+ if (ipmi_req_entries == e) {
+ if (ipmi_req_entries != p)
+ ipmi_req_entries = p;
+ else
+ ipmi_req_entries = saved_next_entry;
+ }
+ /* If entry being removed is last in list, fix up list tail */
+ if (ipmi_req_entries_tail == e) {
+ if (ipmi_req_entries_tail != p)
+ ipmi_req_entries_tail = p;
+ else
+ ipmi_req_entries_tail = NULL;
+ }
+ if (e->msg_data) {
+ free(e->msg_data);
+ e->msg_data = NULL;
+ }
+ free(e);
+ e = NULL;
+ }
+}
+
+static void
+ipmi_req_clear_entries(void)
+{
+ struct ipmi_rq_entry * p, * e;
+
+ e = ipmi_req_entries;
+ while (e) {
+ lprintf(LOG_DEBUG+3, "cleared list entry seq=0x%02x cmd=0x%02x",
+ e->rq_seq, e->req.msg.cmd);
+ if (e->next != NULL) {
+ p = e->next;
+ free(e);
+ e = p;
+ } else {
+ free(e);
+ e = NULL;
+ break;
+ }
+ }
+ ipmi_req_entries = NULL;
+}
+
+static int
+get_random(void *data, int len)
+{
+ int fd = open("/dev/urandom", O_RDONLY);
+ int rv;
+
+ if (fd < 0)
+ return errno;
+ if (len < 0) {
+ close(fd);
+ return errno; /* XXX: ORLY? */
+ }
+
+ rv = read(fd, data, len);
+
+ close(fd);
+ return rv;
+}
+
+static int
+ipmi_lan_send_packet(struct ipmi_intf * intf, uint8_t * data, int data_len)
+{
+ if (verbose > 2)
+ printbuf(data, data_len, "send_packet");
+
+ return send(intf->fd, data, data_len, 0);
+}
+
+static struct ipmi_rs *
+ipmi_lan_recv_packet(struct ipmi_intf * intf)
+{
+ static struct ipmi_rs rsp;
+ fd_set read_set, err_set;
+ struct timeval tmout;
+ int ret;
+
+ FD_ZERO(&read_set);
+ FD_SET(intf->fd, &read_set);
+
+ FD_ZERO(&err_set);
+ FD_SET(intf->fd, &err_set);
+
+ tmout.tv_sec = intf->session->timeout;
+ tmout.tv_usec = 0;
+
+ ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout);
+ if (ret < 0 || FD_ISSET(intf->fd, &err_set) || !FD_ISSET(intf->fd, &read_set))
+ return NULL;
+
+ /* the first read may return ECONNREFUSED because the rmcp ping
+ * packet--sent to UDP port 623--will be processed by both the
+ * BMC and the OS.
+ *
+ * The problem with this is that the ECONNREFUSED takes
+ * priority over any other received datagram; that means that
+ * the Connection Refused shows up _before_ the response packet,
+ * regardless of the order they were sent out. (unless the
+ * response is read before the connection refused is returned)
+ */
+ ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0);
+
+ if (ret < 0) {
+ FD_ZERO(&read_set);
+ FD_SET(intf->fd, &read_set);
+
+ FD_ZERO(&err_set);
+ FD_SET(intf->fd, &err_set);
+
+ tmout.tv_sec = intf->session->timeout;
+ tmout.tv_usec = 0;
+
+ ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout);
+ if (ret < 0 || FD_ISSET(intf->fd, &err_set) || !FD_ISSET(intf->fd, &read_set))
+ return NULL;
+
+ ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0);
+ if (ret < 0)
+ return NULL;
+ }
+
+ if (ret == 0)
+ return NULL;
+
+ rsp.data[ret] = '\0';
+ rsp.data_len = ret;
+
+ if (verbose > 2)
+ printbuf(rsp.data, rsp.data_len, "recv_packet");
+
+ return &rsp;
+}
+
+/*
+ * parse response RMCP "pong" packet
+ *
+ * return -1 if ping response not received
+ * returns 0 if IPMI is NOT supported
+ * returns 1 if IPMI is supported
+ *
+ * udp.source = 0x026f // RMCP_UDP_PORT
+ * udp.dest = ? // udp.source from rmcp-ping
+ * udp.len = ?
+ * udp.check = ?
+ * rmcp.ver = 0x06 // RMCP Version 1.0
+ * rmcp.__res = 0x00 // RESERVED
+ * rmcp.seq = 0xff // no RMCP ACK
+ * rmcp.class = 0x06 // RMCP_CLASS_ASF
+ * asf.iana = 0x000011be // ASF_RMCP_IANA
+ * asf.type = 0x40 // ASF_TYPE_PONG
+ * asf.tag = ? // asf.tag from rmcp-ping
+ * asf.__res = 0x00 // RESERVED
+ * asf.len = 0x10 // 16 bytes
+ * asf.data[3:0]= 0x000011be // IANA# = RMCP_ASF_IANA if no OEM
+ * asf.data[7:4]= 0x00000000 // OEM-defined (not for IPMI)
+ * asf.data[8] = 0x81 // supported entities
+ * // [7]=IPMI [6:4]=RES [3:0]=ASF_1.0
+ * asf.data[9] = 0x00 // supported interactions (reserved)
+ * asf.data[f:a]= 0x000000000000
+ */
+static int
+ipmi_handle_pong(struct ipmi_intf * intf, struct ipmi_rs * rsp)
+{
+ struct rmcp_pong * pong;
+
+ if (rsp == NULL)
+ return -1;
+
+ pong = (struct rmcp_pong *)rsp->data;
+
+ lprintf(LOG_DEBUG,
+ "Received IPMI/RMCP response packet: \n"
+ " IPMI%s Supported\n"
+ " ASF Version %s\n"
+ " RMCP Version %s\n"
+ " RMCP Sequence %d\n"
+ " IANA Enterprise %ld\n",
+ (pong->sup_entities & 0x80) ? "" : " NOT",
+ (pong->sup_entities & 0x01) ? "1.0" : "unknown",
+ (pong->rmcp.ver == 6) ? "1.0" : "unknown",
+ pong->rmcp.seq,
+ ntohl(pong->iana));
+
+ return (pong->sup_entities & 0x80) ? 1 : 0;
+}
+
+/* build and send RMCP presence ping packet
+ *
+ * RMCP ping
+ *
+ * udp.source = ?
+ * udp.dest = 0x026f // RMCP_UDP_PORT
+ * udp.len = ?
+ * udp.check = ?
+ * rmcp.ver = 0x06 // RMCP Version 1.0
+ * rmcp.__res = 0x00 // RESERVED
+ * rmcp.seq = 0xff // no RMCP ACK
+ * rmcp.class = 0x06 // RMCP_CLASS_ASF
+ * asf.iana = 0x000011be // ASF_RMCP_IANA
+ * asf.type = 0x80 // ASF_TYPE_PING
+ * asf.tag = ? // ASF sequence number
+ * asf.__res = 0x00 // RESERVED
+ * asf.len = 0x00
+ *
+ */
+static int
+ipmi_lan_ping(struct ipmi_intf * intf)
+{
+ struct asf_hdr asf_ping = {
+ .iana = htonl(ASF_RMCP_IANA),
+ .type = ASF_TYPE_PING,
+ };
+ struct rmcp_hdr rmcp_ping = {
+ .ver = RMCP_VERSION_1,
+ .class = RMCP_CLASS_ASF,
+ .seq = 0xff,
+ };
+ uint8_t * data;
+ int len = sizeof(rmcp_ping) + sizeof(asf_ping);
+ int rv;
+
+ data = malloc(len);
+ if (data == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return -1;
+ }
+ memset(data, 0, len);
+ memcpy(data, &rmcp_ping, sizeof(rmcp_ping));
+ memcpy(data+sizeof(rmcp_ping), &asf_ping, sizeof(asf_ping));
+
+ lprintf(LOG_DEBUG, "Sending IPMI/RMCP presence ping packet");
+
+ rv = ipmi_lan_send_packet(intf, data, len);
+
+ free(data);
+ data = NULL;
+
+ if (rv < 0) {
+ lprintf(LOG_ERR, "Unable to send IPMI presence ping packet");
+ return -1;
+ }
+
+ if (ipmi_lan_poll_recv(intf) == 0)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * The "thump" functions are used to send an extra packet following each
+ * request message. This may kick-start some BMCs that get confused with
+ * bad passwords or operate poorly under heavy network load.
+ */
+static void
+ipmi_lan_thump_first(struct ipmi_intf * intf)
+{
+ /* is this random data? */
+ uint8_t data[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x07, 0x20, 0x18, 0xc8, 0xc2, 0x01, 0x01, 0x3c };
+ ipmi_lan_send_packet(intf, data, 16);
+}
+
+static void
+ipmi_lan_thump(struct ipmi_intf * intf)
+{
+ uint8_t data[10] = "thump";
+ ipmi_lan_send_packet(intf, data, 10);
+}
+
+static struct ipmi_rs *
+ipmi_lan_poll_recv(struct ipmi_intf * intf)
+{
+ struct rmcp_hdr rmcp_rsp;
+ struct ipmi_rs * rsp;
+ struct ipmi_rq_entry * entry;
+ int x=0, rv;
+ uint8_t our_address = intf->my_addr;
+
+ if (our_address == 0)
+ our_address = IPMI_BMC_SLAVE_ADDR;
+
+ rsp = ipmi_lan_recv_packet(intf);
+
+ while (rsp != NULL) {
+
+ /* parse response headers */
+ memcpy(&rmcp_rsp, rsp->data, 4);
+
+ switch (rmcp_rsp.class) {
+ case RMCP_CLASS_ASF:
+ /* ping response packet */
+ rv = ipmi_handle_pong(intf, rsp);
+ return (rv <= 0) ? NULL : rsp;
+ case RMCP_CLASS_IPMI:
+ /* handled by rest of function */
+ break;
+ default:
+ lprintf(LOG_DEBUG, "Invalid RMCP class: %x",
+ rmcp_rsp.class);
+ rsp = ipmi_lan_recv_packet(intf);
+ continue;
+ }
+
+ x = 4;
+ rsp->session.authtype = rsp->data[x++];
+ memcpy(&rsp->session.seq, rsp->data+x, 4);
+ x += 4;
+ memcpy(&rsp->session.id, rsp->data+x, 4);
+ x += 4;
+
+ if (rsp->session.id == (intf->session->session_id + 0x10000000)) {
+ /* With SOL, authtype is always NONE, so we have no authcode */
+ rsp->session.payloadtype = IPMI_PAYLOAD_TYPE_SOL;
+
+ rsp->session.msglen = rsp->data[x++];
+
+ rsp->payload.sol_packet.packet_sequence_number =
+ rsp->data[x++] & 0x0F;
+
+ rsp->payload.sol_packet.acked_packet_number =
+ rsp->data[x++] & 0x0F;
+
+ rsp->payload.sol_packet.accepted_character_count =
+ rsp->data[x++];
+
+ rsp->payload.sol_packet.is_nack =
+ rsp->data[x] & 0x40;
+
+ rsp->payload.sol_packet.transfer_unavailable =
+ rsp->data[x] & 0x20;
+
+ rsp->payload.sol_packet.sol_inactive =
+ rsp->data[x] & 0x10;
+
+ rsp->payload.sol_packet.transmit_overrun =
+ rsp->data[x] & 0x08;
+
+ rsp->payload.sol_packet.break_detected =
+ rsp->data[x++] & 0x04;
+
+ x++; /* On ISOL there's and additional fifth byte before the data starts */
+
+ lprintf(LOG_DEBUG, "SOL sequence number : 0x%02x",
+ rsp->payload.sol_packet.packet_sequence_number);
+
+ lprintf(LOG_DEBUG, "SOL acked packet : 0x%02x",
+ rsp->payload.sol_packet.acked_packet_number);
+
+ lprintf(LOG_DEBUG, "SOL accepted char count : 0x%02x",
+ rsp->payload.sol_packet.accepted_character_count);
+
+ lprintf(LOG_DEBUG, "SOL is nack : %s",
+ rsp->payload.sol_packet.is_nack? "true" : "false");
+
+ lprintf(LOG_DEBUG, "SOL xfer unavailable : %s",
+ rsp->payload.sol_packet.transfer_unavailable? "true" : "false");
+
+ lprintf(LOG_DEBUG, "SOL inactive : %s",
+ rsp->payload.sol_packet.sol_inactive? "true" : "false");
+
+ lprintf(LOG_DEBUG, "SOL transmit overrun : %s",
+ rsp->payload.sol_packet.transmit_overrun? "true" : "false");
+
+ lprintf(LOG_DEBUG, "SOL break detected : %s",
+ rsp->payload.sol_packet.break_detected? "true" : "false");
+ }
+ else
+ {
+ /* Standard IPMI 1.5 packet */
+ rsp->session.payloadtype = IPMI_PAYLOAD_TYPE_IPMI;
+ if (intf->session->active && (rsp->session.authtype || intf->session->authtype))
+ x += 16;
+
+ rsp->session.msglen = rsp->data[x++];
+ rsp->payload.ipmi_response.rq_addr = rsp->data[x++];
+ rsp->payload.ipmi_response.netfn = rsp->data[x] >> 2;
+ rsp->payload.ipmi_response.rq_lun = rsp->data[x++] & 0x3;
+ x++; /* checksum */
+ rsp->payload.ipmi_response.rs_addr = rsp->data[x++];
+ rsp->payload.ipmi_response.rq_seq = rsp->data[x] >> 2;
+ rsp->payload.ipmi_response.rs_lun = rsp->data[x++] & 0x3;
+ rsp->payload.ipmi_response.cmd = rsp->data[x++];
+ rsp->ccode = rsp->data[x++];
+
+ if (verbose > 2)
+ printbuf(rsp->data, rsp->data_len, "ipmi message header");
+
+ lprintf(LOG_DEBUG+1, "<< IPMI Response Session Header");
+ lprintf(LOG_DEBUG+1, "<< Authtype : %s",
+ val2str(rsp->session.authtype, ipmi_authtype_session_vals));
+ lprintf(LOG_DEBUG+1, "<< Sequence : 0x%08lx",
+ (long)rsp->session.seq);
+ lprintf(LOG_DEBUG+1, "<< Session ID : 0x%08lx",
+ (long)rsp->session.id);
+ lprintf(LOG_DEBUG+1, "<< IPMI Response Message Header");
+ lprintf(LOG_DEBUG+1, "<< Rq Addr : %02x",
+ rsp->payload.ipmi_response.rq_addr);
+ lprintf(LOG_DEBUG+1, "<< NetFn : %02x",
+ rsp->payload.ipmi_response.netfn);
+ lprintf(LOG_DEBUG+1, "<< Rq LUN : %01x",
+ rsp->payload.ipmi_response.rq_lun);
+ lprintf(LOG_DEBUG+1, "<< Rs Addr : %02x",
+ rsp->payload.ipmi_response.rs_addr);
+ lprintf(LOG_DEBUG+1, "<< Rq Seq : %02x",
+ rsp->payload.ipmi_response.rq_seq);
+ lprintf(LOG_DEBUG+1, "<< Rs Lun : %01x",
+ rsp->payload.ipmi_response.rs_lun);
+ lprintf(LOG_DEBUG+1, "<< Command : %02x",
+ rsp->payload.ipmi_response.cmd);
+ lprintf(LOG_DEBUG+1, "<< Compl Code : 0x%02x",
+ rsp->ccode);
+
+ /* now see if we have outstanding entry in request list */
+ entry = ipmi_req_lookup_entry(rsp->payload.ipmi_response.rq_seq,
+ rsp->payload.ipmi_response.cmd);
+ if (entry) {
+ lprintf(LOG_DEBUG+2, "IPMI Request Match found");
+ if ((intf->target_addr != our_address) && bridge_possible) {
+ if ((rsp->data_len) && (rsp->payload.ipmi_response.netfn == 7) &&
+ (rsp->payload.ipmi_response.cmd != 0x34)) {
+ if (verbose > 2)
+ printbuf(&rsp->data[x], rsp->data_len-x,
+ "bridge command response");
+ }
+ /* bridged command: lose extra header */
+ if (entry->bridging_level &&
+ rsp->payload.ipmi_response.netfn == 7 &&
+ rsp->payload.ipmi_response.cmd == 0x34) {
+ entry->bridging_level--;
+ if (rsp->data_len - x - 1 == 0) {
+ rsp = !rsp->ccode ? ipmi_lan_recv_packet(intf) : NULL;
+ if (!entry->bridging_level)
+ entry->req.msg.cmd = entry->req.msg.target_cmd;
+ if (rsp == NULL) {
+ ipmi_req_remove_entry(entry->rq_seq, entry->req.msg.cmd);
+ }
+ continue;
+ } else {
+ /* The bridged answer data are inside the incoming packet */
+ memmove(rsp->data + x - 7,
+ rsp->data + x,
+ rsp->data_len - x - 1);
+ rsp->data[x - 8] -= 8;
+ rsp->data_len -= 8;
+ entry->rq_seq = rsp->data[x - 3] >> 2;
+ if (!entry->bridging_level)
+ entry->req.msg.cmd = entry->req.msg.target_cmd;
+ continue;
+ }
+ } else {
+ //x += sizeof(rsp->payload.ipmi_response);
+ if (rsp->data[x-1] != 0)
+ lprintf(LOG_DEBUG, "WARNING: Bridged "
+ "cmd ccode = 0x%02x",
+ rsp->data[x-1]);
+ }
+ }
+ ipmi_req_remove_entry(rsp->payload.ipmi_response.rq_seq,
+ rsp->payload.ipmi_response.cmd);
+ } else {
+ lprintf(LOG_INFO, "IPMI Request Match NOT FOUND");
+ rsp = ipmi_lan_recv_packet(intf);
+ continue;
+ }
+ }
+
+ break;
+ }
+
+ /* shift response data to start of array */
+ if (rsp && rsp->data_len > x) {
+ rsp->data_len -= x;
+ if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_IPMI)
+ rsp->data_len -= 1; /* We don't want the checksum */
+ memmove(rsp->data, rsp->data + x, rsp->data_len);
+ memset(rsp->data + rsp->data_len, 0, IPMI_BUF_SIZE - rsp->data_len);
+ }
+
+ return rsp;
+}
+
+/*
+ * IPMI LAN Request Message Format
+ * +--------------------+
+ * | rmcp.ver | 4 bytes
+ * | rmcp.__reserved |
+ * | rmcp.seq |
+ * | rmcp.class |
+ * +--------------------+
+ * | session.authtype | 9 bytes
+ * | session.seq |
+ * | session.id |
+ * +--------------------+
+ * | [session.authcode] | 16 bytes (AUTHTYPE != none)
+ * +--------------------+
+ * | message length | 1 byte
+ * +--------------------+
+ * | message.rs_addr | 6 bytes
+ * | message.netfn_lun |
+ * | message.checksum |
+ * | message.rq_addr |
+ * | message.rq_seq |
+ * | message.cmd |
+ * +--------------------+
+ * | [request data] | data_len bytes
+ * +--------------------+
+ * | checksum | 1 byte
+ * +--------------------+
+ */
+static struct ipmi_rq_entry *
+ipmi_lan_build_cmd(struct ipmi_intf * intf, struct ipmi_rq * req, int isRetry)
+{
+ struct rmcp_hdr rmcp = {
+ .ver = RMCP_VERSION_1,
+ .class = RMCP_CLASS_IPMI,
+ .seq = 0xff,
+ };
+ uint8_t * msg, * temp;
+ int cs, mp, tmp;
+ int ap = 0;
+ int len = 0;
+ int cs2 = 0, cs3 = 0;
+ struct ipmi_rq_entry * entry;
+ struct ipmi_session * s = intf->session;
+ static int curr_seq = 0;
+ uint8_t our_address = intf->my_addr;
+
+ if (our_address == 0)
+ our_address = IPMI_BMC_SLAVE_ADDR;
+
+ if (isRetry == 0)
+ curr_seq++;
+
+ if (curr_seq >= 64)
+ curr_seq = 0;
+
+ // Bug in the existing code where it keeps on adding same command/seq pair
+ // in the lookup entry list.
+ // Check if we have cmd,seq pair already in our list. As we are not changing
+ // the seq number we have to re-use the node which has existing
+ // command and sequence number. If we add then we will have redundant node with
+ // same cmd,seq pair
+ entry = ipmi_req_lookup_entry(curr_seq, req->msg.cmd);
+ if (entry)
+ {
+ // This indicates that we have already same command and seq in list
+ // No need to add once again and we will re-use the existing node.
+ // Only thing we have to do is clear the msg_data as we create
+ // a new one below in the code for it.
+ if (entry->msg_data) {
+ free(entry->msg_data);
+ entry->msg_data = NULL;
+ }
+ }
+ else
+ {
+ // We dont have this request in the list so we can add it
+ // to the list
+ entry = ipmi_req_add_entry(intf, req, curr_seq);
+ if (entry == NULL)
+ return NULL;
+ }
+
+ len = req->msg.data_len + 29;
+ if (s->active && s->authtype)
+ len += 16;
+ if (intf->transit_addr != intf->my_addr && intf->transit_addr != 0)
+ len += 8;
+ msg = malloc(len);
+ if (msg == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return NULL;
+ }
+ memset(msg, 0, len);
+
+ /* rmcp header */
+ memcpy(msg, &rmcp, sizeof(rmcp));
+ len = sizeof(rmcp);
+
+ /* ipmi session header */
+ msg[len++] = s->active ? s->authtype : 0;
+
+ msg[len++] = s->in_seq & 0xff;
+ msg[len++] = (s->in_seq >> 8) & 0xff;
+ msg[len++] = (s->in_seq >> 16) & 0xff;
+ msg[len++] = (s->in_seq >> 24) & 0xff;
+ memcpy(msg+len, &s->session_id, 4);
+ len += 4;
+
+ /* ipmi session authcode */
+ if (s->active && s->authtype) {
+ ap = len;
+ memcpy(msg+len, s->authcode, 16);
+ len += 16;
+ }
+
+ /* message length */
+ if ((intf->target_addr == our_address) || !bridge_possible) {
+ entry->bridging_level = 0;
+ msg[len++] = req->msg.data_len + 7;
+ cs = mp = len;
+ } else {
+ /* bridged request: encapsulate w/in Send Message */
+ entry->bridging_level = 1;
+ msg[len++] = req->msg.data_len + 15 +
+ (intf->transit_addr != intf->my_addr && intf->transit_addr != 0 ? 8 : 0);
+ cs = mp = len;
+ msg[len++] = IPMI_BMC_SLAVE_ADDR;
+ msg[len++] = IPMI_NETFN_APP << 2;
+ tmp = len - cs;
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+ cs2 = len;
+ msg[len++] = IPMI_REMOTE_SWID;
+ msg[len++] = curr_seq << 2;
+ msg[len++] = 0x34; /* Send Message rqst */
+ entry->req.msg.target_cmd = entry->req.msg.cmd; /* Save target command */
+ entry->req.msg.cmd = 0x34; /* (fixup request entry) */
+
+ if (intf->transit_addr == intf->my_addr || intf->transit_addr == 0) {
+ msg[len++] = (0x40|intf->target_channel); /* Track request*/
+ } else {
+ entry->bridging_level++;
+ msg[len++] = (0x40|intf->transit_channel); /* Track request*/
+ cs = len;
+ msg[len++] = intf->transit_addr;
+ msg[len++] = IPMI_NETFN_APP << 2;
+ tmp = len - cs;
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+ cs3 = len;
+ msg[len++] = intf->my_addr;
+ msg[len++] = curr_seq << 2;
+ msg[len++] = 0x34; /* Send Message rqst */
+ msg[len++] = (0x40|intf->target_channel); /* Track request */
+ }
+ cs = len;
+ }
+
+ /* ipmi message header */
+ msg[len++] = intf->target_addr;
+ msg[len++] = req->msg.netfn << 2 | (req->msg.lun & 3);
+ tmp = len - cs;
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+ cs = len;
+
+ if (!entry->bridging_level)
+ msg[len++] = IPMI_REMOTE_SWID;
+ /* Bridged message */
+ else if (entry->bridging_level)
+ msg[len++] = intf->my_addr;
+
+ entry->rq_seq = curr_seq;
+ msg[len++] = entry->rq_seq << 2;
+ msg[len++] = req->msg.cmd;
+
+ lprintf(LOG_DEBUG+1, ">> IPMI Request Session Header (level %d)", entry->bridging_level);
+ lprintf(LOG_DEBUG+1, ">> Authtype : %s",
+ val2str(s->authtype, ipmi_authtype_session_vals));
+ lprintf(LOG_DEBUG+1, ">> Sequence : 0x%08lx", (long)s->in_seq);
+ lprintf(LOG_DEBUG+1, ">> Session ID : 0x%08lx", (long)s->session_id);
+ lprintf(LOG_DEBUG+1, ">> IPMI Request Message Header");
+ lprintf(LOG_DEBUG+1, ">> Rs Addr : %02x", intf->target_addr);
+ lprintf(LOG_DEBUG+1, ">> NetFn : %02x", req->msg.netfn);
+ lprintf(LOG_DEBUG+1, ">> Rs LUN : %01x", 0);
+ lprintf(LOG_DEBUG+1, ">> Rq Addr : %02x", IPMI_REMOTE_SWID);
+ lprintf(LOG_DEBUG+1, ">> Rq Seq : %02x", entry->rq_seq);
+ lprintf(LOG_DEBUG+1, ">> Rq Lun : %01x", 0);
+ lprintf(LOG_DEBUG+1, ">> Command : %02x", req->msg.cmd);
+
+ /* message data */
+ if (req->msg.data_len) {
+ memcpy(msg+len, req->msg.data, req->msg.data_len);
+ len += req->msg.data_len;
+ }
+
+ /* second checksum */
+ tmp = len - cs;
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+
+ /* bridged request: 2nd checksum */
+ if (entry->bridging_level) {
+ if (intf->transit_addr != intf->my_addr && intf->transit_addr != 0) {
+ tmp = len - cs3;
+ msg[len++] = ipmi_csum(msg+cs3, tmp);
+ }
+ tmp = len - cs2;
+ msg[len++] = ipmi_csum(msg+cs2, tmp);
+ }
+
+ if (s->active) {
+ /*
+ * s->authcode is already copied to msg+ap but some
+ * authtypes require portions of the ipmi message to
+ * create the authcode so they must be done last.
+ */
+ switch (s->authtype) {
+ case IPMI_SESSION_AUTHTYPE_MD5:
+ temp = ipmi_auth_md5(s, msg+mp, msg[mp-1]);
+ memcpy(msg+ap, temp, 16);
+ break;
+ case IPMI_SESSION_AUTHTYPE_MD2:
+ temp = ipmi_auth_md2(s, msg+mp, msg[mp-1]);
+ memcpy(msg+ap, temp, 16);
+ break;
+ }
+ }
+
+ if (s->in_seq) {
+ s->in_seq++;
+ if (s->in_seq == 0)
+ s->in_seq++;
+ }
+
+ entry->msg_len = len;
+ entry->msg_data = msg;
+
+ return entry;
+}
+
+static struct ipmi_rs *
+ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
+{
+ struct ipmi_rq_entry * entry;
+ struct ipmi_rs * rsp = NULL;
+ int try = 0;
+ int isRetry = 0;
+
+ lprintf(LOG_DEBUG, "ipmi_lan_send_cmd:opened=[%d], open=[%d]",
+ intf->opened, intf->open);
+
+ if (intf->opened == 0 && intf->open != NULL) {
+ if (intf->open(intf) < 0) {
+ lprintf(LOG_DEBUG, "Failed to open LAN interface");
+ return NULL;
+ }
+ lprintf(LOG_DEBUG, "\topened=[%d], open=[%d]",
+ intf->opened, intf->open);
+ }
+
+ for (;;) {
+ isRetry = ( try > 0 ) ? 1 : 0;
+
+ entry = ipmi_lan_build_cmd(intf, req, isRetry);
+ if (entry == NULL) {
+ lprintf(LOG_ERR, "Aborting send command, unable to build");
+ return NULL;
+ }
+
+ if (ipmi_lan_send_packet(intf, entry->msg_data, entry->msg_len) < 0) {
+ try++;
+ usleep(5000);
+ ipmi_req_remove_entry(entry->rq_seq, entry->req.msg.target_cmd);
+ continue;
+ }
+
+ /* if we are set to noanswer we do not expect response */
+ if (intf->noanswer)
+ break;
+
+ if (ipmi_oem_active(intf, "intelwv2"))
+ ipmi_lan_thump(intf);
+
+ usleep(100);
+
+ rsp = ipmi_lan_poll_recv(intf);
+
+ /* Duplicate Request ccode most likely indicates a response to
+ a previous retry. Ignore and keep polling. */
+ if((rsp != NULL) && (rsp->ccode == 0xcf)) {
+ rsp = NULL;
+ rsp = ipmi_lan_poll_recv(intf);
+ }
+
+ if (rsp)
+ break;
+
+ usleep(5000);
+ if (++try >= intf->session->retry) {
+ lprintf(LOG_DEBUG, " No response from remote controller");
+ break;
+ }
+ }
+
+ // We need to cleanup the existing entries from the list. Because if we
+ // keep it and then when we send the new command and if the response is for
+ // old command it still matches it and then returns success.
+ // This is the corner case where the remote controller responds very slowly.
+ //
+ // Example: We have to send command 23 and 2d.
+ // If we send command,seq as 23,10 and if we dont get any response it will
+ // retry 4 times with 23,10 and then come out here and indicate that there is no
+ // reponse from the remote controller and will send the next command for
+ // ie 2d,11. And if the BMC is slow to respond and returns 23,10 then it
+ // will match it in the list and will take response of command 23 as response
+ // for command 2d and return success. So ideally when retries are done and
+ // are out of this function we should be clearing the list to be safe so that
+ // we dont match the old response with new request.
+ // [23, 10] --> BMC
+ // [23, 10] --> BMC
+ // [23, 10] --> BMC
+ // [23, 10] --> BMC
+ // [2D, 11] --> BMC
+ // <-- [23, 10]
+ // here if we maintain 23,10 in the list then it will get matched and consider
+ // 23 response as response for 2D.
+ ipmi_req_clear_entries();
+
+ return rsp;
+}
+
+static uint8_t *
+ipmi_lan_build_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp, int * llen)
+{
+ struct rmcp_hdr rmcp = {
+ .ver = RMCP_VERSION_1,
+ .class = RMCP_CLASS_IPMI,
+ .seq = 0xff,
+ };
+ struct ipmi_session * s = intf->session;
+ int cs, mp, ap = 0, tmp;
+ int len;
+ uint8_t * msg;
+
+ len = rsp->data_len + 22;
+ if (s->active)
+ len += 16;
+
+ msg = malloc(len);
+ if (msg == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return NULL;
+ }
+ memset(msg, 0, len);
+
+ /* rmcp header */
+ memcpy(msg, &rmcp, 4);
+ len = sizeof(rmcp);
+
+ /* ipmi session header */
+ msg[len++] = s->active ? s->authtype : 0;
+
+ if (s->in_seq) {
+ s->in_seq++;
+ if (s->in_seq == 0)
+ s->in_seq++;
+ }
+ memcpy(msg+len, &s->in_seq, 4);
+ len += 4;
+ memcpy(msg+len, &s->session_id, 4);
+ len += 4;
+
+ /* session authcode, if session active and authtype is not none */
+ if (s->active && s->authtype) {
+ ap = len;
+ memcpy(msg+len, s->authcode, 16);
+ len += 16;
+ }
+
+ /* message length */
+ msg[len++] = rsp->data_len + 8;
+
+ /* message header */
+ cs = mp = len;
+ msg[len++] = IPMI_REMOTE_SWID;
+ msg[len++] = rsp->msg.netfn << 2;
+ tmp = len - cs;
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+ cs = len;
+ msg[len++] = IPMI_BMC_SLAVE_ADDR;
+ msg[len++] = (rsp->msg.seq << 2) | (rsp->msg.lun & 3);
+ msg[len++] = rsp->msg.cmd;
+
+ /* completion code */
+ msg[len++] = rsp->ccode;
+
+ /* message data */
+ if (rsp->data_len) {
+ memcpy(msg+len, rsp->data, rsp->data_len);
+ len += rsp->data_len;
+ }
+
+ /* second checksum */
+ tmp = len - cs;
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+
+ if (s->active) {
+ uint8_t * d;
+ switch (s->authtype) {
+ case IPMI_SESSION_AUTHTYPE_MD5:
+ d = ipmi_auth_md5(s, msg+mp, msg[mp-1]);
+ memcpy(msg+ap, d, 16);
+ break;
+ case IPMI_SESSION_AUTHTYPE_MD2:
+ d = ipmi_auth_md2(s, msg+mp, msg[mp-1]);
+ memcpy(msg+ap, d, 16);
+ break;
+ }
+ }
+
+ *llen = len;
+ return msg;
+}
+
+static int
+ipmi_lan_send_rsp(struct ipmi_intf * intf, struct ipmi_rs * rsp)
+{
+ uint8_t * msg;
+ int len = 0;
+ int rv;
+
+ msg = ipmi_lan_build_rsp(intf, rsp, &len);
+ if (len <= 0 || msg == NULL) {
+ lprintf(LOG_ERR, "Invalid response packet");
+ if (msg != NULL) {
+ free(msg);
+ msg = NULL;
+ }
+ return -1;
+ }
+
+ rv = sendto(intf->fd, msg, len, 0,
+ (struct sockaddr *)&intf->session->addr,
+ intf->session->addrlen);
+ if (rv < 0) {
+ lprintf(LOG_ERR, "Packet send failed");
+ if (msg != NULL) {
+ free(msg);
+ msg = NULL;
+ }
+ return -1;
+ }
+
+ if (msg != NULL) {
+ free(msg);
+ msg = NULL;
+ }
+ return 0;
+}
+
+/*
+ * IPMI SOL Payload Format
+ * +--------------------+
+ * | rmcp.ver | 4 bytes
+ * | rmcp.__reserved |
+ * | rmcp.seq |
+ * | rmcp.class |
+ * +--------------------+
+ * | session.authtype | 9 bytes
+ * | session.seq |
+ * | session.id |
+ * +--------------------+
+ * | message length | 1 byte
+ * +--------------------+
+ * | sol.seq | 5 bytes
+ * | sol.ack_seq |
+ * | sol.acc_count |
+ * | sol.control |
+ * | sol.__reserved |
+ * +--------------------+
+ * | [request data] | data_len bytes
+ * +--------------------+
+ */
+uint8_t * ipmi_lan_build_sol_msg(struct ipmi_intf * intf,
+ struct ipmi_v2_payload * payload,
+ int * llen)
+{
+ struct rmcp_hdr rmcp = {
+ .ver = RMCP_VERSION_1,
+ .class = RMCP_CLASS_IPMI,
+ .seq = 0xff,
+ };
+ struct ipmi_session * session = intf->session;
+
+ /* msg will hold the entire message to be sent */
+ uint8_t * msg;
+
+ int len = 0;
+
+ len = sizeof(rmcp) + // RMCP Header (4)
+ 10 + // IPMI Session Header
+ 5 + // SOL header
+ payload->payload.sol_packet.character_count; // The actual payload
+
+ msg = malloc(len);
+ if (msg == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return NULL;
+ }
+ memset(msg, 0, len);
+
+ /* rmcp header */
+ memcpy(msg, &rmcp, sizeof(rmcp));
+ len = sizeof(rmcp);
+
+ /* ipmi session header */
+ msg[len++] = 0; /* SOL is always authtype = NONE */
+ msg[len++] = session->in_seq & 0xff;
+ msg[len++] = (session->in_seq >> 8) & 0xff;
+ msg[len++] = (session->in_seq >> 16) & 0xff;
+ msg[len++] = (session->in_seq >> 24) & 0xff;
+
+ msg[len++] = session->session_id & 0xff;
+ msg[len++] = (session->session_id >> 8) & 0xff;
+ msg[len++] = (session->session_id >> 16) & 0xff;
+ msg[len++] = ((session->session_id >> 24) + 0x10) & 0xff; /* Add 0x10 to MSB for SOL */
+
+ msg[len++] = payload->payload.sol_packet.character_count + 5;
+
+ /* sol header */
+ msg[len++] = payload->payload.sol_packet.packet_sequence_number;
+ msg[len++] = payload->payload.sol_packet.acked_packet_number;
+ msg[len++] = payload->payload.sol_packet.accepted_character_count;
+ msg[len] = payload->payload.sol_packet.is_nack ? 0x40 : 0;
+ msg[len] |= payload->payload.sol_packet.assert_ring_wor ? 0x20 : 0;
+ msg[len] |= payload->payload.sol_packet.generate_break ? 0x10 : 0;
+ msg[len] |= payload->payload.sol_packet.deassert_cts ? 0x08 : 0;
+ msg[len] |= payload->payload.sol_packet.deassert_dcd_dsr ? 0x04 : 0;
+ msg[len] |= payload->payload.sol_packet.flush_inbound ? 0x02 : 0;
+ msg[len++] |= payload->payload.sol_packet.flush_outbound ? 0x01 : 0;
+
+ len++; /* On SOL there's and additional fifth byte before the data starts */
+
+ if (payload->payload.sol_packet.character_count) {
+ /* We may have data to add */
+ memcpy(msg + len,
+ payload->payload.sol_packet.data,
+ payload->payload.sol_packet.character_count);
+ len += payload->payload.sol_packet.character_count;
+ }
+
+ session->in_seq++;
+ if (session->in_seq == 0)
+ session->in_seq++;
+
+ *llen = len;
+ return msg;
+}
+
+/*
+ * is_sol_packet
+ */
+static int
+is_sol_packet(struct ipmi_rs * rsp)
+{
+ return (rsp &&
+ (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL));
+}
+
+
+
+/*
+ * sol_response_acks_packet
+ */
+static int
+sol_response_acks_packet(struct ipmi_rs * rsp,
+ struct ipmi_v2_payload * payload)
+{
+ return (is_sol_packet(rsp) &&
+ payload &&
+ (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL) &&
+ (rsp->payload.sol_packet.acked_packet_number ==
+ payload->payload.sol_packet.packet_sequence_number));
+}
+
+/*
+ * ipmi_lan_send_sol_payload
+ *
+ */
+static struct ipmi_rs *
+ipmi_lan_send_sol_payload(struct ipmi_intf * intf,
+ struct ipmi_v2_payload * payload)
+{
+ struct ipmi_rs * rsp = NULL;
+ uint8_t * msg;
+ int len;
+ int try = 0;
+
+ if (intf->opened == 0 && intf->open != NULL) {
+ if (intf->open(intf) < 0)
+ return NULL;
+ }
+
+ msg = ipmi_lan_build_sol_msg(intf, payload, &len);
+ if (len <= 0 || msg == NULL) {
+ lprintf(LOG_ERR, "Invalid SOL payload packet");
+ if (msg != NULL) {
+ free(msg);
+ msg = NULL;
+ }
+ return NULL;
+ }
+
+ lprintf(LOG_DEBUG, ">> SENDING A SOL MESSAGE\n");
+
+ for (;;) {
+ if (ipmi_lan_send_packet(intf, msg, len) < 0) {
+ try++;
+ usleep(5000);
+ continue;
+ }
+
+ /* if we are set to noanswer we do not expect response */
+ if (intf->noanswer)
+ break;
+
+ if (payload->payload.sol_packet.packet_sequence_number == 0) {
+ /* We're just sending an ACK. No need to retry. */
+ break;
+ }
+
+ usleep(100);
+
+ rsp = ipmi_lan_recv_sol(intf); /* Grab the next packet */
+
+ if (sol_response_acks_packet(rsp, payload))
+ break;
+
+ else if (is_sol_packet(rsp) && rsp->data_len)
+ {
+ /*
+ * We're still waiting for our ACK, but we more data from
+ * the BMC
+ */
+ intf->session->sol_data.sol_input_handler(rsp);
+ }
+
+ usleep(5000);
+ if (++try >= intf->session->retry) {
+ lprintf(LOG_DEBUG, " No response from remote controller");
+ break;
+ }
+ }
+
+ if (msg != NULL) {
+ free(msg);
+ msg = NULL;
+ }
+ return rsp;
+}
+
+/*
+ * is_sol_partial_ack
+ *
+ * Determine if the response is a partial ACK/NACK that indicates
+ * we need to resend part of our packet.
+ *
+ * returns the number of characters we need to resend, or
+ * 0 if this isn't an ACK or we don't need to resend anything
+ */
+static int is_sol_partial_ack(struct ipmi_v2_payload * v2_payload,
+ struct ipmi_rs * rsp)
+{
+ int chars_to_resend = 0;
+
+ if (v2_payload &&
+ rsp &&
+ is_sol_packet(rsp) &&
+ sol_response_acks_packet(rsp, v2_payload) &&
+ (rsp->payload.sol_packet.accepted_character_count <
+ v2_payload->payload.sol_packet.character_count))
+ {
+ if (rsp->payload.sol_packet.accepted_character_count == 0) {
+ /* We should not resend data */
+ chars_to_resend = 0;
+ }
+ else
+ {
+ chars_to_resend =
+ v2_payload->payload.sol_packet.character_count -
+ rsp->payload.sol_packet.accepted_character_count;
+ }
+ }
+
+ return chars_to_resend;
+}
+
+/*
+ * set_sol_packet_sequence_number
+ */
+static void set_sol_packet_sequence_number(struct ipmi_intf * intf,
+ struct ipmi_v2_payload * v2_payload)
+{
+ /* Keep our sequence number sane */
+ if (intf->session->sol_data.sequence_number > 0x0F)
+ intf->session->sol_data.sequence_number = 1;
+
+ v2_payload->payload.sol_packet.packet_sequence_number =
+ intf->session->sol_data.sequence_number++;
+}
+
+/*
+ * ipmi_lan_send_sol
+ *
+ * Sends a SOL packet.. We handle partial ACK/NACKs from the BMC here.
+ *
+ * Returns a pointer to the SOL ACK we received, or
+ * 0 on failure
+ *
+ */
+struct ipmi_rs *
+ipmi_lan_send_sol(struct ipmi_intf * intf,
+ struct ipmi_v2_payload * v2_payload)
+{
+ struct ipmi_rs * rsp;
+ int chars_to_resend = 0;
+
+ v2_payload->payload_type = IPMI_PAYLOAD_TYPE_SOL;
+
+ /*
+ * Payload length is just the length of the character
+ * data here.
+ */
+ v2_payload->payload.sol_packet.acked_packet_number = 0; /* NA */
+
+ set_sol_packet_sequence_number(intf, v2_payload);
+
+ v2_payload->payload.sol_packet.accepted_character_count = 0; /* NA */
+
+ rsp = ipmi_lan_send_sol_payload(intf, v2_payload);
+
+ /* Determine if we need to resend some of our data */
+ chars_to_resend = is_sol_partial_ack(v2_payload, rsp);
+
+ while (chars_to_resend)
+ {
+ /*
+ * We first need to handle any new data we might have
+ * received in our NACK
+ */
+ if (rsp->data_len)
+ intf->session->sol_data.sol_input_handler(rsp);
+
+ set_sol_packet_sequence_number(intf, v2_payload);
+
+ /* Just send the required data */
+ memmove(v2_payload->payload.sol_packet.data,
+ v2_payload->payload.sol_packet.data +
+ rsp->payload.sol_packet.accepted_character_count,
+ chars_to_resend);
+
+ v2_payload->payload.sol_packet.character_count = chars_to_resend;
+
+ rsp = ipmi_lan_send_sol_payload(intf, v2_payload);
+
+ chars_to_resend = is_sol_partial_ack(v2_payload, rsp);
+ }
+
+ return rsp;
+}
+
+/*
+ * check_sol_packet_for_new_data
+ *
+ * Determine whether the SOL packet has already been seen
+ * and whether the packet has new data for us.
+ *
+ * This function has the side effect of removing an previously
+ * seen data, and moving new data to the front.
+ *
+ * It also "Remembers" the data so we don't get repeats.
+ *
+ */
+static int
+check_sol_packet_for_new_data(struct ipmi_intf * intf,
+ struct ipmi_rs *rsp)
+{
+ static uint8_t last_received_sequence_number = 0;
+ static uint8_t last_received_byte_count = 0;
+ int new_data_size = 0;
+
+ if (rsp &&
+ (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL))
+
+ {
+ uint8_t unaltered_data_len = rsp->data_len;
+ if (rsp->payload.sol_packet.packet_sequence_number ==
+ last_received_sequence_number)
+ {
+ /*
+ * This is the same as the last packet, but may include
+ * extra data
+ */
+ new_data_size = rsp->data_len - last_received_byte_count;
+
+ if (new_data_size > 0)
+ {
+ /* We have more data to process */
+ memmove(rsp->data,
+ rsp->data +
+ rsp->data_len - new_data_size,
+ new_data_size);
+ }
+
+ rsp->data_len = new_data_size;
+ }
+
+ /*
+ *Rember the data for next round
+ */
+ if (rsp && rsp->payload.sol_packet.packet_sequence_number)
+ {
+ last_received_sequence_number =
+ rsp->payload.sol_packet.packet_sequence_number;
+ last_received_byte_count = unaltered_data_len;
+ }
+ }
+
+ return new_data_size;
+}
+
+/*
+ * ack_sol_packet
+ *
+ * Provided the specified packet looks reasonable, ACK it.
+ */
+static void
+ack_sol_packet(struct ipmi_intf * intf,
+ struct ipmi_rs * rsp)
+{
+ if (rsp &&
+ (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) &&
+ (rsp->payload.sol_packet.packet_sequence_number))
+ {
+ struct ipmi_v2_payload ack;
+
+ memset(&ack, 0, sizeof(struct ipmi_v2_payload));
+
+ ack.payload_type = IPMI_PAYLOAD_TYPE_SOL;
+
+ /*
+ * Payload length is just the length of the character
+ * data here.
+ */
+ ack.payload_length = 0;
+
+ /* ACK packets have sequence numbers of 0 */
+ ack.payload.sol_packet.packet_sequence_number = 0;
+
+ ack.payload.sol_packet.acked_packet_number =
+ rsp->payload.sol_packet.packet_sequence_number;
+
+ ack.payload.sol_packet.accepted_character_count = rsp->data_len;
+
+ ipmi_lan_send_sol_payload(intf, &ack);
+ }
+}
+
+/*
+ * ipmi_recv_sol
+ *
+ * Receive a SOL packet and send an ACK in response.
+ *
+ */
+static struct ipmi_rs *
+ipmi_lan_recv_sol(struct ipmi_intf * intf)
+{
+ struct ipmi_rs * rsp = ipmi_lan_poll_recv(intf);
+
+ ack_sol_packet(intf, rsp);
+
+ /*
+ * Remembers the data sent, and alters the data to just
+ * include the new stuff.
+ */
+ check_sol_packet_for_new_data(intf, rsp);
+
+ return rsp;
+}
+
+/* send a get device id command to keep session active */
+static int
+ipmi_lan_keepalive(struct ipmi_intf * intf)
+{
+ struct ipmi_rs * rsp;
+ struct ipmi_rq req = { msg: {
+ netfn: IPMI_NETFN_APP,
+ cmd: 1,
+ }};
+
+ if (!intf->opened)
+ return 0;
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL)
+ return -1;
+ if (rsp->ccode > 0)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * IPMI Get Channel Authentication Capabilities Command
+ */
+static int
+ipmi_get_auth_capabilities_cmd(struct ipmi_intf * intf)
+{
+ struct ipmi_rs * rsp;
+ struct ipmi_rq req;
+ struct ipmi_session * s = intf->session;
+ uint8_t msg_data[2];
+
+ msg_data[0] = IPMI_LAN_CHANNEL_E;
+ msg_data[1] = s->privlvl;
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_APP;
+ req.msg.cmd = 0x38;
+ req.msg.data = msg_data;
+ req.msg.data_len = 2;
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL) {
+ lprintf(LOG_INFO, "Get Auth Capabilities command failed");
+ return -1;
+ }
+ if (verbose > 2)
+ printbuf(rsp->data, rsp->data_len, "get_auth_capabilities");
+
+ if (rsp->ccode > 0) {
+ lprintf(LOG_INFO, "Get Auth Capabilities command failed: %s",
+ val2str(rsp->ccode, completion_code_vals));
+ return -1;
+ }
+
+ lprintf(LOG_DEBUG, "Channel %02x Authentication Capabilities:",
+ rsp->data[0]);
+ lprintf(LOG_DEBUG, " Privilege Level : %s",
+ val2str(req.msg.data[1], ipmi_privlvl_vals));
+ lprintf(LOG_DEBUG, " Auth Types : %s%s%s%s%s",
+ (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_NONE) ? "NONE " : "",
+ (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD2) ? "MD2 " : "",
+ (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD5) ? "MD5 " : "",
+ (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD) ? "PASSWORD " : "",
+ (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_OEM) ? "OEM " : "");
+ lprintf(LOG_DEBUG, " Per-msg auth : %sabled",
+ (rsp->data[2] & IPMI_AUTHSTATUS_PER_MSG_DISABLED) ?
+ "dis" : "en");
+ lprintf(LOG_DEBUG, " User level auth : %sabled",
+ (rsp->data[2] & IPMI_AUTHSTATUS_PER_USER_DISABLED) ?
+ "dis" : "en");
+ lprintf(LOG_DEBUG, " Non-null users : %sabled",
+ (rsp->data[2] & IPMI_AUTHSTATUS_NONNULL_USERS_ENABLED) ?
+ "en" : "dis");
+ lprintf(LOG_DEBUG, " Null users : %sabled",
+ (rsp->data[2] & IPMI_AUTHSTATUS_NULL_USERS_ENABLED) ?
+ "en" : "dis");
+ lprintf(LOG_DEBUG, " Anonymous login : %sabled",
+ (rsp->data[2] & IPMI_AUTHSTATUS_ANONYMOUS_USERS_ENABLED) ?
+ "en" : "dis");
+ lprintf(LOG_DEBUG, "");
+
+ s->authstatus = rsp->data[2];
+
+ if (s->password &&
+ (s->authtype_set == 0 ||
+ s->authtype_set == IPMI_SESSION_AUTHTYPE_MD5) &&
+ (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD5))
+ {
+ s->authtype = IPMI_SESSION_AUTHTYPE_MD5;
+ }
+ else if (s->password &&
+ (s->authtype_set == 0 ||
+ s->authtype_set == IPMI_SESSION_AUTHTYPE_MD2) &&
+ (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_MD2))
+ {
+ s->authtype = IPMI_SESSION_AUTHTYPE_MD2;
+ }
+ else if (s->password &&
+ (s->authtype_set == 0 ||
+ s->authtype_set == IPMI_SESSION_AUTHTYPE_PASSWORD) &&
+ (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_PASSWORD))
+ {
+ s->authtype = IPMI_SESSION_AUTHTYPE_PASSWORD;
+ }
+ else if (s->password &&
+ (s->authtype_set == 0 ||
+ s->authtype_set == IPMI_SESSION_AUTHTYPE_OEM) &&
+ (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_OEM))
+ {
+ s->authtype = IPMI_SESSION_AUTHTYPE_OEM;
+ }
+ else if ((s->authtype_set == 0 ||
+ s->authtype_set == IPMI_SESSION_AUTHTYPE_NONE) &&
+ (rsp->data[1] & 1<<IPMI_SESSION_AUTHTYPE_NONE))
+ {
+ s->authtype = IPMI_SESSION_AUTHTYPE_NONE;
+ }
+ else {
+ if (!(rsp->data[1] & 1<<s->authtype_set))
+ lprintf(LOG_ERR, "Authentication type %s not supported",
+ val2str(s->authtype_set, ipmi_authtype_session_vals));
+ else
+ lprintf(LOG_ERR, "No supported authtypes found");
+
+ return -1;
+ }
+
+ lprintf(LOG_DEBUG, "Proceeding with AuthType %s",
+ val2str(s->authtype, ipmi_authtype_session_vals));
+
+ return 0;
+}
+
+/*
+ * IPMI Get Session Challenge Command
+ * returns a temporary session ID and 16 byte challenge string
+ */
+static int
+ipmi_get_session_challenge_cmd(struct ipmi_intf * intf)
+{
+ struct ipmi_rs * rsp;
+ struct ipmi_rq req;
+ struct ipmi_session * s = intf->session;
+ uint8_t msg_data[17];
+
+ memset(msg_data, 0, 17);
+ msg_data[0] = s->authtype;
+ memcpy(msg_data+1, s->username, 16);
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_APP;
+ req.msg.cmd = 0x39;
+ req.msg.data = msg_data;
+ req.msg.data_len = 17; /* 1 byte for authtype, 16 for user */
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL) {
+ lprintf(LOG_ERR, "Get Session Challenge command failed");
+ return -1;
+ }
+ if (verbose > 2)
+ printbuf(rsp->data, rsp->data_len, "get_session_challenge");
+
+ if (rsp->ccode > 0) {
+ switch (rsp->ccode) {
+ case 0x81:
+ lprintf(LOG_ERR, "Invalid user name");
+ break;
+ case 0x82:
+ lprintf(LOG_ERR, "NULL user name not enabled");
+ break;
+ default:
+ lprintf(LOG_ERR, "Get Session Challenge command failed: %s",
+ val2str(rsp->ccode, completion_code_vals));
+ }
+ return -1;
+ }
+
+ memcpy(&s->session_id, rsp->data, 4);
+ memcpy(s->challenge, rsp->data + 4, 16);
+
+ lprintf(LOG_DEBUG, "Opening Session");
+ lprintf(LOG_DEBUG, " Session ID : %08lx", (long)s->session_id);
+ lprintf(LOG_DEBUG, " Challenge : %s", buf2str(s->challenge, 16));
+
+ return 0;
+}
+
+/*
+ * IPMI Activate Session Command
+ */
+static int
+ipmi_activate_session_cmd(struct ipmi_intf * intf)
+{
+ struct ipmi_rs * rsp;
+ struct ipmi_rq req;
+ struct ipmi_session * s = intf->session;
+ uint8_t msg_data[22];
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_APP;
+ req.msg.cmd = 0x3a;
+
+ msg_data[0] = s->authtype;
+ msg_data[1] = s->privlvl;
+
+ /* supermicro oem authentication hack */
+ if (ipmi_oem_active(intf, "supermicro")) {
+ uint8_t * special = ipmi_auth_special(s);
+ memcpy(s->authcode, special, 16);
+ memset(msg_data + 2, 0, 16);
+ lprintf(LOG_DEBUG, " OEM Auth : %s",
+ buf2str(special, 16));
+ } else {
+ memcpy(msg_data + 2, s->challenge, 16);
+ }
+
+ /* setup initial outbound sequence number */
+ get_random(msg_data+18, 4);
+
+ req.msg.data = msg_data;
+ req.msg.data_len = 22;
+
+ s->active = 1;
+
+ lprintf(LOG_DEBUG, " Privilege Level : %s",
+ val2str(msg_data[1], ipmi_privlvl_vals));
+ lprintf(LOG_DEBUG, " Auth Type : %s",
+ val2str(s->authtype, ipmi_authtype_session_vals));
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL) {
+ lprintf(LOG_ERR, "Activate Session command failed");
+ s->active = 0;
+ return -1;
+ }
+ if (verbose > 2)
+ printbuf(rsp->data, rsp->data_len, "activate_session");
+
+ if (rsp->ccode) {
+ fprintf(stderr, "Activate Session error:");
+ switch (rsp->ccode) {
+ case 0x81:
+ lprintf(LOG_ERR, "\tNo session slot available");
+ break;
+ case 0x82:
+ lprintf(LOG_ERR, "\tNo slot available for given user - "
+ "limit reached");
+ break;
+ case 0x83:
+ lprintf(LOG_ERR, "\tNo slot available to support user "
+ "due to maximum privilege capacity");
+ break;
+ case 0x84:
+ lprintf(LOG_ERR, "\tSession sequence out of range");
+ break;
+ case 0x85:
+ lprintf(LOG_ERR, "\tInvalid session ID in request");
+ break;
+ case 0x86:
+ lprintf(LOG_ERR, "\tRequested privilege level "
+ "exceeds limit");
+ break;
+ case 0xd4:
+ lprintf(LOG_ERR, "\tInsufficient privilege level");
+ break;
+ default:
+ lprintf(LOG_ERR, "\t%s",
+ val2str(rsp->ccode, completion_code_vals));
+ }
+ return -1;
+ }
+
+ memcpy(&s->session_id, rsp->data + 1, 4);
+ s->in_seq = rsp->data[8] << 24 | rsp->data[7] << 16 | rsp->data[6] << 8 | rsp->data[5];
+ if (s->in_seq == 0)
+ ++s->in_seq;
+
+ if (s->authstatus & IPMI_AUTHSTATUS_PER_MSG_DISABLED)
+ s->authtype = IPMI_SESSION_AUTHTYPE_NONE;
+ else if (s->authtype != (rsp->data[0] & 0xf)) {
+ lprintf(LOG_ERR, "Invalid Session AuthType %s in response",
+ val2str(s->authtype, ipmi_authtype_session_vals));
+ return -1;
+ }
+
+ bridge_possible = 1;
+
+ lprintf(LOG_DEBUG, "\nSession Activated");
+ lprintf(LOG_DEBUG, " Auth Type : %s",
+ val2str(rsp->data[0], ipmi_authtype_session_vals));
+ lprintf(LOG_DEBUG, " Max Priv Level : %s",
+ val2str(rsp->data[9], ipmi_privlvl_vals));
+ lprintf(LOG_DEBUG, " Session ID : %08lx", (long)s->session_id);
+ lprintf(LOG_DEBUG, " Inbound Seq : %08lx\n", (long)s->in_seq);
+
+ return 0;
+}
+
+
+/*
+ * IPMI Set Session Privilege Level Command
+ */
+static int
+ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf)
+{
+ struct ipmi_rs * rsp;
+ struct ipmi_rq req;
+ uint8_t privlvl = intf->session->privlvl;
+ uint8_t backup_bridge_possible = bridge_possible;
+
+ if (privlvl <= IPMI_SESSION_PRIV_USER)
+ return 0; /* no need to set higher */
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_APP;
+ req.msg.cmd = 0x3b;
+ req.msg.data = &privlvl;
+ req.msg.data_len = 1;
+
+ bridge_possible = 0;
+ rsp = intf->sendrecv(intf, &req);
+ bridge_possible = backup_bridge_possible;
+
+ if (rsp == NULL) {
+ lprintf(LOG_ERR, "Set Session Privilege Level to %s failed",
+ val2str(privlvl, ipmi_privlvl_vals));
+ return -1;
+ }
+ if (verbose > 2)
+ printbuf(rsp->data, rsp->data_len, "set_session_privlvl");
+
+ if (rsp->ccode > 0) {
+ lprintf(LOG_ERR, "Set Session Privilege Level to %s failed: %s",
+ val2str(privlvl, ipmi_privlvl_vals),
+ val2str(rsp->ccode, completion_code_vals));
+ return -1;
+ }
+
+ lprintf(LOG_DEBUG, "Set Session Privilege Level to %s\n",
+ val2str(rsp->data[0], ipmi_privlvl_vals));
+
+ return 0;
+}
+
+static int
+ipmi_close_session_cmd(struct ipmi_intf * intf)
+{
+ struct ipmi_rs * rsp;
+ struct ipmi_rq req;
+ uint8_t msg_data[4];
+ uint32_t session_id = intf->session->session_id;
+
+ if (intf->session->active == 0)
+ return -1;
+
+ intf->target_addr = IPMI_BMC_SLAVE_ADDR;
+ bridge_possible = 0; /* Not a bridge message */
+
+ memcpy(&msg_data, &session_id, 4);
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_APP;
+ req.msg.cmd = 0x3c;
+ req.msg.data = msg_data;
+ req.msg.data_len = 4;
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL) {
+ lprintf(LOG_ERR, "Close Session command failed");
+ return -1;
+ }
+ if (verbose > 2)
+ printbuf(rsp->data, rsp->data_len, "close_session");
+
+ if (rsp->ccode == 0x87) {
+ lprintf(LOG_ERR, "Failed to Close Session: invalid "
+ "session ID %08lx", (long)session_id);
+ return -1;
+ }
+ if (rsp->ccode > 0) {
+ lprintf(LOG_ERR, "Close Session command failed: %s",
+ val2str(rsp->ccode, completion_code_vals));
+ return -1;
+ }
+
+ lprintf(LOG_DEBUG, "Closed Session %08lx\n", (long)session_id);
+
+ return 0;
+}
+
+/*
+ * IPMI LAN Session Activation (IPMI spec v1.5 section 12.9)
+ *
+ * 1. send "RMCP Presence Ping" message, response message will
+ * indicate whether the platform supports IPMI
+ * 2. send "Get Channel Authentication Capabilities" command
+ * with AUTHTYPE = none, response packet will contain information
+ * about supported challenge/response authentication types
+ * 3. send "Get Session Challenge" command with AUTHTYPE = none
+ * and indicate the authentication type in the message, response
+ * packet will contain challenge string and temporary session ID.
+ * 4. send "Activate Session" command, authenticated with AUTHTYPE
+ * sent in previous message. Also sends the initial value for
+ * the outbound sequence number for BMC.
+ * 5. BMC returns response confirming session activation and
+ * session ID for this session and initial inbound sequence.
+ */
+static int
+ipmi_lan_activate_session(struct ipmi_intf * intf)
+{
+ int rc;
+
+ /* don't fail on ping because its not always supported.
+ * Supermicro's IPMI LAN 1.5 cards don't tolerate pings.
+ */
+ if (!ipmi_oem_active(intf, "supermicro"))
+ ipmi_lan_ping(intf);
+
+ /* Some particular Intel boards need special help
+ */
+ if (ipmi_oem_active(intf, "intelwv2"))
+ ipmi_lan_thump_first(intf);
+
+ rc = ipmi_get_auth_capabilities_cmd(intf);
+ if (rc < 0) {
+ goto fail;
+ }
+
+ rc = ipmi_get_session_challenge_cmd(intf);
+ if (rc < 0)
+ goto fail;
+
+ rc = ipmi_activate_session_cmd(intf);
+ if (rc < 0)
+ goto fail;
+
+ intf->abort = 0;
+
+ rc = ipmi_set_session_privlvl_cmd(intf);
+ if (rc < 0)
+ goto fail;
+
+ return 0;
+
+ fail:
+ lprintf(LOG_ERR, "Error: Unable to establish LAN session");
+ return -1;
+}
+
+static void
+ipmi_lan_close(struct ipmi_intf * intf)
+{
+ if (intf->abort == 0)
+ ipmi_close_session_cmd(intf);
+
+ if (intf->fd >= 0)
+ close(intf->fd);
+
+ ipmi_req_clear_entries();
+
+ if (intf->session != NULL) {
+ free(intf->session);
+ intf->session = NULL;
+ }
+
+ intf->opened = 0;
+ intf->manufacturer_id = IPMI_OEM_UNKNOWN;
+ intf = NULL;
+}
+
+static int
+ipmi_lan_open(struct ipmi_intf * intf)
+{
+ int rc;
+ struct ipmi_session *s;
+
+ if (intf == NULL || intf->session == NULL)
+ return -1;
+ s = intf->session;
+
+ if (s->port == 0)
+ s->port = IPMI_LAN_PORT;
+ if (s->privlvl == 0)
+ s->privlvl = IPMI_SESSION_PRIV_ADMIN;
+ if (s->timeout == 0)
+ s->timeout = IPMI_LAN_TIMEOUT;
+ if (s->retry == 0)
+ s->retry = IPMI_LAN_RETRY;
+
+ if (s->hostname == NULL || strlen((const char *)s->hostname) == 0) {
+ lprintf(LOG_ERR, "No hostname specified!");
+ return -1;
+ }
+
+ intf->abort = 1;
+
+ intf->session->sol_data.sequence_number = 1;
+
+ if (ipmi_intf_socket_connect (intf) == -1) {
+ lprintf(LOG_ERR, "Could not open socket!");
+ return -1;
+ }
+
+ if (intf->fd < 0) {
+ lperror(LOG_ERR, "Connect to %s failed",
+ s->hostname);
+ intf->close(intf);
+ return -1;
+ }
+
+ intf->opened = 1;
+
+ /* try to open session */
+ rc = ipmi_lan_activate_session(intf);
+ if (rc < 0) {
+ intf->close(intf);
+ intf->opened = 0;
+ return -1;
+ }
+
+ intf->manufacturer_id = ipmi_get_oem(intf);
+
+ /* automatically detect interface request and response sizes */
+ hpm2_detect_max_payload_size(intf);
+
+ return intf->fd;
+}
+
+static int
+ipmi_lan_setup(struct ipmi_intf * intf)
+{
+ intf->session = malloc(sizeof(struct ipmi_session));
+ if (intf->session == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return -1;
+ }
+ memset(intf->session, 0, sizeof(struct ipmi_session));
+
+ /* setup default LAN maximum request and response sizes */
+ intf->max_request_data_size = IPMI_LAN_MAX_REQUEST_SIZE;
+ intf->max_response_data_size = IPMI_LAN_MAX_RESPONSE_SIZE;
+
+ return 0;
+}
+
+static void
+ipmi_lan_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size)
+{
+ if (size + 7 > 0xFF) {
+ size = 0xFF - 7;
+ }
+
+ intf->max_request_data_size = size;
+}
+
+static void
+ipmi_lan_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size)
+{
+ if (size + 8 > 0xFF) {
+ size = 0xFF - 8;
+ }
+
+ intf->max_response_data_size = size;
+}
diff --git a/src/plugins/lan/lan.h b/src/plugins/lan/lan.h
new file mode 100644
index 0000000..3ba3055
--- /dev/null
+++ b/src/plugins/lan/lan.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IPMI_LAN_H
+#define IPMI_LAN_H
+
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_intf.h>
+
+extern struct ipmi_intf ipmi_lan_intf;
+
+#endif /*IPMI_LAN_H*/
diff --git a/src/plugins/lan/md5.c b/src/plugins/lan/md5.c
new file mode 100644
index 0000000..572c7c8
--- /dev/null
+++ b/src/plugins/lan/md5.c
@@ -0,0 +1,381 @@
+/*
+ Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.c,v 1.1 2003/11/18 17:56:02 iceblink Exp $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.c is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+ either statically or dynamically; added missing #include <string.h>
+ in library.
+ 2002-03-11 lpd Corrected argument list for main(), and added int return
+ type, in test program and T value program.
+ 2002-02-21 lpd Added missing #include <stdio.h> in test program.
+ 2000-07-03 lpd Patched to eliminate warnings about "constant is
+ unsigned in ANSI C, signed in traditional"; made test program
+ self-checking.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+ 1999-05-03 lpd Original version.
+ */
+
+#include "md5.h"
+#include <string.h>
+
+#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#ifdef ARCH_IS_BIG_ENDIAN
+# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+#else
+# define BYTE_ORDER 0
+#endif
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3 0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6 0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9 0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13 0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16 0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19 0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22 0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25 0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28 0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31 0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35 0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38 0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41 0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44 0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47 0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50 0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53 0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57 0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60 0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63 0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+ md5_word_t
+ a = pms->abcd[0], b = pms->abcd[1],
+ c = pms->abcd[2], d = pms->abcd[3];
+ md5_word_t t;
+#if BYTE_ORDER > 0
+ /* Define storage only for big-endian CPUs. */
+ md5_word_t X[16];
+#else
+ /* Define storage for little-endian or both types of CPUs. */
+ md5_word_t xbuf[16];
+ const md5_word_t *X;
+#endif
+
+ {
+#if BYTE_ORDER == 0
+ /*
+ * Determine dynamically whether this is a big-endian or
+ * little-endian machine, since we can use a more efficient
+ * algorithm on the latter.
+ */
+ static const int w = 1;
+
+ if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+#endif
+#if BYTE_ORDER <= 0 /* little-endian */
+ {
+ /*
+ * On little-endian machines, we can process properly aligned
+ * data without copying it.
+ */
+ if (!((data - (const md5_byte_t *)0) & 3)) {
+ /* data are properly aligned */
+ X = (const md5_word_t *)data;
+ } else {
+ /* not aligned */
+ memcpy(xbuf, data, 64);
+ X = xbuf;
+ }
+ }
+#endif
+#if BYTE_ORDER == 0
+ else /* dynamic big-endian */
+#endif
+#if BYTE_ORDER >= 0 /* big-endian */
+ {
+ /*
+ * On big-endian machines, we must arrange the bytes in the
+ * right order.
+ */
+ const md5_byte_t *xp = data;
+ int i;
+
+# if BYTE_ORDER == 0
+ X = xbuf; /* (dynamic only) */
+# else
+# define xbuf X /* (static only) */
+# endif
+ for (i = 0; i < 16; ++i, xp += 4)
+ xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+ }
+#endif
+ }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+ /* Round 1. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + F(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 7, T1);
+ SET(d, a, b, c, 1, 12, T2);
+ SET(c, d, a, b, 2, 17, T3);
+ SET(b, c, d, a, 3, 22, T4);
+ SET(a, b, c, d, 4, 7, T5);
+ SET(d, a, b, c, 5, 12, T6);
+ SET(c, d, a, b, 6, 17, T7);
+ SET(b, c, d, a, 7, 22, T8);
+ SET(a, b, c, d, 8, 7, T9);
+ SET(d, a, b, c, 9, 12, T10);
+ SET(c, d, a, b, 10, 17, T11);
+ SET(b, c, d, a, 11, 22, T12);
+ SET(a, b, c, d, 12, 7, T13);
+ SET(d, a, b, c, 13, 12, T14);
+ SET(c, d, a, b, 14, 17, T15);
+ SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+ /* Round 2. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + G(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 1, 5, T17);
+ SET(d, a, b, c, 6, 9, T18);
+ SET(c, d, a, b, 11, 14, T19);
+ SET(b, c, d, a, 0, 20, T20);
+ SET(a, b, c, d, 5, 5, T21);
+ SET(d, a, b, c, 10, 9, T22);
+ SET(c, d, a, b, 15, 14, T23);
+ SET(b, c, d, a, 4, 20, T24);
+ SET(a, b, c, d, 9, 5, T25);
+ SET(d, a, b, c, 14, 9, T26);
+ SET(c, d, a, b, 3, 14, T27);
+ SET(b, c, d, a, 8, 20, T28);
+ SET(a, b, c, d, 13, 5, T29);
+ SET(d, a, b, c, 2, 9, T30);
+ SET(c, d, a, b, 7, 14, T31);
+ SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+ /* Round 3. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + H(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 5, 4, T33);
+ SET(d, a, b, c, 8, 11, T34);
+ SET(c, d, a, b, 11, 16, T35);
+ SET(b, c, d, a, 14, 23, T36);
+ SET(a, b, c, d, 1, 4, T37);
+ SET(d, a, b, c, 4, 11, T38);
+ SET(c, d, a, b, 7, 16, T39);
+ SET(b, c, d, a, 10, 23, T40);
+ SET(a, b, c, d, 13, 4, T41);
+ SET(d, a, b, c, 0, 11, T42);
+ SET(c, d, a, b, 3, 16, T43);
+ SET(b, c, d, a, 6, 23, T44);
+ SET(a, b, c, d, 9, 4, T45);
+ SET(d, a, b, c, 12, 11, T46);
+ SET(c, d, a, b, 15, 16, T47);
+ SET(b, c, d, a, 2, 23, T48);
+#undef SET
+
+ /* Round 4. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + I(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 6, T49);
+ SET(d, a, b, c, 7, 10, T50);
+ SET(c, d, a, b, 14, 15, T51);
+ SET(b, c, d, a, 5, 21, T52);
+ SET(a, b, c, d, 12, 6, T53);
+ SET(d, a, b, c, 3, 10, T54);
+ SET(c, d, a, b, 10, 15, T55);
+ SET(b, c, d, a, 1, 21, T56);
+ SET(a, b, c, d, 8, 6, T57);
+ SET(d, a, b, c, 15, 10, T58);
+ SET(c, d, a, b, 6, 15, T59);
+ SET(b, c, d, a, 13, 21, T60);
+ SET(a, b, c, d, 4, 6, T61);
+ SET(d, a, b, c, 11, 10, T62);
+ SET(c, d, a, b, 2, 15, T63);
+ SET(b, c, d, a, 9, 21, T64);
+#undef SET
+
+ /* Then perform the following additions. (That is increment each
+ of the four registers by the value it had before this block
+ was started.) */
+ pms->abcd[0] += a;
+ pms->abcd[1] += b;
+ pms->abcd[2] += c;
+ pms->abcd[3] += d;
+}
+
+void
+md5_init(md5_state_t *pms)
+{
+ pms->count[0] = pms->count[1] = 0;
+ pms->abcd[0] = 0x67452301;
+ pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+ pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+ pms->abcd[3] = 0x10325476;
+}
+
+void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+ const md5_byte_t *p = data;
+ int left = nbytes;
+ int offset = (pms->count[0] >> 3) & 63;
+ md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+ if (nbytes <= 0)
+ return;
+
+ /* Update the message length. */
+ pms->count[1] += nbytes >> 29;
+ pms->count[0] += nbits;
+ if (pms->count[0] < nbits)
+ pms->count[1]++;
+
+ /* Process an initial partial block. */
+ if (offset) {
+ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+ memcpy(pms->buf + offset, p, copy);
+ if (offset + copy < 64)
+ return;
+ p += copy;
+ left -= copy;
+ md5_process(pms, pms->buf);
+ }
+
+ /* Process full blocks. */
+ for (; left >= 64; p += 64, left -= 64)
+ md5_process(pms, p);
+
+ /* Process a final partial block. */
+ if (left)
+ memcpy(pms->buf, p, left);
+}
+
+void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+ static const md5_byte_t pad[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ md5_byte_t data[8];
+ int i;
+
+ /* Save the length before padding. */
+ for (i = 0; i < 8; ++i)
+ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+ /* Pad to 56 bytes mod 64. */
+ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+ /* Append the length. */
+ md5_append(pms, data, 8);
+ for (i = 0; i < 16; ++i)
+ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
diff --git a/src/plugins/lan/md5.h b/src/plugins/lan/md5.h
new file mode 100644
index 0000000..11fd117
--- /dev/null
+++ b/src/plugins/lan/md5.h
@@ -0,0 +1,91 @@
+/*
+ Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.h,v 1.1 2003/11/18 17:56:02 iceblink Exp $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.h is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Removed support for non-ANSI compilers; removed
+ references to Ghostscript; clarified derivation from RFC 1321;
+ now handles byte order either statically or dynamically.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+ added conditionalization for C++ compilation from Martin
+ Purschke <purschke@bnl.gov>.
+ 1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+# define md5_INCLUDED
+
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+ md5_word_t count[2]; /* message length in bits, lsw first */
+ md5_word_t abcd[4]; /* digest buffer */
+ md5_byte_t buf[64]; /* accumulate block */
+} md5_state_t;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Initialize the algorithm. */
+void md5_init(md5_state_t *pms);
+
+/* Append a string to the message. */
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+/* Finish the message and return the digest. */
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+#endif /* md5_INCLUDED */
diff --git a/src/plugins/lan/rmcp.h b/src/plugins/lan/rmcp.h
new file mode 100644
index 0000000..b979d92
--- /dev/null
+++ b/src/plugins/lan/rmcp.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IPMI_RMCP_H
+#define IPMI_RMCP_H
+
+#include <ipmitool/helper.h>
+#include "lan.h"
+#include "asf.h"
+
+#define RMCP_VERSION_1 0x06
+
+#define RMCP_UDP_PORT 0x26f /* port 623 */
+#define RMCP_UDP_SECURE_PORT 0x298 /* port 664 */
+
+#define RMCP_TYPE_MASK 0x80
+#define RMCP_TYPE_NORM 0x00
+#define RMCP_TYPE_ACK 0x01
+
+static const struct valstr rmcp_type_vals[] __attribute__((unused)) = {
+ { RMCP_TYPE_NORM, "Normal RMCP" },
+ { RMCP_TYPE_ACK, "RMCP ACK" },
+ { 0, NULL }
+};
+
+#define RMCP_CLASS_MASK 0x1f
+#define RMCP_CLASS_ASF 0x06
+#define RMCP_CLASS_IPMI 0x07
+#define RMCP_CLASS_OEM 0x08
+
+static const struct valstr rmcp_class_vals[] __attribute__((unused)) = {
+ { RMCP_CLASS_ASF, "ASF" },
+ { RMCP_CLASS_IPMI, "IPMI" },
+ { RMCP_CLASS_OEM, "OEM" },
+ { 0, NULL }
+};
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+/* RMCP message header */
+struct rmcp_hdr {
+ uint8_t ver;
+ uint8_t __reserved;
+ uint8_t seq;
+ uint8_t class;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct rmcp_pong {
+ struct rmcp_hdr rmcp;
+ struct asf_hdr asf;
+ uint32_t iana;
+ uint32_t oem;
+ uint8_t sup_entities;
+ uint8_t sup_interact;
+ uint8_t reserved[6];
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+int handle_rmcp(struct ipmi_intf * intf, uint8_t * data, int data_len);
+
+#endif /* IPMI_RMCP_H */
diff --git a/src/plugins/lanplus/Makefile.am b/src/plugins/lanplus/Makefile.am
new file mode 100644
index 0000000..428eb04
--- /dev/null
+++ b/src/plugins/lanplus/Makefile.am
@@ -0,0 +1,45 @@
+# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Sun Microsystems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = -I$(top_srcdir)/include
+
+EXTRA_LTLIBRARIES = libintf_lanplus.la
+noinst_LTLIBRARIES = @INTF_LANPLUS_LIB@
+libintf_lanplus_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_lanplus_la_SOURCES = \
+ rmcp.h asf.h \
+ lanplus.c lanplus.h \
+ lanplus_strings.c \
+ lanplus_crypt.c lanplus_crypt.h \
+ lanplus_dump.h lanplus_dump.c \
+ lanplus_crypt_impl.h lanplus_crypt_impl.c
+
diff --git a/src/plugins/lanplus/Makefile.in b/src/plugins/lanplus/Makefile.in
new file mode 100644
index 0000000..6860f1b
--- /dev/null
+++ b/src/plugins/lanplus/Makefile.in
@@ -0,0 +1,550 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 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.
+
+# 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@
+
+# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Sun Microsystems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+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@
+subdir = src/plugins/lanplus
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libintf_lanplus_la_DEPENDENCIES = $(top_builddir)/lib/libipmitool.la
+am_libintf_lanplus_la_OBJECTS = lanplus.lo lanplus_strings.lo \
+ lanplus_crypt.lo lanplus_dump.lo lanplus_crypt_impl.lo
+libintf_lanplus_la_OBJECTS = $(am_libintf_lanplus_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+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 = $(libintf_lanplus_la_SOURCES)
+DIST_SOURCES = $(libintf_lanplus_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+ARCH = @ARCH@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASEDIR = @BASEDIR@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTRO = @DISTRO@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTF_BMC = @INTF_BMC@
+INTF_BMC_LIB = @INTF_BMC_LIB@
+INTF_DUMMY = @INTF_DUMMY@
+INTF_DUMMY_LIB = @INTF_DUMMY_LIB@
+INTF_FREE = @INTF_FREE@
+INTF_FREE_LIB = @INTF_FREE_LIB@
+INTF_IMB = @INTF_IMB@
+INTF_IMB_LIB = @INTF_IMB_LIB@
+INTF_LAN = @INTF_LAN@
+INTF_LANPLUS = @INTF_LANPLUS@
+INTF_LANPLUS_LIB = @INTF_LANPLUS_LIB@
+INTF_LAN_LIB = @INTF_LAN_LIB@
+INTF_LIPMI = @INTF_LIPMI@
+INTF_LIPMI_LIB = @INTF_LIPMI_LIB@
+INTF_OPEN = @INTF_OPEN@
+INTF_OPEN_LIB = @INTF_OPEN_LIB@
+INTF_SERIAL = @INTF_SERIAL@
+INTF_SERIAL_LIB = @INTF_SERIAL_LIB@
+IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OS = @OS@
+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@
+POW_LIB = @POW_LIB@
+PSTAMP = @PSTAMP@
+RANLIB = @RANLIB@
+RPMBUILD = @RPMBUILD@
+RPM_RELEASE = @RPM_RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_configure_args = @ac_configure_args@
+ac_ct_AR = @ac_ct_AR@
+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@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+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@
+MAINTAINERCLEANFILES = Makefile.in
+INCLUDES = -I$(top_srcdir)/include
+EXTRA_LTLIBRARIES = libintf_lanplus.la
+noinst_LTLIBRARIES = @INTF_LANPLUS_LIB@
+libintf_lanplus_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_lanplus_la_SOURCES = \
+ rmcp.h asf.h \
+ lanplus.c lanplus.h \
+ lanplus_strings.c \
+ lanplus_crypt.c lanplus_crypt.h \
+ lanplus_dump.h lanplus_dump.c \
+ lanplus_crypt_impl.h lanplus_crypt_impl.c
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(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) --foreign src/plugins/lanplus/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/plugins/lanplus/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: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libintf_lanplus.la: $(libintf_lanplus_la_OBJECTS) $(libintf_lanplus_la_DEPENDENCIES) $(EXTRA_libintf_lanplus_la_DEPENDENCIES)
+ $(LINK) $(libintf_lanplus_la_OBJECTS) $(libintf_lanplus_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lanplus.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lanplus_crypt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lanplus_crypt_impl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lanplus_dump.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lanplus_strings.Plo@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 $(LTLIBRARIES)
+installdirs:
+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:
+ 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:
+
+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."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ 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-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:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES 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-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
+
+
+# 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:
diff --git a/src/plugins/lanplus/asf.h b/src/plugins/lanplus/asf.h
new file mode 100644
index 0000000..7a30418
--- /dev/null
+++ b/src/plugins/lanplus/asf.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IPMI_ASF_H
+#define IPMI_ASF_H
+
+#include <ipmitool/helper.h>
+#include "lanplus.h"
+
+#define ASF_RMCP_IANA 0x000011be
+
+#define ASF_TYPE_PING 0x80
+#define ASF_TYPE_PONG 0x40
+
+static const struct valstr asf_type_vals[] __attribute__((unused)) = {
+ { 0x10, "Reset" },
+ { 0x11, "Power-up" },
+ { 0x12, "Unconditional Power-down" },
+ { 0x13, "Power Cycle" },
+ { 0x40, "Presence Pong" },
+ { 0x41, "Capabilities Response" },
+ { 0x42, "System State Response" },
+ { 0x80, "Presence Ping" },
+ { 0x81, "Capabilities Request" },
+ { 0x82, "System State Request" },
+ { 0x00, NULL }
+};
+
+/* ASF message header */
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct asf_hdr {
+ uint32_t iana;
+ uint8_t type;
+ uint8_t tag;
+ uint8_t __reserved;
+ uint8_t len;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+int handle_asf(struct ipmi_intf * intf, uint8_t * data, int data_len);
+
+#endif /* IPMI_ASF_H */
diff --git a/src/plugins/lanplus/lanplus.c b/src/plugins/lanplus/lanplus.c
new file mode 100644
index 0000000..27b9610
--- /dev/null
+++ b/src/plugins/lanplus/lanplus.c
@@ -0,0 +1,3680 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <time.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <ipmitool/helper.h>
+#include <ipmitool/log.h>
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_lanp.h>
+#include <ipmitool/ipmi_channel.h>
+#include <ipmitool/ipmi_intf.h>
+#include <ipmitool/ipmi_strings.h>
+#include <ipmitool/hpm2.h>
+#include <ipmitool/bswap.h>
+#include <openssl/rand.h>
+
+#include "lanplus.h"
+#include "lanplus_crypt.h"
+#include "lanplus_crypt_impl.h"
+#include "lanplus_dump.h"
+#include "rmcp.h"
+#include "asf.h"
+
+/*
+ * LAN interface is required to support 45 byte request transactions and
+ * 42 byte response transactions.
+ */
+#define IPMI_LAN_MAX_REQUEST_SIZE 38 /* 45 - 7 */
+#define IPMI_LAN_MAX_RESPONSE_SIZE 34 /* 42 - 8 */
+
+extern const struct valstr ipmi_rakp_return_codes[];
+extern const struct valstr ipmi_priv_levels[];
+extern const struct valstr ipmi_auth_algorithms[];
+extern const struct valstr ipmi_integrity_algorithms[];
+extern const struct valstr ipmi_encryption_algorithms[];
+
+static struct ipmi_rq_entry * ipmi_req_entries;
+static struct ipmi_rq_entry * ipmi_req_entries_tail;
+
+
+static int ipmi_lanplus_setup(struct ipmi_intf * intf);
+static int ipmi_lanplus_keepalive(struct ipmi_intf * intf);
+static int ipmi_lan_send_packet(struct ipmi_intf * intf, uint8_t * data, int data_len);
+static struct ipmi_rs * ipmi_lan_recv_packet(struct ipmi_intf * intf);
+static struct ipmi_rs * ipmi_lan_poll_recv(struct ipmi_intf * intf);
+static struct ipmi_rs * ipmi_lanplus_send_ipmi_cmd(struct ipmi_intf * intf, struct ipmi_rq * req);
+static struct ipmi_rs * ipmi_lanplus_send_payload(struct ipmi_intf * intf,
+ struct ipmi_v2_payload * payload);
+static void getIpmiPayloadWireRep(
+ struct ipmi_intf * intf,
+ struct ipmi_v2_payload * payload, /* in */
+ uint8_t * out,
+ struct ipmi_rq * req,
+ uint8_t rq_seq,
+ uint8_t curr_seq);
+static void getSolPayloadWireRep(
+ struct ipmi_intf * intf,
+ uint8_t * msg,
+ struct ipmi_v2_payload * payload);
+static void read_open_session_response(struct ipmi_rs * rsp, int offset);
+static void read_rakp2_message(struct ipmi_rs * rsp, int offset, uint8_t alg);
+static void read_rakp4_message(struct ipmi_rs * rsp, int offset, uint8_t alg);
+static void read_session_data(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s);
+static void read_session_data_v15(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s);
+static void read_session_data_v2x(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s);
+static void read_ipmi_response(struct ipmi_rs * rsp, int * offset);
+static void read_sol_packet(struct ipmi_rs * rsp, int * offset);
+static struct ipmi_rs * ipmi_lanplus_recv_sol(struct ipmi_intf * intf);
+static struct ipmi_rs * ipmi_lanplus_send_sol(
+ struct ipmi_intf * intf,
+ struct ipmi_v2_payload * payload);
+static int check_sol_packet_for_new_data(
+ struct ipmi_intf * intf,
+ struct ipmi_rs *rsp);
+static void ack_sol_packet(
+ struct ipmi_intf * intf,
+ struct ipmi_rs * rsp);
+static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size);
+static void ipmi_lanp_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size);
+
+static uint8_t bridgePossible = 0;
+
+struct ipmi_intf ipmi_lanplus_intf = {
+ name: "lanplus",
+ desc: "IPMI v2.0 RMCP+ LAN Interface",
+ setup: ipmi_lanplus_setup,
+ open: ipmi_lanplus_open,
+ close: ipmi_lanplus_close,
+ sendrecv: ipmi_lanplus_send_ipmi_cmd,
+ recv_sol: ipmi_lanplus_recv_sol,
+ send_sol: ipmi_lanplus_send_sol,
+ keepalive: ipmi_lanplus_keepalive,
+ set_max_request_data_size: ipmi_lanp_set_max_rq_data_size,
+ set_max_response_data_size: ipmi_lanp_set_max_rp_data_size,
+ target_addr: IPMI_BMC_SLAVE_ADDR,
+};
+
+
+extern int verbose;
+
+
+
+/*
+ * lanplus_get_requested_ciphers
+ *
+ * Set the authentication, integrity and encryption algorithms based
+ * on the cipher suite ID. See table 22-19 in the IPMIv2 spec for the
+ * source of this information.
+ *
+ * param cipher_suite_id [in]
+ * param auth_alg [out]
+ * param integrity_alg [out]
+ * param crypt_alg [out]
+ *
+ * returns 0 on success
+ * 1 on failure
+ */
+int lanplus_get_requested_ciphers(int cipher_suite_id,
+ uint8_t * auth_alg,
+ uint8_t * integrity_alg,
+ uint8_t * crypt_alg)
+{
+ if ((cipher_suite_id < 0) || (cipher_suite_id > 14))
+ return 1;
+
+ /* See table 22-19 for the source of the statement */
+ switch (cipher_suite_id)
+ {
+ case 0:
+ *auth_alg = IPMI_AUTH_RAKP_NONE;
+ *integrity_alg = IPMI_INTEGRITY_NONE;
+ *crypt_alg = IPMI_CRYPT_NONE;
+ break;
+ case 1:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
+ *integrity_alg = IPMI_INTEGRITY_NONE;
+ *crypt_alg = IPMI_CRYPT_NONE;
+ break;
+ case 2:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
+ *crypt_alg = IPMI_CRYPT_NONE;
+ break;
+ case 3:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
+ *crypt_alg = IPMI_CRYPT_AES_CBC_128;
+ break;
+ case 4:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
+ *crypt_alg = IPMI_CRYPT_XRC4_128;
+ break;
+ case 5:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
+ *crypt_alg = IPMI_CRYPT_XRC4_40;
+ break;
+ case 6:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_NONE;
+ *crypt_alg = IPMI_CRYPT_NONE;
+ break;
+ case 7:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
+ *crypt_alg = IPMI_CRYPT_NONE;
+ break;
+ case 8:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
+ *crypt_alg = IPMI_CRYPT_AES_CBC_128;
+ break;
+ case 9:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
+ *crypt_alg = IPMI_CRYPT_XRC4_128;
+ break;
+ case 10:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
+ *crypt_alg = IPMI_CRYPT_XRC4_40;
+ break;
+ case 11:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_MD5_128;
+ *crypt_alg = IPMI_CRYPT_NONE;
+ break;
+ case 12:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_MD5_128;
+ *crypt_alg = IPMI_CRYPT_AES_CBC_128;
+ break;
+ case 13:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_MD5_128;
+ *crypt_alg = IPMI_CRYPT_XRC4_128;
+ break;
+ case 14:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_MD5_128;
+ *crypt_alg = IPMI_CRYPT_XRC4_40;
+ break;
+ }
+
+ return 0;
+}
+
+
+
+/*
+ * Reverse the order of arbitrarily long strings of bytes
+ */
+void lanplus_swap(
+ uint8_t * buffer,
+ int length)
+{
+ int i;
+ uint8_t temp;
+
+ for (i =0; i < length/2; ++i)
+ {
+ temp = buffer[i];
+ buffer[i] = buffer[length - 1 - i];
+ buffer[length - 1 - i] = temp;
+ }
+}
+
+
+
+static const struct valstr plus_payload_types_vals[] = {
+ { IPMI_PAYLOAD_TYPE_IPMI, "IPMI (0)" }, // IPMI Message
+ { IPMI_PAYLOAD_TYPE_SOL, "SOL (1)" }, // SOL (Serial over LAN)
+ { IPMI_PAYLOAD_TYPE_OEM, "OEM (2)" }, // OEM Explicid
+
+ { IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST, "OpenSession Req (0x10)" },
+ { IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE,"OpenSession Resp (0x11)" },
+ { IPMI_PAYLOAD_TYPE_RAKP_1, "RAKP1 (0x12)" },
+ { IPMI_PAYLOAD_TYPE_RAKP_2, "RAKP2 (0x13)" },
+ { IPMI_PAYLOAD_TYPE_RAKP_3, "RAKP3 (0x14)" },
+ { IPMI_PAYLOAD_TYPE_RAKP_4, "RAKP4 (0x15)" },
+ { 0x00, NULL },
+};
+
+
+static struct ipmi_rq_entry *
+ipmi_req_add_entry(struct ipmi_intf * intf, struct ipmi_rq * req, uint8_t req_seq)
+{
+ struct ipmi_rq_entry * e;
+
+ e = malloc(sizeof(struct ipmi_rq_entry));
+ if (e == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return NULL;
+ }
+
+ memset(e, 0, sizeof(struct ipmi_rq_entry));
+ memcpy(&e->req, req, sizeof(struct ipmi_rq));
+
+ e->intf = intf;
+ e->rq_seq = req_seq;
+
+ if (ipmi_req_entries == NULL)
+ ipmi_req_entries = e;
+ else
+ ipmi_req_entries_tail->next = e;
+
+ ipmi_req_entries_tail = e;
+ lprintf(LOG_DEBUG+3, "added list entry seq=0x%02x cmd=0x%02x",
+ e->rq_seq, e->req.msg.cmd);
+ return e;
+}
+
+
+static struct ipmi_rq_entry *
+ipmi_req_lookup_entry(uint8_t seq, uint8_t cmd)
+{
+ struct ipmi_rq_entry * e = ipmi_req_entries;
+
+ while (e && (e->rq_seq != seq || e->req.msg.cmd != cmd)) {
+ if (e == e->next)
+ return NULL;
+ e = e->next;
+ }
+ return e;
+}
+
+static void
+ipmi_req_remove_entry(uint8_t seq, uint8_t cmd)
+{
+ struct ipmi_rq_entry * p, * e, * saved_next_entry;
+
+ e = p = ipmi_req_entries;
+
+ while (e && (e->rq_seq != seq || e->req.msg.cmd != cmd)) {
+ p = e;
+ e = e->next;
+ }
+ if (e) {
+ lprintf(LOG_DEBUG+3, "removed list entry seq=0x%02x cmd=0x%02x",
+ seq, cmd);
+ saved_next_entry = e->next;
+ p->next = (p->next == e->next) ? NULL : e->next;
+ /* If entry being removed is first in list, fix up list head */
+ if (ipmi_req_entries == e) {
+ if (ipmi_req_entries != p)
+ ipmi_req_entries = p;
+ else
+ ipmi_req_entries = saved_next_entry;
+ }
+ /* If entry being removed is last in list, fix up list tail */
+ if (ipmi_req_entries_tail == e) {
+ if (ipmi_req_entries_tail != p)
+ ipmi_req_entries_tail = p;
+ else
+ ipmi_req_entries_tail = NULL;
+ }
+
+ if (e->msg_data) {
+ free(e->msg_data);
+ e->msg_data = NULL;
+ }
+ free(e);
+ e = NULL;
+ }
+}
+
+static void
+ipmi_req_clear_entries(void)
+{
+ struct ipmi_rq_entry * p, * e;
+
+ e = ipmi_req_entries;
+ while (e) {
+ lprintf(LOG_DEBUG+3, "cleared list entry seq=0x%02x cmd=0x%02x",
+ e->rq_seq, e->req.msg.cmd);
+ p = e->next;
+ free(e);
+ e = p;
+ }
+}
+
+
+int
+ipmi_lan_send_packet(
+ struct ipmi_intf * intf,
+ uint8_t * data, int
+ data_len)
+{
+ if (verbose >= 5)
+ printbuf(data, data_len, ">> sending packet");
+
+ return send(intf->fd, data, data_len, 0);
+}
+
+
+
+struct ipmi_rs *
+ipmi_lan_recv_packet(struct ipmi_intf * intf)
+{
+ static struct ipmi_rs rsp;
+ fd_set read_set, err_set;
+ struct timeval tmout;
+ int ret;
+
+ FD_ZERO(&read_set);
+ FD_SET(intf->fd, &read_set);
+
+ FD_ZERO(&err_set);
+ FD_SET(intf->fd, &err_set);
+
+ tmout.tv_sec = intf->session->timeout;
+ tmout.tv_usec = 0;
+
+ ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout);
+ if (ret < 0 || FD_ISSET(intf->fd, &err_set) || !FD_ISSET(intf->fd, &read_set))
+ return NULL;
+
+ /* the first read may return ECONNREFUSED because the rmcp ping
+ * packet--sent to UDP port 623--will be processed by both the
+ * BMC and the OS.
+ *
+ * The problem with this is that the ECONNREFUSED takes
+ * priority over any other received datagram; that means that
+ * the Connection Refused shows up _before_ the response packet,
+ * regardless of the order they were sent out. (unless the
+ * response is read before the connection refused is returned)
+ */
+ ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0);
+
+ if (ret < 0) {
+ FD_ZERO(&read_set);
+ FD_SET(intf->fd, &read_set);
+
+ FD_ZERO(&err_set);
+ FD_SET(intf->fd, &err_set);
+
+ tmout.tv_sec = intf->session->timeout;
+ tmout.tv_usec = 0;
+
+ ret = select(intf->fd + 1, &read_set, NULL, &err_set, &tmout);
+ if (ret < 0 || FD_ISSET(intf->fd, &err_set) || !FD_ISSET(intf->fd, &read_set))
+ return NULL;
+
+ ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0);
+ if (ret < 0)
+ return NULL;
+ }
+
+ if (ret == 0)
+ return NULL;
+
+ rsp.data[ret] = '\0';
+ rsp.data_len = ret;
+
+ if (verbose >= 5)
+ printbuf(rsp.data, rsp.data_len, "<< received packet");
+
+ return &rsp;
+}
+
+
+
+/*
+ * parse response RMCP "pong" packet
+ *
+ * return -1 if ping response not received
+ * returns 0 if IPMI is NOT supported
+ * returns 1 if IPMI is supported
+ *
+ * udp.source = 0x026f // RMCP_UDP_PORT
+ * udp.dest = ? // udp.source from rmcp-ping
+ * udp.len = ?
+ * udp.check = ?
+ * rmcp.ver = 0x06 // RMCP Version 1.0
+ * rmcp.__res = 0x00 // RESERVED
+ * rmcp.seq = 0xff // no RMCP ACK
+ * rmcp.class = 0x06 // RMCP_CLASS_ASF
+ * asf.iana = 0x000011be // ASF_RMCP_IANA
+ * asf.type = 0x40 // ASF_TYPE_PONG
+ * asf.tag = ? // asf.tag from rmcp-ping
+ * asf.__res = 0x00 // RESERVED
+ * asf.len = 0x10 // 16 bytes
+ * asf.data[3:0]= 0x000011be // IANA# = RMCP_ASF_IANA if no OEM
+ * asf.data[7:4]= 0x00000000 // OEM-defined (not for IPMI)
+ * asf.data[8] = 0x81 // supported entities
+ * // [7]=IPMI [6:4]=RES [3:0]=ASF_1.0
+ * asf.data[9] = 0x00 // supported interactions (reserved)
+ * asf.data[f:a]= 0x000000000000
+ */
+static int
+ipmi_handle_pong(struct ipmi_intf * intf, struct ipmi_rs * rsp)
+{
+ struct rmcp_pong {
+ struct rmcp_hdr rmcp;
+ struct asf_hdr asf;
+ uint32_t iana;
+ uint32_t oem;
+ uint8_t sup_entities;
+ uint8_t sup_interact;
+ uint8_t reserved[6];
+ } * pong;
+
+ if (!rsp)
+ return -1;
+
+ pong = (struct rmcp_pong *)rsp->data;
+
+ if (verbose)
+ printf("Received IPMI/RMCP response packet: "
+ "IPMI%s Supported\n",
+ (pong->sup_entities & 0x80) ? "" : " NOT");
+
+ if (verbose > 1)
+ printf(" ASF Version %s\n"
+ " RMCP Version %s\n"
+ " RMCP Sequence %d\n"
+ " IANA Enterprise %lu\n\n",
+ (pong->sup_entities & 0x01) ? "1.0" : "unknown",
+ (pong->rmcp.ver == 6) ? "1.0" : "unknown",
+ pong->rmcp.seq,
+ (unsigned long)ntohl(pong->iana));
+
+ return (pong->sup_entities & 0x80) ? 1 : 0;
+}
+
+
+/* build and send RMCP presence ping packet
+ *
+ * RMCP ping
+ *
+ * udp.source = ?
+ * udp.dest = 0x026f // RMCP_UDP_PORT
+ * udp.len = ?
+ * udp.check = ?
+ * rmcp.ver = 0x06 // RMCP Version 1.0
+ * rmcp.__res = 0x00 // RESERVED
+ * rmcp.seq = 0xff // no RMCP ACK
+ * rmcp.class = 0x06 // RMCP_CLASS_ASF
+ * asf.iana = 0x000011be // ASF_RMCP_IANA
+ * asf.type = 0x80 // ASF_TYPE_PING
+ * asf.tag = ? // ASF sequence number
+ * asf.__res = 0x00 // RESERVED
+ * asf.len = 0x00
+ *
+ */
+int
+ipmiv2_lan_ping(struct ipmi_intf * intf)
+{
+ struct asf_hdr asf_ping = {
+ .iana = htonl(ASF_RMCP_IANA),
+ .type = ASF_TYPE_PING,
+ };
+ struct rmcp_hdr rmcp_ping = {
+ .ver = RMCP_VERSION_1,
+ .class = RMCP_CLASS_ASF,
+ .seq = 0xff,
+ };
+ uint8_t * data;
+ int len = sizeof(rmcp_ping) + sizeof(asf_ping);
+ int rv;
+
+ data = malloc(len);
+ if (data == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return -1;
+ }
+ memset(data, 0, len);
+ memcpy(data, &rmcp_ping, sizeof(rmcp_ping));
+ memcpy(data+sizeof(rmcp_ping), &asf_ping, sizeof(asf_ping));
+
+ lprintf(LOG_DEBUG, "Sending IPMI/RMCP presence ping packet");
+
+ rv = ipmi_lan_send_packet(intf, data, len);
+
+ free(data);
+ data = NULL;
+
+ if (rv < 0) {
+ lprintf(LOG_ERR, "Unable to send IPMI presence ping packet");
+ return -1;
+ }
+
+ if (ipmi_lan_poll_recv(intf) == 0)
+ return 0;
+
+ return 1;
+}
+
+
+/**
+ *
+ * ipmi_lan_poll_recv
+ *
+ * Receive whatever comes back. Ignore received packets that don't correspond
+ * to a request we've sent.
+ *
+ * Returns: the ipmi_rs packet describing the/a reponse we expect.
+ */
+static struct ipmi_rs *
+ipmi_lan_poll_recv(struct ipmi_intf * intf)
+{
+ struct rmcp_hdr rmcp_rsp;
+ struct ipmi_rs * rsp;
+ struct ipmi_session * session = intf->session;
+ int offset, rv;
+ uint16_t payload_size;
+ uint8_t ourAddress = intf->my_addr;
+
+ if (ourAddress == 0) {
+ ourAddress = IPMI_BMC_SLAVE_ADDR;
+ }
+
+ rsp = ipmi_lan_recv_packet(intf);
+
+ /*
+ * Not positive why we're looping. Do we sometimes get stuff we don't
+ * expect?
+ */
+ while (rsp != NULL) {
+
+ /* parse response headers */
+ memcpy(&rmcp_rsp, rsp->data, 4);
+
+ if (rmcp_rsp.class == RMCP_CLASS_ASF) {
+ /* might be ping response packet */
+ rv = ipmi_handle_pong(intf, rsp);
+ return (rv <= 0) ? NULL : rsp;
+ }
+
+ if (rmcp_rsp.class != RMCP_CLASS_IPMI) {
+ lprintf(LOG_DEBUG, "Invalid RMCP class: %x",
+ rmcp_rsp.class);
+ rsp = ipmi_lan_recv_packet(intf);
+ continue;
+ }
+
+
+ /*
+ * The authtype / payload type determines what we are receiving
+ */
+ offset = 4;
+
+
+ /*--------------------------------------------------------------------
+ *
+ * The current packet could be one of several things:
+ *
+ * 1) An IPMI 1.5 packet (the response to our GET CHANNEL
+ * AUTHENTICATION CAPABILITIES request)
+ * 2) An RMCP+ message with an IPMI reponse payload
+ * 3) AN RMCP+ open session response
+ * 4) An RAKP-2 message (response to an RAKP 1 message)
+ * 5) An RAKP-4 message (response to an RAKP 3 message)
+ * 6) A Serial Over LAN packet
+ * 7) An Invalid packet (one that doesn't match a request)
+ * -------------------------------------------------------------------
+ */
+
+ read_session_data(rsp, &offset, intf->session);
+
+ if (lanplus_has_valid_auth_code(rsp, intf->session) == 0)
+ {
+ lprintf(LOG_ERR, "ERROR: Received message with invalid authcode!");
+ rsp = ipmi_lan_recv_packet(intf);
+ assert(0);
+ //continue;
+ }
+
+ if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) &&
+ (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
+ (rsp->session.bEncrypted))
+
+ {
+ lanplus_decrypt_payload(session->v2_data.crypt_alg,
+ session->v2_data.k2,
+ rsp->data + offset,
+ rsp->session.msglen,
+ rsp->data + offset,
+ &payload_size);
+ }
+ else
+ payload_size = rsp->session.msglen;
+
+
+ /*
+ * Handle IPMI responses (case #1 and #2) -- all IPMI reponses
+ */
+ if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_IPMI)
+ {
+ struct ipmi_rq_entry * entry;
+ int payload_start = offset;
+ int extra_data_length;
+ read_ipmi_response(rsp, &offset);
+
+ lprintf(LOG_DEBUG+1, "<< IPMI Response Session Header");
+ lprintf(LOG_DEBUG+1, "<< Authtype : %s",
+ val2str(rsp->session.authtype, ipmi_authtype_session_vals));
+ lprintf(LOG_DEBUG+1, "<< Payload type : %s",
+ val2str(rsp->session.payloadtype, plus_payload_types_vals));
+ lprintf(LOG_DEBUG+1, "<< Session ID : 0x%08lx",
+ (long)rsp->session.id);
+ lprintf(LOG_DEBUG+1, "<< Sequence : 0x%08lx",
+ (long)rsp->session.seq);
+ lprintf(LOG_DEBUG+1, "<< IPMI Msg/Payload Length : %d",
+ rsp->session.msglen);
+ lprintf(LOG_DEBUG+1, "<< IPMI Response Message Header");
+ lprintf(LOG_DEBUG+1, "<< Rq Addr : %02x",
+ rsp->payload.ipmi_response.rq_addr);
+ lprintf(LOG_DEBUG+1, "<< NetFn : %02x",
+ rsp->payload.ipmi_response.netfn);
+ lprintf(LOG_DEBUG+1, "<< Rq LUN : %01x",
+ rsp->payload.ipmi_response.rq_lun);
+ lprintf(LOG_DEBUG+1, "<< Rs Addr : %02x",
+ rsp->payload.ipmi_response.rs_addr);
+ lprintf(LOG_DEBUG+1, "<< Rq Seq : %02x",
+ rsp->payload.ipmi_response.rq_seq);
+ lprintf(LOG_DEBUG+1, "<< Rs Lun : %01x",
+ rsp->payload.ipmi_response.rs_lun);
+ lprintf(LOG_DEBUG+1, "<< Command : %02x",
+ rsp->payload.ipmi_response.cmd);
+ lprintf(LOG_DEBUG+1, "<< Compl Code : 0x%02x",
+ rsp->ccode);
+
+ /* Are we expecting this packet? */
+ entry = ipmi_req_lookup_entry(rsp->payload.ipmi_response.rq_seq,
+ rsp->payload.ipmi_response.cmd);
+
+ if (entry != NULL) {
+ lprintf(LOG_DEBUG+2, "IPMI Request Match found");
+ if ( intf->target_addr != intf->my_addr &&
+ bridgePossible &&
+ rsp->data_len &&
+ rsp->payload.ipmi_response.cmd == 0x34 &&
+ (rsp->payload.ipmi_response.netfn == 0x06 ||
+ rsp->payload.ipmi_response.netfn == 0x07) &&
+ rsp->payload.ipmi_response.rs_lun == 0 )
+ {
+ /* Check completion code */
+ if (rsp->data[offset-1] == 0)
+ {
+ lprintf(LOG_DEBUG, "Bridged command answer,"
+ " waiting for next answer... ");
+ ipmi_req_remove_entry(
+ rsp->payload.ipmi_response.rq_seq,
+ rsp->payload.ipmi_response.cmd);
+ return ipmi_lan_poll_recv(intf);
+ }
+ else
+ {
+ lprintf(LOG_DEBUG, "WARNING: Bridged "
+ "cmd ccode = 0x%02x",
+ rsp->data[offset-1]);
+ }
+
+ if (rsp->data_len &&
+ rsp->payload.ipmi_response.cmd == 0x34) {
+ memcpy(rsp->data, &rsp->data[offset],
+ (rsp->data_len-offset));
+ if (verbose > 2)
+ printbuf( &rsp->data[offset],
+ (rsp->data_len-offset),
+ "bridge command response");
+ }
+ }
+
+ ipmi_req_remove_entry(rsp->payload.ipmi_response.rq_seq,
+ rsp->payload.ipmi_response.cmd);
+ } else {
+ lprintf(LOG_INFO, "IPMI Request Match NOT FOUND");
+ rsp = ipmi_lan_recv_packet(intf);
+ continue;
+ }
+
+ /*
+ * Good packet. Shift response data to start of array.
+ * rsp->data becomes the variable length IPMI response data
+ * rsp->data_len becomes the length of that data
+ */
+ extra_data_length = payload_size - (offset - payload_start) - 1;
+ if (rsp != NULL && extra_data_length)
+ {
+ rsp->data_len = extra_data_length;
+ memmove(rsp->data, rsp->data + offset, extra_data_length);
+ }
+ else
+ rsp->data_len = 0;
+
+ break;
+ }
+
+
+ /*
+ * Open Response
+ */
+ else if (rsp->session.payloadtype ==
+ IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE)
+ {
+ if (session->v2_data.session_state !=
+ LANPLUS_STATE_OPEN_SESSION_SENT)
+ {
+ lprintf(LOG_ERR, "Error: Received an Unexpected Open Session "
+ "Response");
+ rsp = ipmi_lan_recv_packet(intf);
+ continue;
+ }
+
+ read_open_session_response(rsp, offset);
+ break;
+ }
+
+
+ /*
+ * RAKP 2
+ */
+ else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_2)
+ {
+ if (session->v2_data.session_state != LANPLUS_STATE_RAKP_1_SENT)
+ {
+ lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 2 message");
+ rsp = ipmi_lan_recv_packet(intf);
+ continue;
+ }
+
+ read_rakp2_message(rsp, offset, session->v2_data.auth_alg);
+ break;
+ }
+
+
+ /*
+ * RAKP 4
+ */
+ else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_4)
+ {
+ if (session->v2_data.session_state != LANPLUS_STATE_RAKP_3_SENT)
+ {
+ lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 4 message");
+ rsp = ipmi_lan_recv_packet(intf);
+ continue;
+ }
+
+ read_rakp4_message(rsp, offset, session->v2_data.auth_alg);
+ break;
+ }
+
+
+ /*
+ * SOL
+ */
+ else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL)
+ {
+ int payload_start = offset;
+ int extra_data_length;
+
+ if (session->v2_data.session_state != LANPLUS_STATE_ACTIVE)
+ {
+ lprintf(LOG_ERR, "Error: Received an Unexpected SOL packet");
+ rsp = ipmi_lan_recv_packet(intf);
+ continue;
+ }
+
+ read_sol_packet(rsp, &offset);
+ extra_data_length = payload_size - (offset - payload_start);
+ if (rsp && extra_data_length)
+ {
+ rsp->data_len = extra_data_length;
+ memmove(rsp->data, rsp->data + offset, extra_data_length);
+ }
+ else
+ rsp->data_len = 0;
+
+ break;
+ }
+
+ else
+ {
+ lprintf(LOG_ERR, "Invalid RMCP+ payload type : 0x%x",
+ rsp->session.payloadtype);
+ assert(0);
+ }
+ }
+
+ return rsp;
+}
+
+
+
+/*
+ * read_open_session_reponse
+ *
+ * Initialize the ipmi_rs from the IPMI 2.x open session response data.
+ *
+ * The offset should point to the first byte of the the Open Session Response
+ * payload when this function is called.
+ *
+ * param rsp [in/out] reading from the data and writing to the open_session_response
+ * section
+ * param offset [in] tells us where the Open Session Response payload starts
+ *
+ * returns 0 on success, 1 on error
+ */
+void
+read_open_session_response(struct ipmi_rs * rsp, int offset)
+{
+ memset(&rsp->payload.open_session_response, 0,
+ sizeof(rsp->payload.open_session_response));
+
+ /* Message tag */
+ rsp->payload.open_session_response.message_tag = rsp->data[offset];
+
+ /* RAKP reponse code */
+ rsp->payload.open_session_response.rakp_return_code = rsp->data[offset + 1];
+
+ /* Maximum privilege level */
+ rsp->payload.open_session_response.max_priv_level = rsp->data[offset + 2];
+
+ /*** offset + 3 is reserved ***/
+
+ /* Remote console session ID */
+ memcpy(&(rsp->payload.open_session_response.console_id),
+ rsp->data + offset + 4,
+ 4);
+ #if WORDS_BIGENDIAN
+ rsp->payload.open_session_response.console_id =
+ BSWAP_32(rsp->payload.open_session_response.console_id);
+ #endif
+
+ /* only tag, status, privlvl, and console id are returned if error */
+ if (rsp->payload.open_session_response.rakp_return_code !=
+ IPMI_RAKP_STATUS_NO_ERRORS)
+ return;
+
+ /* BMC session ID */
+ memcpy(&(rsp->payload.open_session_response.bmc_id),
+ rsp->data + offset + 8,
+ 4);
+ #if WORDS_BIGENDIAN
+ rsp->payload.open_session_response.bmc_id =
+ BSWAP_32(rsp->payload.open_session_response.bmc_id);
+ #endif
+
+ /* And of course, our negotiated algorithms */
+ rsp->payload.open_session_response.auth_alg = rsp->data[offset + 16];
+ rsp->payload.open_session_response.integrity_alg = rsp->data[offset + 24];
+ rsp->payload.open_session_response.crypt_alg = rsp->data[offset + 32];
+}
+
+
+
+/*
+ * read_rakp2_message
+ *
+ * Initialize the ipmi_rs from the IPMI 2.x RAKP 2 message
+ *
+ * The offset should point the first byte of the the RAKP 2 payload when this
+ * function is called.
+ *
+ * param rsp [in/out] reading from the data variable and writing to the rakp 2
+ * section
+ * param offset [in] tells us where hte rakp2 payload starts
+ * param auth_alg [in] describes the authentication algorithm was agreed upon in
+ * the open session request/response phase. We need to know that here so
+ * that we know how many bytes (if any) to read fromt the packet.
+ *
+ * returns 0 on success, 1 on error
+ */
+void
+read_rakp2_message(
+ struct ipmi_rs * rsp,
+ int offset,
+ uint8_t auth_alg)
+{
+ int i;
+
+ /* Message tag */
+ rsp->payload.rakp2_message.message_tag = rsp->data[offset];
+
+ /* RAKP reponse code */
+ rsp->payload.rakp2_message.rakp_return_code = rsp->data[offset + 1];
+
+ /* Console session ID */
+ memcpy(&(rsp->payload.rakp2_message.console_id),
+ rsp->data + offset + 4,
+ 4);
+ #if WORDS_BIGENDIAN
+ rsp->payload.rakp2_message.console_id =
+ BSWAP_32(rsp->payload.rakp2_message.console_id);
+ #endif
+
+ /* BMC random number */
+ memcpy(&(rsp->payload.rakp2_message.bmc_rand),
+ rsp->data + offset + 8,
+ 16);
+ #if WORDS_BIGENDIAN
+ lanplus_swap(rsp->payload.rakp2_message.bmc_rand, 16);
+ #endif
+
+ /* BMC GUID */
+ memcpy(&(rsp->payload.rakp2_message.bmc_guid),
+ rsp->data + offset + 24,
+ 16);
+ #if WORDS_BIGENDIAN
+ lanplus_swap(rsp->payload.rakp2_message.bmc_guid, 16);
+ #endif
+
+ /* Key exchange authentication code */
+ switch (auth_alg)
+ {
+ case IPMI_AUTH_RAKP_NONE:
+ /* Nothing to do here */
+ break;
+
+ case IPMI_AUTH_RAKP_HMAC_SHA1:
+ /* We need to copy 20 bytes */
+ for (i = 0; i < 20; ++i)
+ rsp->payload.rakp2_message.key_exchange_auth_code[i] =
+ rsp->data[offset + 40 + i];
+ break;
+
+ case IPMI_AUTH_RAKP_HMAC_MD5:
+ lprintf(LOG_ERR, "read_rakp2_message: no support for "
+ "IPMI_AUTH_RAKP_HMAC_MD5");
+ assert(0);
+ break;
+ }
+}
+
+
+
+/*
+ * read_rakp4_message
+ *
+ * Initialize the ipmi_rs from the IPMI 2.x RAKP 4 message
+ *
+ * The offset should point the first byte of the the RAKP 4 payload when this
+ * function is called.
+ *
+ * param rsp [in/out] reading from the data variable and writing to the rakp
+ * 4 section
+ * param offset [in] tells us where hte rakp4 payload starts
+ * param integrity_alg [in] describes the authentication algorithm was
+ * agreed upon in the open session request/response phase. We need
+ * to know that here so that we know how many bytes (if any) to read
+ * from the packet.
+ *
+ * returns 0 on success, 1 on error
+ */
+void
+read_rakp4_message(
+ struct ipmi_rs * rsp,
+ int offset,
+ uint8_t auth_alg)
+{
+ int i;
+
+ /* Message tag */
+ rsp->payload.rakp4_message.message_tag = rsp->data[offset];
+
+ /* RAKP reponse code */
+ rsp->payload.rakp4_message.rakp_return_code = rsp->data[offset + 1];
+
+ /* Console session ID */
+ memcpy(&(rsp->payload.rakp4_message.console_id),
+ rsp->data + offset + 4,
+ 4);
+ #if WORDS_BIGENDIAN
+ rsp->payload.rakp4_message.console_id =
+ BSWAP_32(rsp->payload.rakp4_message.console_id);
+ #endif
+
+
+ /* Integrity check value */
+ switch (auth_alg)
+ {
+ case IPMI_AUTH_RAKP_NONE:
+ /* Nothing to do here */
+ break;
+
+ case IPMI_AUTH_RAKP_HMAC_SHA1:
+ /* We need to copy 12 bytes */
+ for (i = 0; i < 12; ++i)
+ rsp->payload.rakp4_message.integrity_check_value[i] =
+ rsp->data[offset + 8 + i];
+ break;
+
+ case IPMI_AUTH_RAKP_HMAC_MD5:
+ lprintf(LOG_ERR, "read_rakp4_message: no support "
+ "for authentication algorithm 0x%x", auth_alg);
+ assert(0);
+ break;
+ }
+}
+
+
+
+
+/*
+ * read_session_data
+ *
+ * Initialize the ipmi_rsp from the session data in the packet
+ *
+ * The offset should point the first byte of the the IPMI session when this
+ * function is called.
+ *
+ * param rsp [in/out] we read from the data buffer and populate the session
+ * specific fields.
+ * param offset [in/out] should point to the beginning of the session when
+ * this function is called. The offset will be adjusted to
+ * point to the end of the session when this function exits.
+ * param session holds our session state
+ */
+void
+read_session_data(
+ struct ipmi_rs * rsp,
+ int * offset,
+ struct ipmi_session * s)
+{
+ /* We expect to read different stuff depending on the authtype */
+ rsp->session.authtype = rsp->data[*offset];
+
+ if (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS)
+ read_session_data_v2x(rsp, offset, s);
+ else
+ read_session_data_v15(rsp, offset, s);
+}
+
+
+
+/*
+ * read_session_data_v2x
+ *
+ * Initialize the ipmi_rsp from the v2.x session header of the packet.
+ *
+ * The offset should point to the first byte of the the IPMI session when this
+ * function is called. When this function exits, offset will point to the
+ * start of payload.
+ *
+ * Should decrypt and perform integrity checking here?
+ *
+ * param rsp [in/out] we read from the data buffer and populate the session
+ * specific fields.
+ * param offset [in/out] should point to the beginning of the session when this
+ * function is called. The offset will be adjusted to point to
+ * the end of the session when this function exits.
+ * param s holds our session state
+ */
+void
+read_session_data_v2x(
+ struct ipmi_rs * rsp,
+ int * offset,
+ struct ipmi_session * s)
+{
+ rsp->session.authtype = rsp->data[(*offset)++];
+
+ rsp->session.bEncrypted = (rsp->data[*offset] & 0x80 ? 1 : 0);
+ rsp->session.bAuthenticated = (rsp->data[*offset] & 0x40 ? 1 : 0);
+
+
+ /* Payload type */
+ rsp->session.payloadtype = rsp->data[(*offset)++] & 0x3F;
+
+ /* Session ID */
+ memcpy(&rsp->session.id, rsp->data + *offset, 4);
+ *offset += 4;
+ #if WORDS_BIGENDIAN
+ rsp->session.id = BSWAP_32(rsp->session.id);
+ #endif
+
+
+ /*
+ * Verify that the session ID is what we think it should be
+ */
+ if ((s->v2_data.session_state == LANPLUS_STATE_ACTIVE) &&
+ (rsp->session.id != s->v2_data.console_id))
+ {
+ lprintf(LOG_ERR, "packet session id 0x%x does not "
+ "match active session 0x%0x",
+ rsp->session.id, s->v2_data.console_id);
+ assert(0);
+ }
+
+
+ /* Ignored, so far */
+ memcpy(&rsp->session.seq, rsp->data + *offset, 4);
+ *offset += 4;
+ #if WORDS_BIGENDIAN
+ rsp->session.seq = BSWAP_32(rsp->session.seq);
+ #endif
+
+ memcpy(&rsp->session.msglen, rsp->data + *offset, 2);
+ *offset += 2;
+ #if WORDS_BIGENDIAN
+ rsp->session.msglen = BSWAP_16(rsp->session.msglen);
+ #endif
+}
+
+
+
+/*
+ * read_session_data_v15
+ *
+ * Initialize the ipmi_rsp from the session header of the packet.
+ *
+ * The offset should point the first byte of the the IPMI session when this
+ * function is called. When this function exits, the offset will point to
+ * the start of the IPMI message.
+ *
+ * param rsp [in/out] we read from the data buffer and populate the session
+ * specific fields.
+ * param offset [in/out] should point to the beginning of the session when this
+ * function is called. The offset will be adjusted to point to the
+ * end of the session when this function exits.
+ * param s holds our session state
+ */
+void read_session_data_v15(
+ struct ipmi_rs * rsp,
+ int * offset,
+ struct ipmi_session * s)
+{
+ /* All v15 messages are IPMI messages */
+ rsp->session.payloadtype = IPMI_PAYLOAD_TYPE_IPMI;
+
+ rsp->session.authtype = rsp->data[(*offset)++];
+
+ /* All v15 messages that we will receive are unencrypted/unauthenticated */
+ rsp->session.bEncrypted = 0;
+ rsp->session.bAuthenticated = 0;
+
+ /* skip the session id and sequence number fields */
+ *offset += 8;
+
+ /* This is the size of the whole payload */
+ rsp->session.msglen = rsp->data[(*offset)++];
+}
+
+
+
+/*
+ * read_ipmi_response
+ *
+ * Initialize the ipmi_rs from with the IPMI response specific data
+ *
+ * The offset should point the first byte of the the IPMI payload when this
+ * function is called.
+ *
+ * param rsp [in/out] we read from the data buffer and populate the IPMI
+ * specific fields.
+ * param offset [in/out] should point to the beginning of the IPMI payload when
+ * this function is called.
+ */
+void read_ipmi_response(struct ipmi_rs * rsp, int * offset)
+{
+ /*
+ * The data here should be decrypted by now.
+ */
+ rsp->payload.ipmi_response.rq_addr = rsp->data[(*offset)++];
+ rsp->payload.ipmi_response.netfn = rsp->data[*offset] >> 2;
+ rsp->payload.ipmi_response.rq_lun = rsp->data[(*offset)++] & 0x3;
+ (*offset)++; /* checksum */
+ rsp->payload.ipmi_response.rs_addr = rsp->data[(*offset)++];
+ rsp->payload.ipmi_response.rq_seq = rsp->data[*offset] >> 2;
+ rsp->payload.ipmi_response.rs_lun = rsp->data[(*offset)++] & 0x3;
+ rsp->payload.ipmi_response.cmd = rsp->data[(*offset)++];
+ rsp->ccode = rsp->data[(*offset)++];
+
+}
+
+
+
+/*
+ * read_sol_packet
+ *
+ * Initialize the ipmi_rs with the SOL response data
+ *
+ * The offset should point the first byte of the the SOL payload when this
+ * function is called.
+ *
+ * param rsp [in/out] we read from the data buffer and populate the
+ * SOL specific fields.
+ * param offset [in/out] should point to the beginning of the SOL payload
+ * when this function is called.
+ */
+void read_sol_packet(struct ipmi_rs * rsp, int * offset)
+{
+
+ /*
+ * The data here should be decrypted by now.
+ */
+ rsp->payload.sol_packet.packet_sequence_number =
+ rsp->data[(*offset)++] & 0x0F;
+
+ rsp->payload.sol_packet.acked_packet_number =
+ rsp->data[(*offset)++] & 0x0F;
+
+ rsp->payload.sol_packet.accepted_character_count =
+ rsp->data[(*offset)++];
+
+ rsp->payload.sol_packet.is_nack =
+ rsp->data[*offset] & 0x40;
+
+ rsp->payload.sol_packet.transfer_unavailable =
+ rsp->data[*offset] & 0x20;
+
+ rsp->payload.sol_packet.sol_inactive =
+ rsp->data[*offset] & 0x10;
+
+ rsp->payload.sol_packet.transmit_overrun =
+ rsp->data[*offset] & 0x08;
+
+ rsp->payload.sol_packet.break_detected =
+ rsp->data[(*offset)++] & 0x04;
+
+ lprintf(LOG_DEBUG, "<<<<<<<<<< RECV FROM BMC <<<<<<<<<<<");
+ lprintf(LOG_DEBUG, "< SOL sequence number : 0x%02x",
+ rsp->payload.sol_packet.packet_sequence_number);
+ lprintf(LOG_DEBUG, "< SOL acked packet : 0x%02x",
+ rsp->payload.sol_packet.acked_packet_number);
+ lprintf(LOG_DEBUG, "< SOL accepted char count : 0x%02x",
+ rsp->payload.sol_packet.accepted_character_count);
+ lprintf(LOG_DEBUG, "< SOL is nack : %s",
+ rsp->payload.sol_packet.is_nack? "true" : "false");
+ lprintf(LOG_DEBUG, "< SOL xfer unavailable : %s",
+ rsp->payload.sol_packet.transfer_unavailable? "true" : "false");
+ lprintf(LOG_DEBUG, "< SOL inactive : %s",
+ rsp->payload.sol_packet.sol_inactive? "true" : "false");
+ lprintf(LOG_DEBUG, "< SOL transmit overrun : %s",
+ rsp->payload.sol_packet.transmit_overrun? "true" : "false");
+ lprintf(LOG_DEBUG, "< SOL break detected : %s",
+ rsp->payload.sol_packet.break_detected? "true" : "false");
+ lprintf(LOG_DEBUG, "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
+
+ if (verbose >= 5)
+ printbuf(rsp->data + *offset - 4, 4, "SOL MSG FROM BMC");
+}
+
+
+
+/*
+ * getIpmiPayloadWireRep
+ *
+ * param out [out] will contain our wire representation
+ * param req [in] is the IPMI request to be written
+ * param crypt_alg [in] specifies the encryption to use
+ * param rq_seq [in] is the IPMI command sequence number.
+ */
+void getIpmiPayloadWireRep(
+ struct ipmi_intf * intf, /* in out */
+ struct ipmi_v2_payload * payload, /* in */
+ uint8_t * msg,
+ struct ipmi_rq * req,
+ uint8_t rq_seq,
+ uint8_t curr_seq)
+{
+ int cs, tmp, len;
+ int cs2 = 0;
+ int cs3 = 0;
+ uint8_t ourAddress = intf->my_addr;
+ uint8_t bridgedRequest = 0;
+
+ if (ourAddress == 0)
+ ourAddress = IPMI_BMC_SLAVE_ADDR;
+
+ len = 0;
+
+ /* IPMI Message Header -- Figure 13-4 of the IPMI v2.0 spec */
+ if ((intf->target_addr == ourAddress) || (!bridgePossible)) {
+ cs = len;
+ } else {
+ bridgedRequest = 1;
+
+ if(intf->transit_addr != ourAddress && intf->transit_addr != 0)
+ {
+ bridgedRequest++;
+ }
+ /* bridged request: encapsulate w/in Send Message */
+ cs = len;
+ msg[len++] = IPMI_BMC_SLAVE_ADDR;
+ msg[len++] = IPMI_NETFN_APP << 2;
+ tmp = len - cs;
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+ cs2 = len;
+ msg[len++] = IPMI_REMOTE_SWID;
+ msg[len++] = curr_seq << 2;
+
+
+ msg[len++] = 0x34; /* Send Message rqst */
+ if(bridgedRequest == 2)
+ msg[len++] = (0x40|intf->transit_channel); /* Track request*/
+ else
+ msg[len++] = (0x40|intf->target_channel); /* Track request*/
+
+ payload->payload_length += 7;
+ cs = len;
+
+ if(bridgedRequest == 2)
+ {
+ /* bridged request: encapsulate w/in Send Message */
+ cs = len;
+ msg[len++] = intf->transit_addr;
+ msg[len++] = IPMI_NETFN_APP << 2;
+ tmp = len - cs;
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+ cs3 = len;
+ msg[len++] = intf->my_addr;
+ msg[len++] = curr_seq << 2;
+ msg[len++] = 0x34; /* Send Message rqst */
+ #if 0 /* From lan.c example */
+ entry->req.msg.target_cmd = entry->req.msg.cmd; /* Save target command */
+ entry->req.msg.cmd = 0x34; /* (fixup request entry) */
+ #endif
+ msg[len++] = (0x40|intf->target_channel); /* Track request*/
+
+ payload->payload_length += 7;
+
+ cs = len;
+ }
+ }
+
+ lprintf(LOG_DEBUG,"%s RqAddr %#x transit %#x:%#x target %#x:%#x "
+ "bridgePossible %d",
+ bridgedRequest ? "Bridging" : "Local",
+ intf->my_addr, intf->transit_addr, intf->transit_channel,
+ intf->target_addr, intf->target_channel,
+ bridgePossible);
+
+ /* rsAddr */
+ msg[len++] = intf->target_addr; /* IPMI_BMC_SLAVE_ADDR; */
+
+ /* net Fn */
+ msg[len++] = req->msg.netfn << 2 | (req->msg.lun & 3);
+ tmp = len - cs;
+
+ /* checkSum */
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+ cs = len;
+
+ /* rqAddr */
+ if (!bridgedRequest)
+ msg[len++] = IPMI_REMOTE_SWID;
+ else /* Bridged message */
+ msg[len++] = intf->my_addr;
+
+ /* rqSeq / rqLUN */
+ msg[len++] = rq_seq << 2;
+
+ /* cmd */
+ msg[len++] = req->msg.cmd;
+
+ /* message data */
+ if (req->msg.data_len) {
+ memcpy(msg + len, req->msg.data, req->msg.data_len);
+ len += req->msg.data_len;
+ }
+
+ /* second checksum */
+ tmp = len - cs;
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+
+ /* Dual bridged request: 2nd checksum */
+ if (bridgedRequest == 2) {
+ tmp = len - cs3;
+ msg[len++] = ipmi_csum(msg+cs3, tmp);
+ payload->payload_length += 1;
+ }
+
+ /* bridged request: 2nd checksum */
+ if (bridgedRequest) {
+ tmp = len - cs2;
+ msg[len++] = ipmi_csum(msg+cs2, tmp);
+ payload->payload_length += 1;
+ }
+}
+
+
+
+/*
+ * getSolPayloadWireRep
+ *
+ * param msg [out] will contain our wire representation
+ * param payload [in] holds the v2 payload with our SOL data
+ */
+void getSolPayloadWireRep(
+ struct ipmi_intf * intf, /* in out */
+ uint8_t * msg, /* output */
+ struct ipmi_v2_payload * payload) /* input */
+{
+ int i = 0;
+
+ lprintf(LOG_DEBUG, ">>>>>>>>>> SENDING TO BMC >>>>>>>>>>");
+ lprintf(LOG_DEBUG, "> SOL sequence number : 0x%02x",
+ payload->payload.sol_packet.packet_sequence_number);
+ lprintf(LOG_DEBUG, "> SOL acked packet : 0x%02x",
+ payload->payload.sol_packet.acked_packet_number);
+ lprintf(LOG_DEBUG, "> SOL accepted char count : 0x%02x",
+ payload->payload.sol_packet.accepted_character_count);
+ lprintf(LOG_DEBUG, "> SOL is nack : %s",
+ payload->payload.sol_packet.is_nack ? "true" : "false");
+ lprintf(LOG_DEBUG, "> SOL assert ring wor : %s",
+ payload->payload.sol_packet.assert_ring_wor ? "true" : "false");
+ lprintf(LOG_DEBUG, "> SOL generate break : %s",
+ payload->payload.sol_packet.generate_break ? "true" : "false");
+ lprintf(LOG_DEBUG, "> SOL deassert cts : %s",
+ payload->payload.sol_packet.deassert_cts ? "true" : "false");
+ lprintf(LOG_DEBUG, "> SOL deassert dcd dsr : %s",
+ payload->payload.sol_packet.deassert_dcd_dsr ? "true" : "false");
+ lprintf(LOG_DEBUG, "> SOL flush inbound : %s",
+ payload->payload.sol_packet.flush_inbound ? "true" : "false");
+ lprintf(LOG_DEBUG, "> SOL flush outbound : %s",
+ payload->payload.sol_packet.flush_outbound ? "true" : "false");
+
+ msg[i++] = payload->payload.sol_packet.packet_sequence_number;
+ msg[i++] = payload->payload.sol_packet.acked_packet_number;
+ msg[i++] = payload->payload.sol_packet.accepted_character_count;
+
+ msg[i] = payload->payload.sol_packet.is_nack ? 0x40 : 0;
+ msg[i] |= payload->payload.sol_packet.assert_ring_wor ? 0x20 : 0;
+ msg[i] |= payload->payload.sol_packet.generate_break ? 0x10 : 0;
+ msg[i] |= payload->payload.sol_packet.deassert_cts ? 0x08 : 0;
+ msg[i] |= payload->payload.sol_packet.deassert_dcd_dsr ? 0x04 : 0;
+ msg[i] |= payload->payload.sol_packet.flush_inbound ? 0x02 : 0;
+ msg[i++] |= payload->payload.sol_packet.flush_outbound ? 0x01 : 0;
+
+ /* We may have data to add */
+ memcpy(msg + i,
+ payload->payload.sol_packet.data,
+ payload->payload.sol_packet.character_count);
+
+ lprintf(LOG_DEBUG, "> SOL character count : %d",
+ payload->payload.sol_packet.character_count);
+ lprintf(LOG_DEBUG, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
+
+ if (verbose >= 5 && payload->payload.sol_packet.character_count)
+ printbuf(payload->payload.sol_packet.data, payload->payload.sol_packet.character_count, "SOL SEND DATA");
+
+ /*
+ * At this point, the payload length becomes the whole payload
+ * length, including the 4 bytes at the beginning of the SOL
+ * packet
+ */
+ payload->payload_length = payload->payload.sol_packet.character_count + 4;
+}
+
+
+
+/*
+ * ipmi_lanplus_build_v2x_msg
+ *
+ * Encapsulates the payload data to create the IPMI v2.0 / RMCP+ packet.
+ *
+ *
+ * IPMI v2.0 LAN Request Message Format
+ * +----------------------+
+ * | rmcp.ver | 4 bytes
+ * | rmcp.__reserved |
+ * | rmcp.seq |
+ * | rmcp.class |
+ * +----------------------+
+ * | session.authtype | 10 bytes
+ * | session.payloadtype |
+ * | session.id |
+ * | session.seq |
+ * +----------------------+
+ * | message length | 2 bytes
+ * +----------------------+
+ * | Confidentiality Hdr | var (possibly absent)
+ * +----------------------+
+ * | Paylod | var Payload
+ * +----------------------+
+ * | Confidentiality Trlr | var (possibly absent)
+ * +----------------------+
+ * | Integrity pad | var (possibly absent)
+ * +----------------------+
+ * | Pad length | 1 byte (WTF?)
+ * +----------------------+
+ * | Next Header | 1 byte (WTF?)
+ * +----------------------+
+ * | Authcode | var (possibly absent)
+ * +----------------------+
+ */
+void
+ipmi_lanplus_build_v2x_msg(
+ struct ipmi_intf * intf, /* in */
+ struct ipmi_v2_payload * payload, /* in */
+ int * msg_len, /* out */
+ uint8_t ** msg_data, /* out */
+ uint8_t curr_seq)
+{
+ uint32_t session_trailer_length = 0;
+ struct ipmi_session * session = intf->session;
+ struct rmcp_hdr rmcp = {
+ .ver = RMCP_VERSION_1,
+ .class = RMCP_CLASS_IPMI,
+ .seq = 0xff,
+ };
+
+ /* msg will hold the entire message to be sent */
+ uint8_t * msg;
+ int len = 0;
+
+
+ len =
+ sizeof(rmcp) + // RMCP Header (4)
+ 10 + // IPMI Session Header
+ 2 + // Message length
+ payload->payload_length + // The actual payload
+ IPMI_MAX_INTEGRITY_PAD_SIZE + // Integrity Pad
+ 1 + // Pad Length
+ 1 + // Next Header
+ IPMI_MAX_AUTH_CODE_SIZE; // Authcode
+
+
+ msg = malloc(len);
+ if (msg == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return;
+ }
+ memset(msg, 0, len);
+
+ /*
+ *------------------------------------------
+ * RMCP HEADER
+ *------------------------------------------
+ */
+ memcpy(msg, &rmcp, sizeof(rmcp));
+ len = sizeof(rmcp);
+
+
+ /*
+ *------------------------------------------
+ * IPMI SESSION HEADER
+ *------------------------------------------
+ */
+ /* ipmi session Auth Type / Format is always 0x06 for IPMI v2 */
+ msg[IPMI_LANPLUS_OFFSET_AUTHTYPE] = 0x06;
+
+ /* Payload Type -- also specifies whether were authenticated/encyrpted */
+ msg[IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE] = payload->payload_type;
+
+ if (session->v2_data.session_state == LANPLUS_STATE_ACTIVE)
+ {
+ msg[IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE] |=
+ ((session->v2_data.crypt_alg != IPMI_CRYPT_NONE )? 0x80 : 0x00);
+ msg[IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE] |=
+ ((session->v2_data.integrity_alg != IPMI_INTEGRITY_NONE)? 0x40 : 0x00);
+ }
+
+ if (session->v2_data.session_state == LANPLUS_STATE_ACTIVE)
+ {
+ /* Session ID -- making it LSB */
+ msg[IPMI_LANPLUS_OFFSET_SESSION_ID ] = session->v2_data.bmc_id & 0xff;
+ msg[IPMI_LANPLUS_OFFSET_SESSION_ID + 1] = (session->v2_data.bmc_id >> 8) & 0xff;
+ msg[IPMI_LANPLUS_OFFSET_SESSION_ID + 2] = (session->v2_data.bmc_id >> 16) & 0xff;
+ msg[IPMI_LANPLUS_OFFSET_SESSION_ID + 3] = (session->v2_data.bmc_id >> 24) & 0xff;
+
+ /* Sequence Number -- making it LSB */
+ msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM ] = session->out_seq & 0xff;
+ msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM + 1] = (session->out_seq >> 8) & 0xff;
+ msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM + 2] = (session->out_seq >> 16) & 0xff;
+ msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM + 3] = (session->out_seq >> 24) & 0xff;
+ }
+
+ /*
+ * Payload Length is set below (we don't know how big the payload is until after
+ * encryption).
+ */
+
+ /*
+ * Payload
+ *
+ * At this point we are ready to slam the payload in.
+ * This includes:
+ * 1) The confidentiality header
+ * 2) The payload proper (possibly encrypted)
+ * 3) The confidentiality trailer
+ *
+ */
+ switch (payload->payload_type)
+ {
+ case IPMI_PAYLOAD_TYPE_IPMI:
+ getIpmiPayloadWireRep(intf,
+ payload, /* in */
+ msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
+ payload->payload.ipmi_request.request,
+ payload->payload.ipmi_request.rq_seq,
+ curr_seq);
+ break;
+
+ case IPMI_PAYLOAD_TYPE_SOL:
+ getSolPayloadWireRep(intf,
+ msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
+ payload);
+
+ if (verbose >= 5)
+ printbuf(msg + IPMI_LANPLUS_OFFSET_PAYLOAD, 4, "SOL MSG TO BMC");
+
+ len += payload->payload_length;
+
+ break;
+
+ case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST:
+ /* never encrypted, so our job is easy */
+ memcpy(msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
+ payload->payload.open_session_request.request,
+ payload->payload_length);
+ len += payload->payload_length;
+ break;
+
+ case IPMI_PAYLOAD_TYPE_RAKP_1:
+ /* never encrypted, so our job is easy */
+ memcpy(msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
+ payload->payload.rakp_1_message.message,
+ payload->payload_length);
+ len += payload->payload_length;
+ break;
+
+ case IPMI_PAYLOAD_TYPE_RAKP_3:
+ /* never encrypted, so our job is easy */
+ memcpy(msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
+ payload->payload.rakp_3_message.message,
+ payload->payload_length);
+ len += payload->payload_length;
+ break;
+
+ default:
+ lprintf(LOG_ERR, "unsupported payload type 0x%x",
+ payload->payload_type);
+ free(msg);
+ msg = NULL;
+ assert(0);
+ break;
+ }
+
+
+ /*
+ *------------------------------------------
+ * ENCRYPT THE PAYLOAD IF NECESSARY
+ *------------------------------------------
+ */
+ if (session->v2_data.session_state == LANPLUS_STATE_ACTIVE)
+ {
+ /* Payload len is adjusted as necessary by lanplus_encrypt_payload */
+ lanplus_encrypt_payload(session->v2_data.crypt_alg, /* input */
+ session->v2_data.k2, /* input */
+ msg + IPMI_LANPLUS_OFFSET_PAYLOAD, /* input */
+ payload->payload_length, /* input */
+ msg + IPMI_LANPLUS_OFFSET_PAYLOAD, /* output */
+ &(payload->payload_length)); /* output */
+
+ }
+
+ /* Now we know the payload length */
+ msg[IPMI_LANPLUS_OFFSET_PAYLOAD_SIZE ] =
+ payload->payload_length & 0xff;
+ msg[IPMI_LANPLUS_OFFSET_PAYLOAD_SIZE + 1] =
+ (payload->payload_length >> 8) & 0xff;
+
+
+ /*
+ *------------------------------------------
+ * SESSION TRAILER
+ *------------------------------------------
+ */
+ if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) &&
+ (session->v2_data.integrity_alg != IPMI_INTEGRITY_NONE))
+ {
+ uint32_t i, hmac_length, integrity_pad_size = 0, hmac_input_size;
+ uint8_t * hmac_output;
+ uint32_t start_of_session_trailer =
+ IPMI_LANPLUS_OFFSET_PAYLOAD +
+ payload->payload_length;
+
+
+ /*
+ * Determine the required integrity pad length. We have to make the
+ * data range covered by the authcode a multiple of 4.
+ */
+ uint32_t length_before_authcode;
+
+ if (ipmi_oem_active(intf, "icts")) {
+ length_before_authcode =
+ 12 + /* the stuff before the payload */
+ payload->payload_length;
+ } else {
+ length_before_authcode =
+ 12 + /* the stuff before the payload */
+ payload->payload_length +
+ 1 + /* pad length field */
+ 1; /* next header field */
+ }
+
+ if (length_before_authcode % 4)
+ integrity_pad_size = 4 - (length_before_authcode % 4);
+
+ for (i = 0; i < integrity_pad_size; ++i)
+ msg[start_of_session_trailer + i] = 0xFF;
+
+ /* Pad length */
+ msg[start_of_session_trailer + integrity_pad_size] = integrity_pad_size;
+
+ /* Next Header */
+ msg[start_of_session_trailer + integrity_pad_size + 1] =
+ 0x07; /* Hardcoded per the spec, table 13-8 */
+
+ hmac_input_size =
+ 12 +
+ payload->payload_length +
+ integrity_pad_size +
+ 2;
+
+ hmac_output =
+ msg +
+ IPMI_LANPLUS_OFFSET_PAYLOAD +
+ payload->payload_length +
+ integrity_pad_size +
+ 2;
+
+ if (verbose > 2)
+ printbuf(msg + IPMI_LANPLUS_OFFSET_AUTHTYPE, hmac_input_size, "authcode input");
+
+
+ /* Auth Code */
+ lanplus_HMAC(session->v2_data.integrity_alg,
+ session->v2_data.k1, /* key */
+ 20, /* key length */
+ msg + IPMI_LANPLUS_OFFSET_AUTHTYPE, /* hmac input */
+ hmac_input_size,
+ hmac_output,
+ &hmac_length);
+
+ assert(hmac_length == 20);
+
+ if (verbose > 2)
+ printbuf(hmac_output, 12, "authcode output");
+
+ /* Set session_trailer_length appropriately */
+ session_trailer_length =
+ integrity_pad_size +
+ 2 + /* pad length + next header */
+ 12; /* Size of the authcode (we only use the first 12 bytes) */
+ }
+
+
+ ++(session->out_seq);
+ if (!session->out_seq)
+ ++(session->out_seq);
+
+ *msg_len =
+ IPMI_LANPLUS_OFFSET_PAYLOAD +
+ payload->payload_length +
+ session_trailer_length;
+ *msg_data = msg;
+}
+
+
+
+/*
+ * ipmi_lanplus_build_v2x_ipmi_cmd
+ *
+ * Wraps ipmi_lanplus_build_v2x_msg and returns a new entry object for the
+ * command
+ *
+ */
+static struct ipmi_rq_entry *
+ipmi_lanplus_build_v2x_ipmi_cmd(
+ struct ipmi_intf * intf,
+ struct ipmi_rq * req,
+ int isRetry)
+{
+ struct ipmi_v2_payload v2_payload;
+ struct ipmi_rq_entry * entry;
+
+ /*
+ * We have a problem. we need to know the sequence number here,
+ * because we use it in our stored entry. But we also need to
+ * know the sequence number when we generate our IPMI
+ * representation far below.
+ */
+ static uint8_t curr_seq = 0;
+
+ if( isRetry == 0 )
+ curr_seq += 1;
+
+ if (curr_seq >= 64)
+ curr_seq = 0;
+
+
+ /* IPMI Message Header -- Figure 13-4 of the IPMI v2.0 spec */
+ if ((intf->target_addr == intf->my_addr) || (!bridgePossible))
+ {
+ entry = ipmi_req_add_entry(intf, req, curr_seq);
+ }
+ else /* it's a bridge command */
+ {
+ unsigned char backup_cmd;
+
+ /* Add entry for cmd */
+ entry = ipmi_req_add_entry(intf, req, curr_seq);
+
+ if(entry)
+ {
+ /* Add entry for bridge cmd */
+ backup_cmd = req->msg.cmd;
+ req->msg.cmd = 0x34;
+ entry = ipmi_req_add_entry(intf, req, curr_seq);
+ req->msg.cmd = backup_cmd;
+ }
+ }
+
+ if (entry == NULL)
+ return NULL;
+
+ // Build our payload
+ v2_payload.payload_type = IPMI_PAYLOAD_TYPE_IPMI;
+ v2_payload.payload_length = req->msg.data_len + 7;
+ v2_payload.payload.ipmi_request.request = req;
+ v2_payload.payload.ipmi_request.rq_seq = curr_seq;
+
+ ipmi_lanplus_build_v2x_msg(intf, // in
+ &v2_payload, // in
+ &(entry->msg_len), // out
+ &(entry->msg_data), // out
+ curr_seq); // in
+
+ return entry;
+}
+
+
+
+
+
+/*
+ * IPMI LAN Request Message Format
+ * +--------------------+
+ * | rmcp.ver | 4 bytes
+ * | rmcp.__reserved |
+ * | rmcp.seq |
+ * | rmcp.class |
+ * +--------------------+
+ * | session.authtype | 9 bytes
+ * | session.seq |
+ * | session.id |
+ * +--------------------+
+ * | [session.authcode] | 16 bytes (AUTHTYPE != none)
+ * +--------------------+
+ * | message length | 1 byte
+ * +--------------------+
+ * | message.rs_addr | 6 bytes
+ * | message.netfn_lun |
+ * | message.checksum |
+ * | message.rq_addr |
+ * | message.rq_seq |
+ * | message.cmd |
+ * +--------------------+
+ * | [request data] | data_len bytes
+ * +--------------------+
+ * | checksum | 1 byte
+ * +--------------------+
+ */
+static struct ipmi_rq_entry *
+ipmi_lanplus_build_v15_ipmi_cmd(
+ struct ipmi_intf * intf,
+ struct ipmi_rq * req)
+{
+ struct rmcp_hdr rmcp = {
+ .ver = RMCP_VERSION_1,
+ .class = RMCP_CLASS_IPMI,
+ .seq = 0xff,
+ };
+ uint8_t * msg;
+ int cs, mp, len = 0, tmp;
+ struct ipmi_session * session = intf->session;
+ struct ipmi_rq_entry * entry;
+
+ entry = ipmi_req_add_entry(intf, req, 0);
+ if (entry == NULL)
+ return NULL;
+
+ len = req->msg.data_len + 21;
+
+ msg = malloc(len);
+ if (msg == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return NULL;
+ }
+ memset(msg, 0, len);
+
+ /* rmcp header */
+ memcpy(msg, &rmcp, sizeof(rmcp));
+ len = sizeof(rmcp);
+
+ /*
+ * ipmi session header
+ */
+ /* Authtype should always be none for 1.5 packets sent from this
+ * interface
+ */
+ msg[len++] = IPMI_SESSION_AUTHTYPE_NONE;
+
+ msg[len++] = session->out_seq & 0xff;
+ msg[len++] = (session->out_seq >> 8) & 0xff;
+ msg[len++] = (session->out_seq >> 16) & 0xff;
+ msg[len++] = (session->out_seq >> 24) & 0xff;
+
+ /*
+ * The session ID should be all zeroes for pre-session commands. We
+ * should only be using the 1.5 interface for the pre-session Get
+ * Channel Authentication Capabilities command
+ */
+ msg[len++] = 0;
+ msg[len++] = 0;
+ msg[len++] = 0;
+ msg[len++] = 0;
+
+ /* message length */
+ msg[len++] = req->msg.data_len + 7;
+
+ /* ipmi message header */
+ cs = mp = len;
+ msg[len++] = IPMI_BMC_SLAVE_ADDR;
+ msg[len++] = req->msg.netfn << 2;
+ tmp = len - cs;
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+ cs = len;
+ msg[len++] = IPMI_REMOTE_SWID;
+
+ entry->rq_seq = 0;
+
+ msg[len++] = entry->rq_seq << 2;
+ msg[len++] = req->msg.cmd;
+
+ lprintf(LOG_DEBUG+1, ">> IPMI Request Session Header");
+ lprintf(LOG_DEBUG+1, ">> Authtype : %s",
+ val2str(IPMI_SESSION_AUTHTYPE_NONE, ipmi_authtype_session_vals));
+ lprintf(LOG_DEBUG+1, ">> Sequence : 0x%08lx",
+ (long)session->out_seq);
+ lprintf(LOG_DEBUG+1, ">> Session ID : 0x%08lx",
+ (long)0);
+
+ lprintf(LOG_DEBUG+1, ">> IPMI Request Message Header");
+ lprintf(LOG_DEBUG+1, ">> Rs Addr : %02x", IPMI_BMC_SLAVE_ADDR);
+ lprintf(LOG_DEBUG+1, ">> NetFn : %02x", req->msg.netfn);
+ lprintf(LOG_DEBUG+1, ">> Rs LUN : %01x", 0);
+ lprintf(LOG_DEBUG+1, ">> Rq Addr : %02x", IPMI_REMOTE_SWID);
+ lprintf(LOG_DEBUG+1, ">> Rq Seq : %02x", entry->rq_seq);
+ lprintf(LOG_DEBUG+1, ">> Rq Lun : %01x", 0);
+ lprintf(LOG_DEBUG+1, ">> Command : %02x", req->msg.cmd);
+
+ /* message data */
+ if (req->msg.data_len) {
+ memcpy(msg+len, req->msg.data, req->msg.data_len);
+ len += req->msg.data_len;
+ }
+
+ /* second checksum */
+ tmp = len - cs;
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+
+ entry->msg_len = len;
+ entry->msg_data = msg;
+
+ return entry;
+}
+
+
+
+/*
+ * is_sol_packet
+ */
+static int
+is_sol_packet(struct ipmi_rs * rsp)
+{
+ return (rsp &&
+ (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
+ (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL));
+}
+
+
+
+/*
+ * sol_response_acks_packet
+ */
+static int
+sol_response_acks_packet(
+ struct ipmi_rs * rsp,
+ struct ipmi_v2_payload * payload)
+{
+ return (is_sol_packet(rsp) &&
+ payload &&
+ (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL) &&
+ (rsp->payload.sol_packet.acked_packet_number ==
+ payload->payload.sol_packet.packet_sequence_number));
+}
+
+
+
+/*
+ * ipmi_lanplus_send_payload
+ *
+ */
+struct ipmi_rs *
+ipmi_lanplus_send_payload(
+ struct ipmi_intf * intf,
+ struct ipmi_v2_payload * payload)
+{
+ struct ipmi_rs * rsp = NULL;
+ uint8_t * msg_data;
+ int msg_length;
+ struct ipmi_session * session = intf->session;
+ struct ipmi_rq_entry * entry = NULL;
+ int try = 0;
+ int xmit = 1;
+ time_t ltime;
+ uint32_t saved_timeout;
+
+ if (!intf->opened && intf->open && intf->open(intf) < 0)
+ return NULL;
+
+ /*
+ * The session timeout is initialized in the above interface open,
+ * so it will only be valid after the open completes.
+ */
+ saved_timeout = session->timeout;
+ while (try < session->retry) {
+ //ltime = time(NULL);
+
+ if (xmit) {
+ ltime = time(NULL);
+
+ if (payload->payload_type == IPMI_PAYLOAD_TYPE_IPMI)
+ {
+ /*
+ * Build an IPMI v1.5 or v2 command
+ */
+ struct ipmi_rq * ipmi_request = payload->payload.ipmi_request.request;
+
+ lprintf(LOG_DEBUG, "");
+ lprintf(LOG_DEBUG, ">> Sending IPMI command payload");
+ lprintf(LOG_DEBUG, ">> netfn : 0x%02x", ipmi_request->msg.netfn);
+ lprintf(LOG_DEBUG, ">> command : 0x%02x", ipmi_request->msg.cmd);
+
+ if (verbose > 1)
+ {
+ uint16_t i;
+ fprintf(stderr, ">> data : ");
+ for (i = 0; i < ipmi_request->msg.data_len; ++i)
+ fprintf(stderr, "0x%02x ", ipmi_request->msg.data[i]);
+ fprintf(stderr, "\n\n");
+ }
+
+
+ /*
+ * If we are presession, and the command is GET CHANNEL AUTHENTICATION
+ * CAPABILITIES, we will build the command in v1.5 format. This is so
+ * that we can ask any server whether it supports IPMI v2 / RMCP+
+ * before we attempt to open a v2.x session.
+ */
+ if ((ipmi_request->msg.netfn == IPMI_NETFN_APP) &&
+ (ipmi_request->msg.cmd == IPMI_GET_CHANNEL_AUTH_CAP) &&
+ (session->v2_data.bmc_id == 0)) // jme - check
+ {
+ lprintf(LOG_DEBUG+1, "BUILDING A v1.5 COMMAND");
+ entry = ipmi_lanplus_build_v15_ipmi_cmd(intf, ipmi_request);
+ }
+ else
+ {
+ int isRetry = ( try > 0 ? 1 : 0 );
+
+ lprintf(LOG_DEBUG+1, "BUILDING A v2 COMMAND");
+ entry = ipmi_lanplus_build_v2x_ipmi_cmd(intf, ipmi_request, isRetry);
+ }
+
+ if (entry == NULL) {
+ lprintf(LOG_ERR, "Aborting send command, unable to build");
+ return NULL;
+ }
+
+ msg_data = entry->msg_data;
+ msg_length = entry->msg_len;
+ }
+
+ else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST)
+ {
+ lprintf(LOG_DEBUG, ">> SENDING AN OPEN SESSION REQUEST\n");
+ assert(session->v2_data.session_state == LANPLUS_STATE_PRESESSION
+ || session->v2_data.session_state == LANPLUS_STATE_OPEN_SESSION_SENT);
+
+ ipmi_lanplus_build_v2x_msg(intf, /* in */
+ payload, /* in */
+ &msg_length, /* out */
+ &msg_data, /* out */
+ 0); /* irrelevant for this msg*/
+
+ }
+
+ else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RAKP_1)
+ {
+ lprintf(LOG_DEBUG, ">> SENDING A RAKP 1 MESSAGE\n");
+ assert(session->v2_data.session_state ==
+ LANPLUS_STATE_OPEN_SESSION_RECEIEVED);
+
+ ipmi_lanplus_build_v2x_msg(intf, /* in */
+ payload, /* in */
+ &msg_length, /* out */
+ &msg_data, /* out */
+ 0); /* irrelevant for this msg*/
+
+ }
+
+ else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RAKP_3)
+ {
+ lprintf(LOG_DEBUG, ">> SENDING A RAKP 3 MESSAGE\n");
+ assert(session->v2_data.session_state ==
+ LANPLUS_STATE_RAKP_2_RECEIVED);
+
+ ipmi_lanplus_build_v2x_msg(intf, /* in */
+ payload, /* in */
+ &msg_length, /* out */
+ &msg_data, /* out */
+ 0); /* irrelevant for this msg*/
+
+ }
+
+ else if (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL)
+ {
+ lprintf(LOG_DEBUG, ">> SENDING A SOL MESSAGE\n");
+ assert(session->v2_data.session_state == LANPLUS_STATE_ACTIVE);
+
+ ipmi_lanplus_build_v2x_msg(intf, /* in */
+ payload, /* in */
+ &msg_length, /* out */
+ &msg_data, /* out */
+ 0); /* irrelevant for this msg*/
+ }
+
+ else
+ {
+ lprintf(LOG_ERR, "Payload type 0x%0x is unsupported!",
+ payload->payload_type);
+ assert(0);
+ }
+
+
+ if (ipmi_lan_send_packet(intf, msg_data, msg_length) < 0) {
+ lprintf(LOG_ERR, "IPMI LAN send command failed");
+ return NULL;
+ }
+ }
+
+ /* if we are set to noanswer we do not expect response */
+ if (intf->noanswer)
+ break;
+
+ usleep(100); /* Not sure what this is for */
+
+ /* Remember our connection state */
+ switch (payload->payload_type)
+ {
+ case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST:
+ session->v2_data.session_state = LANPLUS_STATE_OPEN_SESSION_SENT;
+ /* not retryable for timeouts, force no retry */
+ try = session->retry;
+ break;
+ case IPMI_PAYLOAD_TYPE_RAKP_1:
+ session->v2_data.session_state = LANPLUS_STATE_RAKP_1_SENT;
+ /* not retryable for timeouts, force no retry */
+ try = session->retry;
+ break;
+ case IPMI_PAYLOAD_TYPE_RAKP_3:
+ /* not retryable for timeouts, force no retry */
+ try = session->retry;
+ session->v2_data.session_state = LANPLUS_STATE_RAKP_3_SENT;
+ break;
+ }
+
+
+ /*
+ * Special case for SOL outbound packets.
+ */
+ if (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL)
+ {
+ if (! payload->payload.sol_packet.packet_sequence_number)
+ {
+ /* We're just sending an ACK. No need to retry. */
+ break;
+ }
+
+
+ rsp = ipmi_lanplus_recv_sol(intf); /* Grab the next packet */
+
+ if (sol_response_acks_packet(rsp, payload))
+ break;
+
+ else if (is_sol_packet(rsp) && rsp->data_len)
+ {
+ /*
+ * We're still waiting for our ACK, but we more data from
+ * the BMC
+ */
+ intf->session->sol_data.sol_input_handler(rsp);
+ /* In order to avoid duplicate output, just set data_len to 0 */
+ rsp->data_len = 0;
+ }
+ }
+
+
+ /* Non-SOL processing */
+ else
+ {
+ rsp = ipmi_lan_poll_recv(intf);
+
+ /* Duplicate Request ccode most likely indicates a response to
+ a previous retry. Ignore and keep polling. */
+ while ((rsp != NULL) && (rsp->ccode == 0xcf))
+ {
+ rsp = NULL;
+ rsp = ipmi_lan_poll_recv(intf);
+ }
+
+ if (rsp)
+ break;
+ /* This payload type is retryable for timeouts. */
+ if ((payload->payload_type == IPMI_PAYLOAD_TYPE_IPMI) && entry) {
+ ipmi_req_remove_entry( entry->rq_seq, entry->req.msg.cmd);
+ }
+ }
+
+ /* only timeout if time exceeds the timeout value */
+ xmit = ((time(NULL) - ltime) >= session->timeout);
+
+ usleep(5000);
+
+ if (xmit) {
+ /* increment session timeout by 1 second each retry */
+ session->timeout++;
+ }
+
+ try++;
+ }
+ session->timeout = saved_timeout;
+
+ /* IPMI messages are deleted under ipmi_lan_poll_recv() */
+ switch (payload->payload_type) {
+ case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST:
+ case IPMI_PAYLOAD_TYPE_RAKP_1:
+ case IPMI_PAYLOAD_TYPE_RAKP_3:
+ free(msg_data);
+ msg_data = NULL;
+ break;
+ }
+
+ return rsp;
+}
+
+
+
+/*
+ * is_sol_partial_ack
+ *
+ * Determine if the response is a partial ACK/NACK that indicates
+ * we need to resend part of our packet.
+ *
+ * returns the number of characters we need to resend, or
+ * 0 if this isn't an ACK or we don't need to resend anything
+ */
+int is_sol_partial_ack(
+ struct ipmi_intf * intf,
+ struct ipmi_v2_payload * v2_payload,
+ struct ipmi_rs * rs)
+{
+ int chars_to_resend = 0;
+
+ if (v2_payload &&
+ rs &&
+ is_sol_packet(rs) &&
+ sol_response_acks_packet(rs, v2_payload) &&
+ (rs->payload.sol_packet.accepted_character_count <
+ v2_payload->payload.sol_packet.character_count))
+ {
+ if (ipmi_oem_active(intf, "intelplus") &&
+ rs->payload.sol_packet.accepted_character_count == 0)
+ return 0;
+
+ chars_to_resend =
+ v2_payload->payload.sol_packet.character_count -
+ rs->payload.sol_packet.accepted_character_count;
+ }
+
+ return chars_to_resend;
+}
+
+
+
+/*
+ * set_sol_packet_sequence_number
+ */
+static void set_sol_packet_sequence_number(
+ struct ipmi_intf * intf,
+ struct ipmi_v2_payload * v2_payload)
+{
+ /* Keep our sequence number sane */
+ if (intf->session->sol_data.sequence_number > 0x0F)
+ intf->session->sol_data.sequence_number = 1;
+
+ v2_payload->payload.sol_packet.packet_sequence_number =
+ intf->session->sol_data.sequence_number++;
+}
+
+
+
+/*
+ * ipmi_lanplus_send_sol
+ *
+ * Sends a SOL packet.. We handle partial ACK/NACKs from the BMC here.
+ *
+ * Returns a pointer to the SOL ACK we received, or
+ * 0 on failure
+ *
+ */
+struct ipmi_rs *
+ipmi_lanplus_send_sol(
+ struct ipmi_intf * intf,
+ struct ipmi_v2_payload * v2_payload)
+{
+ struct ipmi_rs * rs;
+
+ /*
+ * chars_to_resend indicates either that we got a NACK telling us
+ * that we need to resend some part of our data.
+ */
+ int chars_to_resend = 0;
+
+ v2_payload->payload_type = IPMI_PAYLOAD_TYPE_SOL;
+
+ /*
+ * Payload length is just the length of the character
+ * data here.
+ */
+ v2_payload->payload_length = v2_payload->payload.sol_packet.character_count;
+
+ v2_payload->payload.sol_packet.acked_packet_number = 0; /* NA */
+
+ set_sol_packet_sequence_number(intf, v2_payload);
+
+ v2_payload->payload.sol_packet.accepted_character_count = 0; /* NA */
+
+ rs = ipmi_lanplus_send_payload(intf, v2_payload);
+
+ /* Determine if we need to resend some of our data */
+ chars_to_resend = is_sol_partial_ack(intf, v2_payload, rs);
+
+ while (rs && !rs->payload.sol_packet.transfer_unavailable &&
+ !rs->payload.sol_packet.is_nack &&
+ chars_to_resend)
+ {
+ /*
+ * We first need to handle any new data we might have
+ * received in our NACK
+ */
+ if (rs->data_len)
+ intf->session->sol_data.sol_input_handler(rs);
+
+ set_sol_packet_sequence_number(intf, v2_payload);
+
+ /* Just send the required data */
+ memmove(v2_payload->payload.sol_packet.data,
+ v2_payload->payload.sol_packet.data +
+ rs->payload.sol_packet.accepted_character_count,
+ chars_to_resend);
+
+ v2_payload->payload.sol_packet.character_count = chars_to_resend;
+
+ v2_payload->payload_length = v2_payload->payload.sol_packet.character_count;
+
+ rs = ipmi_lanplus_send_payload(intf, v2_payload);
+
+ chars_to_resend = is_sol_partial_ack(intf, v2_payload, rs);
+ }
+
+ return rs;
+}
+
+
+
+/*
+ * check_sol_packet_for_new_data
+ *
+ * Determine whether the SOL packet has already been seen
+ * and whether the packet has new data for us.
+ *
+ * This function has the side effect of removing an previously
+ * seen data, and moving new data to the front.
+ *
+ * It also "Remembers" the data so we don't get repeats.
+ *
+ * returns the number of new bytes in the SOL packet
+ */
+static int
+check_sol_packet_for_new_data(
+ struct ipmi_intf * intf,
+ struct ipmi_rs *rsp)
+{
+ static uint8_t last_received_sequence_number = 0;
+ static uint8_t last_received_byte_count = 0;
+ int new_data_size = 0;
+
+
+ if (rsp &&
+ (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
+ (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL))
+ {
+ /* Store the data length before we mod it */
+ uint8_t unaltered_data_len = rsp->data_len;
+
+ if (rsp->payload.sol_packet.packet_sequence_number ==
+ last_received_sequence_number)
+ {
+
+ /*
+ * This is the same as the last packet, but may include
+ * extra data
+ */
+ new_data_size = rsp->data_len - last_received_byte_count;
+
+ if (new_data_size > 0)
+ {
+ /* We have more data to process */
+ memmove(rsp->data,
+ rsp->data +
+ rsp->data_len - new_data_size,
+ new_data_size);
+ }
+
+ rsp->data_len = new_data_size;
+ }
+
+
+ /*
+ *Rember the data for next round
+ */
+ if (rsp->payload.sol_packet.packet_sequence_number)
+ {
+ last_received_sequence_number =
+ rsp->payload.sol_packet.packet_sequence_number;
+
+ last_received_byte_count = unaltered_data_len;
+ }
+ }
+
+
+ return new_data_size;
+}
+
+
+
+/*
+ * ack_sol_packet
+ *
+ * Provided the specified packet looks reasonable, ACK it.
+ */
+static void
+ack_sol_packet(
+ struct ipmi_intf * intf,
+ struct ipmi_rs * rsp)
+{
+ if (rsp &&
+ (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
+ (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) &&
+ (rsp->payload.sol_packet.packet_sequence_number))
+ {
+ struct ipmi_v2_payload ack;
+
+ bzero(&ack, sizeof(struct ipmi_v2_payload));
+
+ ack.payload_type = IPMI_PAYLOAD_TYPE_SOL;
+
+ /*
+ * Payload length is just the length of the character
+ * data here.
+ */
+ ack.payload_length = 0;
+
+ /* ACK packets have sequence numbers of 0 */
+ ack.payload.sol_packet.packet_sequence_number = 0;
+
+ ack.payload.sol_packet.acked_packet_number =
+ rsp->payload.sol_packet.packet_sequence_number;
+
+ ack.payload.sol_packet.accepted_character_count = rsp->data_len;
+
+ ipmi_lanplus_send_payload(intf, &ack);
+ }
+}
+
+
+
+/*
+ * ipmi_lanplus_recv_sol
+ *
+ * Receive a SOL packet and send an ACK in response.
+ *
+ */
+struct ipmi_rs *
+ipmi_lanplus_recv_sol(struct ipmi_intf * intf)
+{
+ struct ipmi_rs * rsp = ipmi_lan_poll_recv(intf);
+
+ if (rsp && rsp->session.authtype != 0)
+ {
+ ack_sol_packet(intf, rsp);
+
+ /*
+ * Remembers the data sent, and alters the data to just
+ * include the new stuff.
+ */
+ check_sol_packet_for_new_data(intf, rsp);
+ }
+ return rsp;
+}
+
+
+
+/**
+ * ipmi_lanplus_send_ipmi_cmd
+ *
+ * Build a payload request and dispatch it.
+ */
+struct ipmi_rs *
+ipmi_lanplus_send_ipmi_cmd(
+ struct ipmi_intf * intf,
+ struct ipmi_rq * req)
+{
+ struct ipmi_v2_payload v2_payload;
+
+ v2_payload.payload_type = IPMI_PAYLOAD_TYPE_IPMI;
+ v2_payload.payload.ipmi_request.request = req;
+
+ return ipmi_lanplus_send_payload(intf, &v2_payload);
+}
+
+
+/*
+ * ipmi_get_auth_capabilities_cmd
+ *
+ * This command may have to be sent twice. We first ask for the
+ * authentication capabilities with the "request IPMI v2 data bit"
+ * set. If this fails, we send the same command without that bit
+ * set.
+ *
+ * param intf is the initialized (but possibly) pre-session interface
+ * on which we will send the command
+ * param auth_cap [out] will be initialized to hold the Get Channel
+ * Authentication Capabilities return data on success. Its
+ * contents will be undefined on error.
+ *
+ * returns 0 on success
+ * non-zero if we were unable to contact the BMC, or we cannot
+ * get a successful response
+ *
+ */
+static int
+ipmi_get_auth_capabilities_cmd(
+ struct ipmi_intf * intf,
+ struct get_channel_auth_cap_rsp * auth_cap)
+{
+ struct ipmi_rs * rsp;
+ struct ipmi_rq req;
+ uint8_t msg_data[2];
+ uint8_t backupBridgePossible;
+
+ backupBridgePossible = bridgePossible;
+
+ bridgePossible = 0;
+
+ msg_data[0] = IPMI_LAN_CHANNEL_E | 0x80; // Ask for IPMI v2 data as well
+ msg_data[1] = intf->session->privlvl;
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_APP; // 0x06
+ req.msg.cmd = IPMI_GET_CHANNEL_AUTH_CAP; // 0x38
+ req.msg.data = msg_data;
+ req.msg.data_len = 2;
+
+ rsp = intf->sendrecv(intf, &req);
+
+ if (rsp == NULL || rsp->ccode > 0) {
+ /*
+ * It's very possible that this failed because we asked for IPMI
+ * v2 data. Ask again, without requesting IPMI v2 data.
+ */
+ msg_data[0] &= 0x7F;
+
+ rsp = intf->sendrecv(intf, &req);
+
+ if (rsp == NULL) {
+ lprintf(LOG_INFO, "Get Auth Capabilities error");
+ return 1;
+ }
+ if (rsp->ccode > 0) {
+ lprintf(LOG_INFO, "Get Auth Capabilities error: %s",
+ val2str(rsp->ccode, completion_code_vals));
+ return 1;
+ }
+ }
+
+
+ memcpy(auth_cap,
+ rsp->data,
+ sizeof(struct get_channel_auth_cap_rsp));
+
+ bridgePossible = backupBridgePossible;
+
+ return 0;
+}
+
+
+
+static int
+ipmi_close_session_cmd(struct ipmi_intf * intf)
+{
+ struct ipmi_rs * rsp;
+ struct ipmi_rq req;
+ uint8_t msg_data[4];
+ uint32_t bmc_session_lsbf;
+ uint8_t backupBridgePossible;
+
+ if (intf->session->v2_data.session_state != LANPLUS_STATE_ACTIVE)
+ return -1;
+
+ backupBridgePossible = bridgePossible;
+
+ intf->target_addr = IPMI_BMC_SLAVE_ADDR;
+ bridgePossible = 0;
+
+ bmc_session_lsbf = intf->session->v2_data.bmc_id;
+#if WORDS_BIGENDIAN
+ bmc_session_lsbf = BSWAP_32(bmc_session_lsbf);
+#endif
+
+ memcpy(&msg_data, &bmc_session_lsbf, 4);
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_APP;
+ req.msg.cmd = 0x3c;
+ req.msg.data = msg_data;
+ req.msg.data_len = 4;
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL) {
+ /* Looks like the session was closed */
+ lprintf(LOG_ERR, "Close Session command failed");
+ return -1;
+ }
+ if (verbose > 2)
+ printbuf(rsp->data, rsp->data_len, "close_session");
+
+ if (rsp->ccode == 0x87) {
+ lprintf(LOG_ERR, "Failed to Close Session: invalid "
+ "session ID %08lx",
+ (long)intf->session->v2_data.bmc_id);
+ return -1;
+ }
+ if (rsp->ccode > 0) {
+ lprintf(LOG_ERR, "Close Session command failed: %s",
+ val2str(rsp->ccode, completion_code_vals));
+ return -1;
+ }
+
+ lprintf(LOG_DEBUG, "Closed Session %08lx\n",
+ (long)intf->session->v2_data.bmc_id);
+
+ bridgePossible = backupBridgePossible;
+
+ return 0;
+}
+
+
+
+/*
+ * ipmi_lanplus_open_session
+ *
+ * Build and send the open session command. See section 13.17 of the IPMI
+ * v2 specification for details.
+ */
+static int
+ipmi_lanplus_open_session(struct ipmi_intf * intf)
+{
+ struct ipmi_v2_payload v2_payload;
+ struct ipmi_session * session = intf->session;
+ uint8_t * msg;
+ struct ipmi_rs * rsp;
+ /* 0 = success, 1 = error, 2 = timeout */
+ int rc = 0;
+
+
+ /*
+ * Build an Open Session Request Payload
+ */
+ msg = (uint8_t*)malloc(IPMI_OPEN_SESSION_REQUEST_SIZE);
+ if (msg == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return 1;
+ }
+
+ memset(msg, 0, IPMI_OPEN_SESSION_REQUEST_SIZE);
+
+ msg[0] = 0; /* Message tag */
+ if (ipmi_oem_active(intf, "intelplus") || session->privlvl != IPMI_SESSION_PRIV_ADMIN)
+ msg[1] = session->privlvl;
+ else
+ msg[1] = 0; /* Give us highest privlg level based on supported algorithms */
+ msg[2] = 0; /* reserved */
+ msg[3] = 0; /* reserved */
+
+ /* Choose our session ID for easy recognition in the packet dump */
+ session->v2_data.console_id = 0xA0A2A3A4;
+ msg[4] = session->v2_data.console_id & 0xff;
+ msg[5] = (session->v2_data.console_id >> 8) & 0xff;
+ msg[6] = (session->v2_data.console_id >> 16) & 0xff;
+ msg[7] = (session->v2_data.console_id >> 24) & 0xff;
+
+
+ if (lanplus_get_requested_ciphers(session->cipher_suite_id,
+ &(session->v2_data.requested_auth_alg),
+ &(session->v2_data.requested_integrity_alg),
+ &(session->v2_data.requested_crypt_alg)))
+ {
+ lprintf(LOG_WARNING, "Unsupported cipher suite ID : %d\n",
+ session->cipher_suite_id);
+ free(msg);
+ msg = NULL;
+ return 1;
+ }
+
+
+ /*
+ * Authentication payload
+ */
+ msg[8] = 0; /* specifies authentication payload */
+ msg[9] = 0; /* reserved */
+ msg[10] = 0; /* reserved */
+ msg[11] = 8; /* payload length */
+ msg[12] = session->v2_data.requested_auth_alg;
+ msg[13] = 0; /* reserved */
+ msg[14] = 0; /* reserved */
+ msg[15] = 0; /* reserved */
+
+ /*
+ * Integrity payload
+ */
+ msg[16] = 1; /* specifies integrity payload */
+ msg[17] = 0; /* reserved */
+ msg[18] = 0; /* reserved */
+ msg[19] = 8; /* payload length */
+ msg[20] = session->v2_data.requested_integrity_alg;
+ msg[21] = 0; /* reserved */
+ msg[22] = 0; /* reserved */
+ msg[23] = 0; /* reserved */
+
+ /*
+ * Confidentiality/Encryption payload
+ */
+ msg[24] = 2; /* specifies confidentiality payload */
+ msg[25] = 0; /* reserved */
+ msg[26] = 0; /* reserved */
+ msg[27] = 8; /* payload length */
+ msg[28] = session->v2_data.requested_crypt_alg;
+ msg[29] = 0; /* reserved */
+ msg[30] = 0; /* reserved */
+ msg[31] = 0; /* reserved */
+
+
+ v2_payload.payload_type = IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST;
+ v2_payload.payload_length = IPMI_OPEN_SESSION_REQUEST_SIZE;
+ v2_payload.payload.open_session_request.request = msg;
+
+ rsp = ipmi_lanplus_send_payload(intf, &v2_payload);
+
+ free(msg);
+ msg = NULL;
+ if (rsp == NULL ) {
+ lprintf(LOG_DEBUG, "Timeout in open session response message.");
+ return 2;
+ }
+ if (verbose)
+ lanplus_dump_open_session_response(rsp);
+
+ if (rsp->payload.open_session_response.rakp_return_code !=
+ IPMI_RAKP_STATUS_NO_ERRORS)
+ {
+ lprintf(LOG_WARNING, "Error in open session response message : %s\n",
+ val2str(rsp->payload.open_session_response.rakp_return_code,
+ ipmi_rakp_return_codes));
+ return 1;
+ }
+ else
+ {
+ if (rsp->payload.open_session_response.console_id !=
+ session->v2_data.console_id) {
+ lprintf(LOG_WARNING, "Warning: Console session ID is not "
+ "what we requested");
+ }
+
+ session->v2_data.max_priv_level =
+ rsp->payload.open_session_response.max_priv_level;
+ session->v2_data.bmc_id =
+ rsp->payload.open_session_response.bmc_id;
+ session->v2_data.auth_alg =
+ rsp->payload.open_session_response.auth_alg;
+ session->v2_data.integrity_alg =
+ rsp->payload.open_session_response.integrity_alg;
+ session->v2_data.crypt_alg =
+ rsp->payload.open_session_response.crypt_alg;
+ session->v2_data.session_state =
+ LANPLUS_STATE_OPEN_SESSION_RECEIEVED;
+
+
+ /*
+ * Verify that we have agreed on a cipher suite
+ */
+ if (rsp->payload.open_session_response.auth_alg !=
+ session->v2_data.requested_auth_alg)
+ {
+ lprintf(LOG_WARNING, "Authentication algorithm 0x%02x is "
+ "not what we requested 0x%02x\n",
+ rsp->payload.open_session_response.auth_alg,
+ session->v2_data.requested_auth_alg);
+ rc = 1;
+ }
+ else if (rsp->payload.open_session_response.integrity_alg !=
+ session->v2_data.requested_integrity_alg)
+ {
+ lprintf(LOG_WARNING, "Integrity algorithm 0x%02x is "
+ "not what we requested 0x%02x\n",
+ rsp->payload.open_session_response.integrity_alg,
+ session->v2_data.requested_integrity_alg);
+ rc = 1;
+ }
+ else if (rsp->payload.open_session_response.crypt_alg !=
+ session->v2_data.requested_crypt_alg)
+ {
+ lprintf(LOG_WARNING, "Encryption algorithm 0x%02x is "
+ "not what we requested 0x%02x\n",
+ rsp->payload.open_session_response.crypt_alg,
+ session->v2_data.requested_crypt_alg);
+ rc = 1;
+ }
+
+ }
+
+ return rc;
+}
+
+
+
+/*
+ * ipmi_lanplus_rakp1
+ *
+ * Build and send the RAKP 1 message as part of the IPMI v2 / RMCP+ session
+ * negotiation protocol. We also read and validate the RAKP 2 message received
+ * from the BMC, here. See section 13.20 of the IPMI v2 specification for
+ * details.
+ *
+ * returns 0 on success
+ * 1 on failure
+ *
+ * Note that failure is only indicated if we have an internal error of
+ * some kind. If we actually get a RAKP 2 message in response to our
+ * RAKP 1 message, any errors will be stored in
+ * session->v2_data.rakp2_return_code and sent to the BMC in the RAKP
+ * 3 message.
+ */
+static int
+ipmi_lanplus_rakp1(struct ipmi_intf * intf)
+{
+ struct ipmi_v2_payload v2_payload;
+ struct ipmi_session * session = intf->session;
+ uint8_t * msg;
+ struct ipmi_rs * rsp;
+ int rc = 0; /* 0 = success, 1 = error, 2 = timeout */
+
+ /*
+ * Build a RAKP 1 message
+ */
+ msg = (uint8_t*)malloc(IPMI_RAKP1_MESSAGE_SIZE);
+ if (msg == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return 1;
+ }
+ memset(msg, 0, IPMI_RAKP1_MESSAGE_SIZE);
+
+
+ msg[0] = 0; /* Message tag */
+
+ msg[1] = 0; /* reserved */
+ msg[2] = 0; /* reserved */
+ msg[3] = 0; /* reserved */
+
+ /* BMC session ID */
+ msg[4] = session->v2_data.bmc_id & 0xff;
+ msg[5] = (session->v2_data.bmc_id >> 8) & 0xff;
+ msg[6] = (session->v2_data.bmc_id >> 16) & 0xff;
+ msg[7] = (session->v2_data.bmc_id >> 24) & 0xff;
+
+
+ /* We need a 16 byte random number */
+ if (lanplus_rand(session->v2_data.console_rand, 16))
+ {
+ // ERROR;
+ lprintf(LOG_ERR, "ERROR generating random number "
+ "in ipmi_lanplus_rakp1");
+ free(msg);
+ msg = NULL;
+ return 1;
+ }
+ memcpy(msg + 8, session->v2_data.console_rand, 16);
+ #if WORDS_BIGENDIAN
+ lanplus_swap(msg + 8, 16);
+ #endif
+
+ if (verbose > 1)
+ printbuf(session->v2_data.console_rand, 16,
+ ">> Console generated random number");
+
+
+ /*
+ * Requested maximum privilege level.
+ */
+ msg[24] = session->privlvl | session->v2_data.lookupbit;
+ session->v2_data.requested_role = msg[24];
+ msg[25] = 0; /* reserved */
+ msg[26] = 0; /* reserved */
+
+
+ /* Username specification */
+ msg[27] = strlen((const char *)session->username);
+ if (msg[27] > IPMI_MAX_USER_NAME_LENGTH)
+ {
+ lprintf(LOG_ERR, "ERROR: user name too long. "
+ "(Exceeds %d characters)",
+ IPMI_MAX_USER_NAME_LENGTH);
+ free(msg);
+ msg = NULL;
+ return 1;
+ }
+ memcpy(msg + 28, session->username, msg[27]);
+
+ v2_payload.payload_type = IPMI_PAYLOAD_TYPE_RAKP_1;
+ v2_payload.payload_length =
+ IPMI_RAKP1_MESSAGE_SIZE - (16 - msg[27]);
+ v2_payload.payload.rakp_1_message.message = msg;
+
+ rsp = ipmi_lanplus_send_payload(intf, &v2_payload);
+
+ free(msg);
+ msg = NULL;
+
+ if (rsp == NULL)
+ {
+ lprintf(LOG_WARNING, "> Error: no response from RAKP 1 message");
+ return 2;
+ }
+
+ session->v2_data.session_state = LANPLUS_STATE_RAKP_2_RECEIVED;
+
+ if (verbose)
+ lanplus_dump_rakp2_message(rsp, session->v2_data.auth_alg);
+
+
+
+ if (rsp->payload.rakp2_message.rakp_return_code != IPMI_RAKP_STATUS_NO_ERRORS)
+ {
+ lprintf(LOG_INFO, "RAKP 2 message indicates an error : %s",
+ val2str(rsp->payload.rakp2_message.rakp_return_code,
+ ipmi_rakp_return_codes));
+ rc = 1;
+ }
+
+ else
+ {
+ memcpy(session->v2_data.bmc_rand, rsp->payload.rakp2_message.bmc_rand, 16);
+ memcpy(session->v2_data.bmc_guid, rsp->payload.rakp2_message.bmc_guid, 16);
+
+ if (verbose > 2)
+ printbuf(session->v2_data.bmc_rand, 16, "bmc_rand");
+
+ /*
+ * It is at this point that we have to decode the random number and determine
+ * whether the BMC has authenticated.
+ */
+ if (! lanplus_rakp2_hmac_matches(session,
+ rsp->payload.rakp2_message.key_exchange_auth_code,
+ intf))
+ {
+ /* Error */
+ lprintf(LOG_INFO, "> RAKP 2 HMAC is invalid");
+ session->v2_data.rakp2_return_code = IPMI_RAKP_STATUS_INVALID_INTEGRITY_CHECK_VALUE;
+ rc = 1;
+ }
+ else
+ {
+ /* Success */
+ session->v2_data.rakp2_return_code = IPMI_RAKP_STATUS_NO_ERRORS;
+ }
+ }
+
+ return rc;
+}
+
+
+
+/*
+ * ipmi_lanplus_rakp3
+ *
+ * Build and send the RAKP 3 message as part of the IPMI v2 / RMCP+ session
+ * negotiation protocol. We also read and validate the RAKP 4 message received
+ * from the BMC, here. See section 13.20 of the IPMI v2 specification for
+ * details.
+ *
+ * If the RAKP 2 return code is not IPMI_RAKP_STATUS_NO_ERRORS, we will
+ * exit with an error code immediately after sendint the RAKP 3 message.
+ *
+ * param intf is the intf that holds all the state we are concerned with
+ *
+ * returns 0 on success
+ * 1 on failure
+ */
+static int
+ipmi_lanplus_rakp3(struct ipmi_intf * intf)
+{
+ struct ipmi_v2_payload v2_payload;
+ struct ipmi_session * session = intf->session;
+ uint8_t * msg;
+ struct ipmi_rs * rsp;
+
+ assert(session->v2_data.session_state == LANPLUS_STATE_RAKP_2_RECEIVED);
+
+ /*
+ * Build a RAKP 3 message
+ */
+ msg = (uint8_t*)malloc(IPMI_RAKP3_MESSAGE_MAX_SIZE);
+ if (msg == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return 1;
+ }
+ memset(msg, 0, IPMI_RAKP3_MESSAGE_MAX_SIZE);
+
+
+ msg[0] = 0; /* Message tag */
+ msg[1] = session->v2_data.rakp2_return_code;
+
+ msg[2] = 0; /* reserved */
+ msg[3] = 0; /* reserved */
+
+ /* BMC session ID */
+ msg[4] = session->v2_data.bmc_id & 0xff;
+ msg[5] = (session->v2_data.bmc_id >> 8) & 0xff;
+ msg[6] = (session->v2_data.bmc_id >> 16) & 0xff;
+ msg[7] = (session->v2_data.bmc_id >> 24) & 0xff;
+
+ v2_payload.payload_type = IPMI_PAYLOAD_TYPE_RAKP_3;
+ v2_payload.payload_length = 8;
+ v2_payload.payload.rakp_3_message.message = msg;
+
+ /*
+ * If the rakp2 return code indicates and error, we don't have to
+ * generate an authcode or session integrity key. In that case, we
+ * are simply sending a RAKP 3 message to indicate to the BMC that the
+ * RAKP 2 message caused an error.
+ */
+ if (session->v2_data.rakp2_return_code == IPMI_RAKP_STATUS_NO_ERRORS)
+ {
+ uint32_t auth_length;
+
+ if (lanplus_generate_rakp3_authcode(msg + 8, session, &auth_length, intf))
+ {
+ /* Error */
+ lprintf(LOG_INFO, "> Error generating RAKP 3 authcode");
+ free(msg);
+ msg = NULL;
+ return 1;
+ }
+ else
+ {
+ /* Success */
+ v2_payload.payload_length += auth_length;
+ }
+
+ /* Generate our Session Integrity Key, K1, and K2 */
+ if (lanplus_generate_sik(session, intf))
+ {
+ /* Error */
+ lprintf(LOG_INFO, "> Error generating session integrity key");
+ free(msg);
+ msg = NULL;
+ return 1;
+ }
+ else if (lanplus_generate_k1(session))
+ {
+ /* Error */
+ lprintf(LOG_INFO, "> Error generating K1 key");
+ free(msg);
+ msg = NULL;
+ return 1;
+ }
+ else if (lanplus_generate_k2(session))
+ {
+ /* Error */
+ lprintf(LOG_INFO, "> Error generating K1 key");
+ free(msg);
+ msg = NULL;
+ return 1;
+ }
+ }
+
+
+ rsp = ipmi_lanplus_send_payload(intf, &v2_payload);
+
+ free(msg);
+ msg = NULL;
+
+ if (session->v2_data.rakp2_return_code != IPMI_RAKP_STATUS_NO_ERRORS)
+ {
+ /*
+ * If the previous RAKP 2 message received was deemed erroneous,
+ * we have nothing else to do here. We only sent the RAKP 3 message
+ * to indicate to the BMC that the RAKP 2 message failed.
+ */
+ return 1;
+ }
+ else if (rsp == NULL)
+ {
+ lprintf(LOG_WARNING, "> Error: no response from RAKP 3 message");
+ return 2;
+ }
+
+
+ /*
+ * We have a RAKP 4 message to chew on.
+ */
+ if (verbose)
+ lanplus_dump_rakp4_message(rsp, session->v2_data.auth_alg);
+
+
+ if (rsp->payload.open_session_response.rakp_return_code != IPMI_RAKP_STATUS_NO_ERRORS)
+ {
+ lprintf(LOG_INFO, "RAKP 4 message indicates an error : %s",
+ val2str(rsp->payload.rakp4_message.rakp_return_code,
+ ipmi_rakp_return_codes));
+ return 1;
+ }
+
+ else
+ {
+ /* Validate the authcode */
+ if (lanplus_rakp4_hmac_matches(session,
+ rsp->payload.rakp4_message.integrity_check_value,
+ intf))
+ {
+ /* Success */
+ session->v2_data.session_state = LANPLUS_STATE_ACTIVE;
+ }
+ else
+ {
+ /* Error */
+ lprintf(LOG_INFO, "> RAKP 4 message has invalid integrity check value");
+ return 1;
+ }
+ }
+
+ intf->abort = 0;
+ return 0;
+}
+
+
+
+/**
+ * ipmi_lan_close
+ */
+void
+ipmi_lanplus_close(struct ipmi_intf * intf)
+{
+ if (!intf->abort)
+ ipmi_close_session_cmd(intf);
+
+ if (intf->fd >= 0)
+ close(intf->fd);
+
+ ipmi_req_clear_entries();
+
+ if (intf->session) {
+ free(intf->session);
+ intf->session = NULL;
+ }
+
+ intf->session = NULL;
+ intf->opened = 0;
+ intf->manufacturer_id = IPMI_OEM_UNKNOWN;
+ intf = NULL;
+}
+
+
+
+static int
+ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf)
+{
+ struct ipmi_rs * rsp;
+ struct ipmi_rq req;
+ uint8_t backupBridgePossible;
+ uint8_t privlvl = intf->session->privlvl;
+
+ if (privlvl <= IPMI_SESSION_PRIV_USER)
+ return 0; /* no need to set higher */
+
+ backupBridgePossible = bridgePossible;
+
+ bridgePossible = 0;
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_APP;
+ req.msg.cmd = 0x3b;
+ req.msg.data = &privlvl;
+ req.msg.data_len = 1;
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL) {
+ lprintf(LOG_ERR, "Set Session Privilege Level to %s failed",
+ val2str(privlvl, ipmi_privlvl_vals));
+ bridgePossible = backupBridgePossible;
+ return -1;
+ }
+ if (verbose > 2)
+ printbuf(rsp->data, rsp->data_len, "set_session_privlvl");
+
+ if (rsp->ccode > 0) {
+ lprintf(LOG_ERR, "Set Session Privilege Level to %s failed: %s",
+ val2str(privlvl, ipmi_privlvl_vals),
+ val2str(rsp->ccode, completion_code_vals));
+ bridgePossible = backupBridgePossible;
+ return -1;
+ }
+
+ lprintf(LOG_DEBUG, "Set Session Privilege Level to %s\n",
+ val2str(rsp->data[0], ipmi_privlvl_vals));
+
+ bridgePossible = backupBridgePossible;
+
+ return 0;
+}
+
+/**
+ * ipmi_lanplus_open
+ */
+int
+ipmi_lanplus_open(struct ipmi_intf * intf)
+{
+ int rc;
+ int retry;
+ struct get_channel_auth_cap_rsp auth_cap;
+ struct ipmi_session *session;
+
+ if (!intf || !intf->session)
+ return -1;
+ session = intf->session;
+
+
+ if (!session->port)
+ session->port = IPMI_LANPLUS_PORT;
+ if (!session->privlvl)
+ session->privlvl = IPMI_SESSION_PRIV_ADMIN;
+ if (!session->timeout)
+ session->timeout = IPMI_LAN_TIMEOUT;
+ if (!session->retry)
+ session->retry = IPMI_LAN_RETRY;
+
+ if (session->hostname == NULL || strlen((const char *)session->hostname) == 0) {
+ lprintf(LOG_ERR, "No hostname specified!");
+ return -1;
+ }
+
+ intf->abort = 1;
+
+
+ /* Setup our lanplus session state */
+ session->v2_data.auth_alg = IPMI_AUTH_RAKP_NONE;
+ session->v2_data.crypt_alg = IPMI_CRYPT_NONE;
+ session->v2_data.console_id = 0x00;
+ session->v2_data.bmc_id = 0x00;
+ session->sol_data.sequence_number = 1;
+ //session->sol_data.last_received_sequence_number = 0;
+ //session->sol_data.last_received_byte_count = 0;
+ memset(session->v2_data.sik, 0, IPMI_SIK_BUFFER_SIZE);
+
+ /* Kg is set in ipmi_intf */
+ //memset(session->v2_data.kg, 0, IPMI_KG_BUFFER_SIZE);
+
+ if (ipmi_intf_socket_connect (intf) == -1) {
+ lprintf(LOG_ERR, "Could not open socket!");
+ return -1;
+ }
+
+ if (intf->fd < 0) {
+ lperror(LOG_ERR, "Connect to %s failed",
+ session->hostname);
+ intf->close(intf);
+ return -1;
+ }
+
+ intf->opened = 1;
+
+ /*
+ *
+ * Make sure the BMC supports IPMI v2 / RMCP+
+ */
+ if (!ipmi_oem_active(intf, "i82571spt") &&
+ ipmi_get_auth_capabilities_cmd(intf, &auth_cap)) {
+ lprintf(LOG_INFO, "Error issuing Get Channel "
+ "Authentication Capabilies request");
+ goto fail;
+ }
+
+ if (!ipmi_oem_active(intf, "i82571spt") && ! auth_cap.v20_data_available)
+ {
+ lprintf(LOG_INFO, "This BMC does not support IPMI v2 / RMCP+");
+ goto fail;
+ }
+
+ /*
+ * If the open/rakp1/rakp3 sequence encounters a timeout, the whole sequence
+ * needs to restart. The individual messages are not individually retryable,
+ * as the session state is advancing.
+ */
+ for (retry = 0; retry < IPMI_LAN_RETRY; retry++) {
+ session->v2_data.session_state = LANPLUS_STATE_PRESESSION;
+ /*
+ * Open session
+ */
+ if ((rc = ipmi_lanplus_open_session(intf)) == 1) {
+ intf->close(intf);
+ goto fail;
+ }
+ if (rc == 2) {
+ lprintf(LOG_DEBUG, "Retry lanplus open session, %d", retry);
+ continue;
+ }
+ /*
+ * RAKP 1
+ */
+ if ((rc = ipmi_lanplus_rakp1(intf)) == 1) {
+ intf->close(intf);
+ goto fail;
+ }
+ if (rc == 2) {
+ lprintf(LOG_DEBUG, "Retry lanplus rakp1, %d", retry);
+ continue;
+ }
+ /*
+ * RAKP 3
+ */
+ if ((rc = ipmi_lanplus_rakp3(intf)) == 1) {
+ intf->close(intf);
+ goto fail;
+ }
+ if (rc == 0) break;
+ lprintf(LOG_DEBUG,"Retry lanplus rakp3, %d", retry);
+ }
+
+ lprintf(LOG_DEBUG, "IPMIv2 / RMCP+ SESSION OPENED SUCCESSFULLY\n");
+
+ if (!ipmi_oem_active(intf, "i82571spt")) {
+ rc = ipmi_set_session_privlvl_cmd(intf);
+ if (rc < 0) {
+ intf->close(intf);
+ goto fail;
+ }
+ }
+ intf->manufacturer_id = ipmi_get_oem(intf);
+ bridgePossible = 1;
+
+ /* automatically detect interface request and response sizes */
+ hpm2_detect_max_payload_size(intf);
+
+ return intf->fd;
+
+ fail:
+ lprintf(LOG_ERR, "Error: Unable to establish IPMI v2 / RMCP+ session");
+ intf->opened = 0;
+ return -1;
+}
+
+
+
+void test_crypt1(void)
+{
+ uint8_t key[] =
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
+ 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14};
+
+ uint16_t bytes_encrypted;
+ uint16_t bytes_decrypted;
+ uint8_t decrypt_buffer[1000];
+ uint8_t encrypt_buffer[1000];
+
+ uint8_t data[] =
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x11, 0x12};
+
+ printbuf(data, sizeof(data), "original data");
+
+ if (lanplus_encrypt_payload(IPMI_CRYPT_AES_CBC_128,
+ key,
+ data,
+ sizeof(data),
+ encrypt_buffer,
+ &bytes_encrypted))
+ {
+ lprintf(LOG_ERR, "Encrypt test failed");
+ assert(0);
+ }
+ printbuf(encrypt_buffer, bytes_encrypted, "encrypted payload");
+
+
+ if (lanplus_decrypt_payload(IPMI_CRYPT_AES_CBC_128,
+ key,
+ encrypt_buffer,
+ bytes_encrypted,
+ decrypt_buffer,
+ &bytes_decrypted))
+ {
+ lprintf(LOG_ERR, "Decrypt test failed\n");
+ assert(0);
+ }
+ printbuf(decrypt_buffer, bytes_decrypted, "decrypted payload");
+
+ lprintf(LOG_DEBUG, "\nDone testing the encrypt/decyrpt methods!\n");
+ exit(0);
+}
+
+
+
+void test_crypt2(void)
+{
+ uint8_t key[] =
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
+ 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14};
+ uint8_t iv[] =
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
+ 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14};
+ uint8_t data[8] = "12345678";
+
+ uint8_t encrypt_buffer[1000];
+ uint8_t decrypt_buffer[1000];
+ uint32_t bytes_encrypted;
+ uint32_t bytes_decrypted;
+
+ printbuf((const uint8_t *)data, strlen((const char *)data), "input data");
+
+ lanplus_encrypt_aes_cbc_128(iv,
+ key,
+ data,
+ strlen((const char *)data),
+ encrypt_buffer,
+ &bytes_encrypted);
+ printbuf((const uint8_t *)encrypt_buffer, bytes_encrypted, "encrypt_buffer");
+
+ lanplus_decrypt_aes_cbc_128(iv,
+ key,
+ encrypt_buffer,
+ bytes_encrypted,
+ decrypt_buffer,
+ &bytes_decrypted);
+ printbuf((const uint8_t *)decrypt_buffer, bytes_decrypted, "decrypt_buffer");
+
+ lprintf(LOG_INFO, "\nDone testing the encrypt/decyrpt methods!\n");
+ exit(0);
+}
+
+
+/**
+ * send a get device id command to keep session active
+ */
+static int
+ipmi_lanplus_keepalive(struct ipmi_intf * intf)
+{
+ struct ipmi_rs * rsp;
+ struct ipmi_rq req = { msg: {
+ netfn: IPMI_NETFN_APP,
+ cmd: 1,
+ }};
+
+ if (!intf->opened)
+ return 0;
+
+ rsp = intf->sendrecv(intf, &req);
+ while (rsp != NULL && is_sol_packet(rsp)) {
+ /* rsp was SOL data instead of our answer */
+ /* since it didn't go through the sol recv, do sol recv stuff here */
+ ack_sol_packet(intf, rsp);
+ check_sol_packet_for_new_data(intf, rsp);
+ if (rsp->data_len)
+ intf->session->sol_data.sol_input_handler(rsp);
+ rsp = ipmi_lan_poll_recv(intf);
+ if (rsp == NULL) /* the get device id answer never got back, but retry mechanism was bypassed by SOL data */
+ return 0; /* so get device id command never returned, the connection is still alive */
+ }
+
+ if (rsp == NULL)
+ return -1;
+ if (rsp->ccode > 0)
+ return -1;
+
+ return 0;
+}
+
+
+/**
+ * ipmi_lanplus_setup
+ */
+static int ipmi_lanplus_setup(struct ipmi_intf * intf)
+{
+ //test_crypt1();
+ assert("ipmi_lanplus_setup");
+
+ if (lanplus_seed_prng(16))
+ return -1;
+
+ intf->session = malloc(sizeof(struct ipmi_session));
+ if (intf->session == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return -1;
+ }
+ memset(intf->session, 0, sizeof(struct ipmi_session));
+
+ /* setup default LAN maximum request and response sizes */
+ intf->max_request_data_size = IPMI_LAN_MAX_REQUEST_SIZE;
+ intf->max_response_data_size = IPMI_LAN_MAX_RESPONSE_SIZE;
+
+ return 0;
+}
+
+static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size)
+{
+ if (intf->session->cipher_suite_id == 3) {
+ /*
+ * encrypted payload can only be multiple of 16 bytes
+ */
+ size &= ~15;
+
+ /*
+ * decrement payload size on confidentiality header size
+ * plus minimal confidentiality trailer size
+ */
+ size -= (16 + 1);
+ }
+
+ intf->max_request_data_size = size;
+}
+
+static void ipmi_lanp_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size)
+{
+ if (intf->session->cipher_suite_id == 3) {
+ /*
+ * encrypted payload can only be multiple of 16 bytes
+ */
+ size &= ~15;
+
+ /*
+ * decrement payload size on confidentiality header size
+ * plus minimal confidentiality trailer size
+ */
+ size -= (16 + 1);
+ }
+
+ intf->max_response_data_size = size;
+}
diff --git a/src/plugins/lanplus/lanplus.h b/src/plugins/lanplus/lanplus.h
new file mode 100644
index 0000000..4b6ae1e
--- /dev/null
+++ b/src/plugins/lanplus/lanplus.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IPMI_LANPLUS_H
+#define IPMI_LANPLUS_H
+
+#include <ipmitool/ipmi.h>
+
+#define IPMI_LANPLUS_PORT 0x26f
+
+/*
+ * RAKP return codes. These values come from table 13-15 of the IPMI v2
+ * specification.
+ */
+#define IPMI_RAKP_STATUS_NO_ERRORS 0x00
+#define IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_SESSION 0x01
+#define IPMI_RAKP_STATUS_INVALID_SESSION_ID 0x02
+#define IPMI_RAKP_STATUS_INVALID_PAYLOAD_TYPE 0x03
+#define IPMI_RAKP_STATUS_INVALID_AUTHENTICATION_ALGORITHM 0x04
+#define IPMI_RAKP_STATUS_INVALID_INTEGRITTY_ALGORITHM 0x05
+#define IPMI_RAKP_STATUS_NO_MATCHING_AUTHENTICATION_PAYLOAD 0x06
+#define IPMI_RAKP_STATUS_NO_MATCHING_INTEGRITY_PAYLOAD 0x07
+#define IPMI_RAKP_STATUS_INACTIVE_SESSION_ID 0x08
+#define IPMI_RAKP_STATUS_INVALID_ROLE 0x09
+#define IPMI_RAKP_STATUS_UNAUTHORIZED_ROLE_REQUESTED 0x0A
+#define IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_ROLE 0x0B
+#define IPMI_RAKP_STATUS_INVALID_NAME_LENGTH 0x0C
+#define IPMI_RAKP_STATUS_UNAUTHORIZED_NAME 0x0D
+#define IPMI_RAKP_STATUS_UNAUTHORIZED_GUID 0x0E
+#define IPMI_RAKP_STATUS_INVALID_INTEGRITY_CHECK_VALUE 0x0F
+#define IPMI_RAKP_STATUS_INVALID_CONFIDENTIALITY_ALGORITHM 0x10
+#define IPMI_RAKP_STATUS_NO_CIPHER_SUITE_MATCH 0x11
+#define IPMI_RAKP_STATUS_ILLEGAL_PARAMTER 0x12
+
+
+#define IPMI_LAN_CHANNEL_1 0x07
+#define IPMI_LAN_CHANNEL_2 0x06
+#define IPMI_LAN_CHANNEL_E 0x0e
+
+#define IPMI_LAN_TIMEOUT 1
+#define IPMI_LAN_RETRY 4
+
+#define IPMI_PRIV_CALLBACK 1
+#define IPMI_PRIV_USER 2
+#define IPMI_PRIV_OPERATOR 3
+#define IPMI_PRIV_ADMIN 4
+#define IPMI_PRIV_OEM 5
+
+
+#define IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE 0x10
+
+
+/* Session message offsets, from table 13-8 of the v2 specification */
+#define IPMI_LANPLUS_OFFSET_AUTHTYPE 0x04
+#define IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE 0x05
+#define IPMI_LANPLUS_OFFSET_SESSION_ID 0x06
+#define IPMI_LANPLUS_OFFSET_SEQUENCE_NUM 0x0A
+#define IPMI_LANPLUS_OFFSET_PAYLOAD_SIZE 0x0E
+#define IPMI_LANPLUS_OFFSET_PAYLOAD 0x10
+
+
+#define IPMI_GET_CHANNEL_AUTH_CAP 0x38
+
+/*
+ * TODO: these are wild guesses and should be checked
+ */
+#define IPMI_MAX_CONF_HEADER_SIZE 0x20
+#define IPMI_MAX_PAYLOAD_SIZE 0xFFFF /* Includes confidentiality header/trailer */
+#define IPMI_MAX_CONF_TRAILER_SIZE 0x20
+#define IPMI_MAX_INTEGRITY_PAD_SIZE 0x20
+#define IPMI_MAX_AUTH_CODE_SIZE 0x20
+
+#define IPMI_REQUEST_MESSAGE_SIZE 0x07
+#define IPMI_MAX_MAC_SIZE 0x14 /* The largest mac we ever expect to generate */
+#define IPMI_SHA1_AUTHCODE_SIZE 0x0C
+
+/*
+ *This is accurate, as long as we're only passing 1 auth algorithm,
+ * one integrity algorithm, and 1 encyrption alogrithm
+ */
+#define IPMI_OPEN_SESSION_REQUEST_SIZE 32
+#define IPMI_RAKP1_MESSAGE_SIZE 44
+#define IPMI_RAKP3_MESSAGE_MAX_SIZE 28
+
+#define IPMI_MAX_USER_NAME_LENGTH 16
+
+extern const struct valstr ipmi_privlvl_vals[];
+extern const struct valstr ipmi_authtype_vals[];
+
+extern struct ipmi_intf ipmi_lanplus_intf;
+
+struct ipmi_rs * ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req);
+int ipmi_lanplus_open(struct ipmi_intf * intf);
+void ipmi_lanplus_close(struct ipmi_intf * intf);
+int ipmiv2_lan_ping(struct ipmi_intf * intf);
+
+#endif /*IPMI_LAN_H*/
diff --git a/src/plugins/lanplus/lanplus_crypt.c b/src/plugins/lanplus/lanplus_crypt.c
new file mode 100644
index 0000000..54fd5cb
--- /dev/null
+++ b/src/plugins/lanplus/lanplus_crypt.c
@@ -0,0 +1,934 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <assert.h>
+#include <string.h>
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+#include <ipmitool/bswap.h>
+#include <ipmitool/log.h>
+#include "lanplus.h"
+#include "lanplus_crypt.h"
+#include "lanplus_crypt_impl.h"
+
+
+
+/*
+ * lanplus_rakp2_hmac_matches
+ *
+ * param session holds all the state data that we need to generate the hmac
+ * param hmac is the HMAC sent by the BMC in the RAKP 2 message
+ *
+ * The HMAC was generated [per RFC2404] from :
+ *
+ * SIDm - Remote console session ID
+ * SIDc - BMC session ID
+ * Rm - Remote console random number
+ * Rc - BMC random number
+ * GUIDc - BMC guid
+ * ROLEm - Requested privilege level (entire byte)
+ * ULENGTHm - Username length
+ * <UNAMEm> - Username (absent for null user names)
+ *
+ * generated by using Kuid. I am aware that the subscripts on the values
+ * look backwards, but that's the way they are written in the specification.
+ *
+ * If the authentication algorithm is IPMI_AUTH_RAKP_NONE, we return success.
+ *
+ * return 0 on success (the authcode matches)
+ * 1 on failure (the authcode does not match)
+ */
+int
+lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
+ const uint8_t * bmc_mac, struct ipmi_intf * intf)
+{
+ uint8_t * buffer;
+ int bufferLength, i;
+ uint8_t mac[20];
+ uint32_t macLength;
+
+ uint32_t SIDm_lsbf, SIDc_lsbf;
+
+
+ if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
+ return 1;
+
+ /* We don't yet support other algorithms */
+ assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
+
+
+ bufferLength =
+ 4 + /* SIDm */
+ 4 + /* SIDc */
+ 16 + /* Rm */
+ 16 + /* Rc */
+ 16 + /* GUIDc */
+ 1 + /* ROLEm */
+ 1 + /* ULENGTHm */
+ strlen((const char *)session->username); /* optional */
+
+ buffer = malloc(bufferLength);
+ if (buffer == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return 1;
+ }
+
+ /*
+ * Fill the buffer. I'm assuming that we're using the LSBF representation of the
+ * multibyte numbers in use.
+ */
+
+ /* SIDm */
+ SIDm_lsbf = session->v2_data.console_id;
+ #if WORDS_BIGENDIAN
+ SIDm_lsbf = BSWAP_32(SIDm_lsbf);
+ #endif
+
+ memcpy(buffer, &SIDm_lsbf, 4);
+
+ /* SIDc */
+ SIDc_lsbf = session->v2_data.bmc_id;
+ #if WORDS_BIGENDIAN
+ SIDc_lsbf = BSWAP_32(SIDc_lsbf);
+ #endif
+ memcpy(buffer + 4, &SIDc_lsbf, 4);
+
+ /* Rm */
+ #if WORDS_BIGENDIAN
+ for (i = 0; i < 16; ++i)
+ buffer[8 + i] = session->v2_data.console_rand[16 - 1 - i];
+ #else
+ for (i = 0; i < 16; ++i)
+ buffer[8 + i] = session->v2_data.console_rand[i];
+ #endif
+
+ /* Rc */
+ #if WORDS_BIGENDIAN
+ for (i = 0; i < 16; ++i)
+ buffer[24 + i] = session->v2_data.bmc_rand[16 - 1 - i];
+ #else
+ for (i = 0; i < 16; ++i)
+ buffer[24 + i] = session->v2_data.bmc_rand[i];
+ #endif
+
+ /* GUIDc */
+ #if WORDS_BIGENDIAN
+ for (i = 0; i < 16; ++i)
+ buffer[40 + i] = session->v2_data.bmc_guid[16 - 1 - i];
+ #else
+ for (i = 0; i < 16; ++i)
+ buffer[40 + i] = session->v2_data.bmc_guid[i];
+ #endif
+
+ /* ROLEm */
+ buffer[56] = session->v2_data.requested_role;
+
+ if (ipmi_oem_active(intf, "i82571spt")) {
+ /*
+ * The HMAC calculation code in the Intel 82571 GbE
+ * skips this bit! Looks like a GbE bug, but we need
+ * to work around it here anyway...
+ */
+ buffer[56] &= ~0x10;
+ }
+
+ /* ULENGTHm */
+ buffer[57] = strlen((const char *)session->username);
+
+ /* UserName [optional] */
+ for (i = 0; i < buffer[57]; ++i)
+ buffer[58 + i] = session->username[i];
+
+ if (verbose > 2)
+ {
+ printbuf((const uint8_t *)buffer, bufferLength, ">> rakp2 mac input buffer");
+ printbuf((const uint8_t *)session->authcode, IPMI_AUTHCODE_BUFFER_SIZE, ">> rakp2 mac key");
+ }
+
+ /*
+ * The buffer is complete. Let's hash.
+ */
+ lanplus_HMAC(session->v2_data.auth_alg,
+ session->authcode,
+ IPMI_AUTHCODE_BUFFER_SIZE,
+ buffer,
+ bufferLength,
+ mac,
+ &macLength);
+
+ free(buffer);
+ buffer = NULL;
+
+
+ if (verbose > 2)
+ {
+ printbuf(mac, macLength, ">> rakp2 mac as computed by the remote console");
+ }
+
+ return (memcmp(bmc_mac, mac, macLength) == 0);
+}
+
+
+
+/*
+ * lanplus_rakp4_hmac_matches
+ *
+ * param session holds all the state data that we need to generate the hmac
+ * param hmac is the HMAC sent by the BMC in the RAKP 4 message
+ *
+ * The HMAC was generated [per RFC2404] from :
+ *
+ * Rm - Remote console random number
+ * SIDc - BMC session ID
+ * GUIDc - BMC guid
+ *
+ * generated by using SIK (the session integrity key). I am aware that the
+ * subscripts on the values look backwards, but that's the way they are
+ * written in the specification.
+ *
+ * If the authentication algorithm is IPMI_AUTH_RAKP_NONE, we return success.
+ *
+ * return 1 on success (the authcode matches)
+ * 0 on failure (the authcode does not match)
+ *
+ */
+int
+lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
+ const uint8_t * bmc_mac, struct ipmi_intf * intf)
+{
+ uint8_t * buffer;
+ int bufferLength, i;
+ uint8_t mac[20];
+ uint32_t macLength;
+ uint32_t SIDc_lsbf;
+
+ if (ipmi_oem_active(intf, "intelplus")){
+ /* Intel BMC responds with the integrity Algorithm in RAKP4 */
+ if (session->v2_data.integrity_alg == IPMI_INTEGRITY_NONE)
+ return 1;
+
+ /* We don't yet support other algorithms */
+ assert(session->v2_data.integrity_alg == IPMI_INTEGRITY_HMAC_SHA1_96);
+ } else {
+ if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
+ return 1;
+
+ /* We don't yet support other algorithms */
+ assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
+ }
+
+ bufferLength =
+ 16 + /* Rm */
+ 4 + /* SIDc */
+ 16; /* GUIDc */
+
+ buffer = (uint8_t *)malloc(bufferLength);
+ if (buffer == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return 1;
+ }
+
+ /*
+ * Fill the buffer. I'm assuming that we're using the LSBF representation of the
+ * multibyte numbers in use.
+ */
+
+ /* Rm */
+ #if WORDS_BIGENDIAN
+ for (i = 0; i < 16; ++i)
+ buffer[i] = session->v2_data.console_rand[16 - 1 - i];
+ #else
+ for (i = 0; i < 16; ++i)
+ buffer[i] = session->v2_data.console_rand[i];
+ #endif
+
+
+ /* SIDc */
+ SIDc_lsbf = session->v2_data.bmc_id;
+ #if WORDS_BIGENDIAN
+ SIDc_lsbf = BSWAP_32(SIDc_lsbf);
+ #endif
+ memcpy(buffer + 16, &SIDc_lsbf, 4);
+
+
+ /* GUIDc */
+ #if WORDS_BIGENDIAN
+ for (i = 0; i < 16; ++i)
+ buffer[i + 20] = session->v2_data.bmc_guid[16 - 1 - i];
+ #else
+ for (i = 0; i < 16; ++i)
+ buffer[i + 20] = session->v2_data.bmc_guid[i];
+ #endif
+
+
+ if (verbose > 2)
+ {
+ printbuf((const uint8_t *)buffer, bufferLength, ">> rakp4 mac input buffer");
+ printbuf(session->v2_data.sik, 20l, ">> rakp4 mac key (sik)");
+ }
+
+
+ /*
+ * The buffer is complete. Let's hash.
+ */
+ lanplus_HMAC((ipmi_oem_active(intf, "intelplus"))
+ ? session->v2_data.integrity_alg
+ : session->v2_data.auth_alg ,
+ session->v2_data.sik,
+ IPMI_SIK_BUFFER_SIZE,
+ buffer,
+ bufferLength,
+ mac,
+ &macLength);
+
+ if (verbose > 2)
+ {
+ printbuf(bmc_mac, macLength, ">> rakp4 mac as computed by the BMC");
+ printbuf(mac, macLength, ">> rakp4 mac as computed by the remote console");
+ }
+
+
+
+ free(buffer);
+ buffer = NULL;
+ assert(macLength == 20);
+ return (memcmp(bmc_mac, mac, 12) == 0);
+}
+
+
+
+/*
+ * lanplus_generate_rakp3_auth_code
+ *
+ * This auth code is an HMAC generated with :
+ *
+ * Rc - BMC random number
+ * SIDm - Console session ID
+ * ROLEm - Requested privilege level (entire byte)
+ * ULENGTHm - Username length
+ * <USERNAME> - Usename (absent for null usernames)
+ *
+ * The key used to generated the MAC is Kuid
+ *
+ * I am aware that the subscripts look backwards, but that is the way they are
+ * written in the spec.
+ *
+ * param output_buffer [out] will hold the generated MAC
+ * param session [in] holds all the state data we need to generate the auth code
+ * param mac_length [out] will be set to the length of the auth code
+ *
+ * returns 0 on success
+ * 1 on failure
+ */
+int
+lanplus_generate_rakp3_authcode(uint8_t * output_buffer,
+ const struct ipmi_session * session,
+ uint32_t * mac_length, struct ipmi_intf * intf)
+{
+ int ret = 0;
+ int input_buffer_length, i;
+ uint8_t * input_buffer;
+ uint32_t SIDm_lsbf;
+
+
+ if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
+ {
+ *mac_length = 0;
+ return 0;
+ }
+
+ /* We don't yet support other algorithms */
+ assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
+
+ input_buffer_length =
+ 16 + /* Rc */
+ 4 + /* SIDm */
+ 1 + /* ROLEm */
+ 1 + /* ULENGTHm */
+ strlen((const char *)session->username);
+
+ input_buffer = malloc(input_buffer_length);
+ if (input_buffer == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return 1;
+ }
+
+ /*
+ * Fill the buffer. I'm assuming that we're using the LSBF representation of the
+ * multibyte numbers in use.
+ */
+
+ /* Rc */
+ #if WORDS_BIGENDIAN
+ for (i = 0; i < 16; ++i)
+ input_buffer[i] = session->v2_data.bmc_rand[16 - 1 - i];
+ #else
+ for (i = 0; i < 16; ++i)
+ input_buffer[i] = session->v2_data.bmc_rand[i];
+ #endif
+
+ /* SIDm */
+ SIDm_lsbf = session->v2_data.console_id;
+ #if WORDS_BIGENDIAN
+ SIDm_lsbf = BSWAP_32(SIDm_lsbf);
+ #endif
+ memcpy(input_buffer + 16, &SIDm_lsbf, 4);
+
+ /* ROLEm */
+ if (ipmi_oem_active(intf, "intelplus") || ipmi_oem_active(intf, "i82571spt"))
+ input_buffer[20] = session->privlvl;
+ else
+ input_buffer[20] = session->v2_data.requested_role;
+
+ /* ULENGTHm */
+ input_buffer[21] = strlen((const char *)session->username);
+
+ /* USERNAME */
+ for (i = 0; i < input_buffer[21]; ++i)
+ input_buffer[22 + i] = session->username[i];
+
+ if (verbose > 2)
+ {
+ printbuf((const uint8_t *)input_buffer, input_buffer_length, ">> rakp3 mac input buffer");
+ printbuf((const uint8_t *)session->authcode, IPMI_AUTHCODE_BUFFER_SIZE, ">> rakp3 mac key");
+ }
+
+ lanplus_HMAC(session->v2_data.auth_alg,
+ session->authcode,
+ IPMI_AUTHCODE_BUFFER_SIZE,
+ input_buffer,
+ input_buffer_length,
+ output_buffer,
+ mac_length);
+
+ if (verbose > 2)
+ printbuf((const uint8_t *)output_buffer, *mac_length, "generated rakp3 mac");
+
+
+ free(input_buffer);
+ input_buffer = NULL;
+
+ return ret;
+}
+
+
+
+/*
+ * lanplus_generate_sik
+ *
+ * Generate the session integrity key (SIK) used for integrity checking
+ * during the IPMI v2 / RMCP+ session
+ *
+ * This session integrity key is a HMAC generated with :
+ *
+ * Rm - Console generated random number
+ * Rc - BMC generated random number
+ * ROLEm - Requested privilege level (entire byte)
+ * ULENGTHm - Username length
+ * <USERNAME> - Usename (absent for null usernames)
+ *
+ * The key used to generated the SIK is Kg if Kg is not null (two-key logins are
+ * enabled). Otherwise Kuid (the user authcode) is used as the key to genereate
+ * the SIK.
+ *
+ * I am aware that the subscripts look backwards, but that is the way they are
+ * written in the spec.
+ *
+ * param session [in/out] contains our input and output fields.
+ *
+ * returns 0 on success
+ * 1 on failure
+ */
+int
+lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf)
+{
+ uint8_t * input_buffer;
+ int input_buffer_length, i;
+ uint8_t * input_key;
+ uint32_t mac_length;
+
+
+ memset(session->v2_data.sik, 0, IPMI_SIK_BUFFER_SIZE);
+
+ if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
+ return 0;
+
+ /* We don't yet support other algorithms */
+ assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
+
+ input_buffer_length =
+ 16 + /* Rm */
+ 16 + /* Rc */
+ 1 + /* ROLEm */
+ 1 + /* ULENGTHm */
+ strlen((const char *)session->username);
+
+ input_buffer = malloc(input_buffer_length);
+ if (input_buffer == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return 1;
+ }
+
+ /*
+ * Fill the buffer. I'm assuming that we're using the LSBF representation of the
+ * multibyte numbers in use.
+ */
+
+ /* Rm */
+ #if WORDS_BIGENDIAN
+ for (i = 0; i < 16; ++i)
+ input_buffer[i] = session->v2_data.console_rand[16 - 1 - i];
+ #else
+ for (i = 0; i < 16; ++i)
+ input_buffer[i] = session->v2_data.console_rand[i];
+ #endif
+
+
+ /* Rc */
+ #if WORDS_BIGENDIAN
+ for (i = 0; i < 16; ++i)
+ input_buffer[16 + i] = session->v2_data.bmc_rand[16 - 1 - i];
+ #else
+ for (i = 0; i < 16; ++i)
+ input_buffer[16 + i] = session->v2_data.bmc_rand[i];
+ #endif
+
+ /* ROLEm */
+ input_buffer[32] = session->v2_data.requested_role;
+
+ if (ipmi_oem_active(intf, "i82571spt")) {
+ /*
+ * The HMAC calculation code in the Intel 82571 GbE
+ * skips this bit! Looks like a GbE bug, but we need
+ * to work around it here anyway...
+ */
+ input_buffer[32] &= ~0x10;
+ }
+
+ /* ULENGTHm */
+ input_buffer[33] = strlen((const char *)session->username);
+
+ /* USERNAME */
+ for (i = 0; i < input_buffer[33]; ++i)
+ input_buffer[34 + i] = session->username[i];
+
+ if (session->v2_data.kg[0])
+ {
+ /* We will be hashing with Kg */
+ /*
+ * Section 13.31 of the IPMI v2 spec describes the SIK creation
+ * using Kg. It specifies that Kg should not be truncated.
+ * Kg is set in ipmi_intf.
+ */
+ input_key = session->v2_data.kg;
+ }
+ else
+ {
+ /* We will be hashing with Kuid */
+ input_key = session->authcode;
+ }
+
+
+ if (verbose >= 2)
+ printbuf((const uint8_t *)input_buffer, input_buffer_length, "session integrity key input");
+
+ lanplus_HMAC(session->v2_data.auth_alg,
+ input_key,
+ IPMI_AUTHCODE_BUFFER_SIZE,
+ input_buffer,
+ input_buffer_length,
+ session->v2_data.sik,
+ &mac_length);
+
+ free(input_buffer);
+ input_buffer = NULL;
+ assert(mac_length == 20);
+
+ /*
+ * The key MAC generated is 20 bytes, but we will only be using the first
+ * 12 for SHA1 96
+ */
+ if (verbose >= 2)
+ printbuf(session->v2_data.sik, 20, "Generated session integrity key");
+
+ return 0;
+}
+
+
+
+/*
+ * lanplus_generate_k1
+ *
+ * Generate K1, the key presumably used to generate integrity authcodes
+ *
+ * We use the authentication algorithm to generated the HMAC, using
+ * the session integrity key (SIK) as our key.
+ *
+ * param session [in/out].
+ *
+ * returns 0 on success
+ * 1 on failure
+ */
+int
+lanplus_generate_k1(struct ipmi_session * session)
+{
+ uint32_t mac_length;
+
+ uint8_t CONST_1[] =
+ {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+
+ if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
+ memcpy(session->v2_data.k1, CONST_1, 20);
+ else
+ {
+ lanplus_HMAC(session->v2_data.auth_alg,
+ session->v2_data.sik,
+ IPMI_SIK_BUFFER_SIZE, /* SIK length */
+ CONST_1,
+ 20,
+ session->v2_data.k1,
+ &mac_length);
+ assert(mac_length == 20);
+ }
+
+ if (verbose >= 2)
+ printbuf(session->v2_data.k1, 20, "Generated K1");
+
+ return 0;
+}
+
+
+
+/*
+ * lanplus_generate_k2
+ *
+ * Generate K2, the key used for RMCP+ AES encryption.
+ *
+ * We use the authentication algorithm to generated the HMAC, using
+ * the session integrity key (SIK) as our key.
+ *
+ * param session [in/out].
+ *
+ * returns 0 on success
+ * 1 on failure
+ */
+int
+lanplus_generate_k2(struct ipmi_session * session)
+{
+ uint32_t mac_length;
+
+ uint8_t CONST_2[] =
+ {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+
+ if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
+ memcpy(session->v2_data.k2, CONST_2, 20);
+ else
+ {
+ lanplus_HMAC(session->v2_data.auth_alg,
+ session->v2_data.sik,
+ IPMI_SIK_BUFFER_SIZE, /* SIK length */
+ CONST_2,
+ 20,
+ session->v2_data.k2,
+ &mac_length);
+ assert(mac_length == 20);
+ }
+
+ if (verbose >= 2)
+ printbuf(session->v2_data.k2, 20, "Generated K2");
+
+ return 0;
+}
+
+
+
+/*
+ * lanplus_encrypt_payload
+ *
+ * Perform the appropriate encryption on the input data. Output the encrypted
+ * data to output, including the required confidentiality header and trailer.
+ * If the crypt_alg is IPMI_CRYPT_NONE, simply copy the input to the output and
+ * set bytes_written to input_length.
+ *
+ * param crypt_alg specifies the encryption algorithm (from table 13-19 of the
+ * IPMI v2 spec)
+ * param key is the used as input to the encryption algorithmf
+ * param input is the input data to be encrypted
+ * param input_length is the length of the input data to be encrypted
+ * param output is the cipher text generated by the encryption process
+ * param bytes_written is the number of bytes written during the encryption
+ * process
+ *
+ * returns 0 on success
+ * 1 on failure
+ */
+int
+lanplus_encrypt_payload(uint8_t crypt_alg,
+ const uint8_t * key, const uint8_t * input,
+ uint32_t input_length, uint8_t * output,
+ uint16_t * bytes_written)
+{
+ uint8_t * padded_input;
+ uint32_t mod, i, bytes_encrypted;
+ uint8_t pad_length = 0;
+
+ if (crypt_alg == IPMI_CRYPT_NONE)
+ {
+ /* Just copy the input to the output */
+ *bytes_written = input_length;
+ return 0;
+ }
+
+ /* Currently, we only support AES */
+ assert(crypt_alg == IPMI_CRYPT_AES_CBC_128);
+ assert(input_length <= IPMI_MAX_PAYLOAD_SIZE);
+
+
+ /*
+ * The input to the AES encryption algorithm has to be a multiple of the
+ * block size (16 bytes). The extra byte we are adding is the pad length
+ * byte.
+ */
+ mod = (input_length + 1) % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE;
+ if (mod)
+ pad_length = IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE - mod;
+
+ padded_input = (uint8_t*)malloc(input_length + pad_length + 1);
+ if (padded_input == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return 1;
+ }
+ memcpy(padded_input, input, input_length);
+
+ /* add the pad */
+ for (i = 0; i < pad_length; ++i)
+ padded_input[input_length + i] = i + 1;
+
+ /* add the pad length */
+ padded_input[input_length + pad_length] = pad_length;
+
+ /* Generate an initialization vector, IV, for the encryption process */
+ if (lanplus_rand(output, IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE))
+ {
+ lprintf(LOG_ERR, "lanplus_encrypt_payload: Error generating IV");
+ if (padded_input != NULL) {
+ free(padded_input);
+ padded_input = NULL;
+ }
+ return 1;
+ }
+
+ if (verbose > 2)
+ printbuf(output, IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, ">> Initialization vector");
+
+
+
+ lanplus_encrypt_aes_cbc_128(output, /* IV */
+ key, /* K2 */
+ padded_input, /* Data to encrypt */
+ input_length + pad_length + 1, /* Input length */
+ output + IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, /* output */
+ &bytes_encrypted); /* bytes written */
+
+ *bytes_written =
+ IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE + /* IV */
+ bytes_encrypted;
+
+ free(padded_input);
+ padded_input = NULL;
+
+ return 0;
+}
+
+
+
+/*
+ * lanplus_has_valid_auth_code
+ *
+ * Determine whether the packets authcode field is valid for packet.
+ *
+ * We always return success if any of the following are true.
+ * - this is not an IPMIv2 packet
+ * - the session is not yet active
+ * - the packet specifies that it is not authenticated
+ * - the integrity algorithm agreed upon during session creation is "none"
+ *
+ * The authcode is computed using the specified integrity algorithm starting
+ * with the AuthType / Format field, and ending with the field immediately
+ * preceeding the authcode itself.
+ *
+ * The key key used to generate the authcode MAC is K1.
+ *
+ * param rs holds the response structure.
+ * param session holds our session state, including our chosen algorithm, key, etc.
+ *
+ * returns 1 on success (authcode is valid)
+ * 0 on failure (autchode integrity check failed)
+ */
+int
+lanplus_has_valid_auth_code(struct ipmi_rs * rs, struct ipmi_session * session)
+{
+ uint8_t * bmc_authcode;
+ uint8_t generated_authcode[IPMI_MAX_MAC_SIZE];
+ uint32_t generated_authcode_length;
+
+
+ if ((rs->session.authtype != IPMI_SESSION_AUTHTYPE_RMCP_PLUS) ||
+ (session->v2_data.session_state != LANPLUS_STATE_ACTIVE) ||
+ (! rs->session.bAuthenticated) ||
+ (session->v2_data.integrity_alg == IPMI_INTEGRITY_NONE))
+ return 1;
+
+ /* We only support SHA1-96 now */
+ assert(session->v2_data.integrity_alg == IPMI_INTEGRITY_HMAC_SHA1_96);
+
+ /*
+ * For SHA1-96, the authcode will be the last 12 bytes in the packet
+ */
+ bmc_authcode = rs->data + (rs->data_len - IPMI_SHA1_AUTHCODE_SIZE);
+
+ lanplus_HMAC(session->v2_data.integrity_alg,
+ session->v2_data.k1,
+ IPMI_AUTHCODE_BUFFER_SIZE,
+ rs->data + IPMI_LANPLUS_OFFSET_AUTHTYPE,
+ rs->data_len - IPMI_LANPLUS_OFFSET_AUTHTYPE - IPMI_SHA1_AUTHCODE_SIZE,
+ generated_authcode,
+ &generated_authcode_length);
+
+ if (verbose > 3)
+ {
+ lprintf(LOG_DEBUG+2, "Validating authcode");
+ printbuf(session->v2_data.k1, 20, "K1");
+ printbuf(rs->data + IPMI_LANPLUS_OFFSET_AUTHTYPE,
+ rs->data_len - IPMI_LANPLUS_OFFSET_AUTHTYPE - IPMI_SHA1_AUTHCODE_SIZE,
+ "Authcode Input Data");
+ printbuf(generated_authcode, 12, "Generated authcode");
+ printbuf(bmc_authcode, 12, "Expected authcode");
+ }
+
+
+ assert(generated_authcode_length == 20);
+ return (memcmp(bmc_authcode, generated_authcode, 12) == 0);
+}
+
+
+
+/*
+ * lanplus_decrypt_payload
+ *
+ *
+ * param input points to the beginning of the payload (which will be the IV if
+ * we are using AES)
+ * param payload_size [out] will be set to the size of the payload EXCLUDING
+ * padding
+ *
+ * returns 0 on success (we were able to successfully decrypt the packet)
+ * 1 on failure (we were unable to successfully decrypt the packet)
+ */
+int
+lanplus_decrypt_payload(uint8_t crypt_alg, const uint8_t * key,
+ const uint8_t * input, uint32_t input_length,
+ uint8_t * output, uint16_t * payload_size)
+{
+ uint8_t * decrypted_payload;
+ uint32_t bytes_decrypted;
+
+ if (crypt_alg == IPMI_CRYPT_NONE)
+ {
+ /* We are not encrypted. The paylaod size is is everything. */
+ *payload_size = input_length;
+ memmove(output, input, input_length);
+ return 0;
+ }
+
+ /* We only support AES */
+ assert(crypt_alg == IPMI_CRYPT_AES_CBC_128);
+
+ decrypted_payload = (uint8_t*)malloc(input_length);
+ if (decrypted_payload == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return 1;
+ }
+
+
+ lanplus_decrypt_aes_cbc_128(input, /* IV */
+ key, /* Key */
+ input +
+ IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, /* Data to decrypt */
+ input_length -
+ IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, /* Input length */
+ decrypted_payload, /* output */
+ &bytes_decrypted); /* bytes written */
+
+ if (bytes_decrypted != 0)
+ {
+ /* Success */
+ uint8_t conf_pad_length;
+ int i;
+
+ memmove(output,
+ decrypted_payload,
+ bytes_decrypted);
+
+ /*
+ * We have to determine the payload size, by substracting the padding, etc.
+ * The last byte of the decrypted payload is the confidentiality pad length.
+ */
+ conf_pad_length = decrypted_payload[bytes_decrypted - 1];
+ *payload_size = bytes_decrypted - conf_pad_length - 1;
+
+ /*
+ * Extra test to make sure that the padding looks like it should (should start
+ * with 0x01, 0x02, 0x03, etc...
+ */
+ for (i = 0; i < conf_pad_length; ++i)
+ {
+ if (decrypted_payload[*payload_size + i] != (i + 1))
+ {
+ lprintf(LOG_ERR, "Malformed payload padding");
+ assert(0);
+ }
+ }
+ }
+ else
+ {
+ lprintf(LOG_ERR, "ERROR: lanplus_decrypt_aes_cbc_128 decryptd 0 bytes");
+ assert(0);
+ }
+
+ free(decrypted_payload);
+ decrypted_payload = NULL;
+ return (bytes_decrypted == 0);
+}
diff --git a/src/plugins/lanplus/lanplus_crypt.h b/src/plugins/lanplus/lanplus_crypt.h
new file mode 100644
index 0000000..d69cc9b
--- /dev/null
+++ b/src/plugins/lanplus/lanplus_crypt.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IPMI_LANPLUS_CRYPT_H
+#define IPMI_LANPLUS_CRYPT_H
+
+#include <ipmitool/ipmi_intf.h>
+
+/*
+ * See the implementation file for documentation
+ * ipmi_intf can be used for oem specific implementations
+ * e.g. if (ipmi_oem_active(intf, "OEM_XYZ"))
+ */
+
+int lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
+ const uint8_t * hmac,
+ struct ipmi_intf * intf);
+int lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
+ const uint8_t * hmac,
+ struct ipmi_intf * intf);
+int lanplus_generate_rakp3_authcode(uint8_t * buffer,
+ const struct ipmi_session * session,
+ uint32_t * auth_length,
+ struct ipmi_intf * intf);
+int lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf);
+int lanplus_generate_k1(struct ipmi_session * session);
+int lanplus_generate_k2(struct ipmi_session * session);
+int lanplus_encrypt_payload(uint8_t crypt_alg,
+ const uint8_t * key,
+ const uint8_t * input,
+ uint32_t input_length,
+ uint8_t * output,
+ uint16_t * bytesWritten);
+int lanplus_decrypt_payload(uint8_t crypt_alg,
+ const uint8_t * key,
+ const uint8_t * input,
+ uint32_t input_length,
+ uint8_t * output,
+ uint16_t * payload_size);
+int lanplus_has_valid_auth_code(struct ipmi_rs * rs,
+ struct ipmi_session * session);
+
+
+
+
+#endif /* IPMI_LANPLUS_CRYPT_H */
diff --git a/src/plugins/lanplus/lanplus_crypt_impl.c b/src/plugins/lanplus/lanplus_crypt_impl.c
new file mode 100644
index 0000000..cde6c54
--- /dev/null
+++ b/src/plugins/lanplus/lanplus_crypt_impl.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include "ipmitool/log.h"
+#include "ipmitool/ipmi_constants.h"
+#include "lanplus.h"
+#include "lanplus_crypt_impl.h"
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <assert.h>
+
+
+
+/*
+ * lanplus_seed_prng
+ *
+ * Seed our PRNG with the specified number of bytes from /dev/random
+ *
+ * param bytes specifies the number of bytes to read from /dev/random
+ *
+ * returns 0 on success
+ * 1 on failure
+ */
+int lanplus_seed_prng(uint32_t bytes)
+{
+ if (! RAND_load_file("/dev/urandom", bytes))
+ return 1;
+ else
+ return 0;
+}
+
+
+
+/*
+ * lanplus_rand
+ *
+ * Generate a random number of the specified size
+ *
+ * param num_bytes [in] is the size of the random number to be
+ * generated
+ * param buffer [out] is where we will place our random number
+ *
+ * return 0 on success
+ * 1 on failure
+ */
+int
+lanplus_rand(uint8_t * buffer, uint32_t num_bytes)
+{
+#undef IPMI_LANPLUS_FAKE_RAND
+#ifdef IPMI_LANPLUS_FAKE_RAND
+
+ /*
+ * This code exists so that we can easily find the generated random number
+ * in the hex dumps.
+ */
+ int i;
+ for (i = 0; i < num_bytes; ++i)
+ buffer[i] = 0x70 | i;
+
+ return 0;
+#else
+ return (! RAND_bytes(buffer, num_bytes));
+#endif
+}
+
+
+
+/*
+ * lanplus_HMAC
+ *
+ * param mac specifies the algorithm to be used, currently only SHA1 is supported
+ * param key is the key used for HMAC generation
+ * param key_len is the lenght of key
+ * param d is the data to be MAC'd
+ * param n is the length of the data at d
+ * param md is the result of the HMAC algorithm
+ * param md_len is the length of md
+ *
+ * returns a pointer to md
+ */
+uint8_t *
+lanplus_HMAC(uint8_t mac,
+ const void *key,
+ int key_len,
+ const uint8_t *d,
+ int n,
+ uint8_t *md,
+ uint32_t *md_len)
+{
+ const EVP_MD *evp_md = NULL;
+
+ if ((mac == IPMI_AUTH_RAKP_HMAC_SHA1) ||
+ (mac == IPMI_INTEGRITY_HMAC_SHA1_96))
+ evp_md = EVP_sha1();
+ else
+ {
+ lprintf(LOG_DEBUG, "Invalid mac type 0x%x in lanplus_HMAC\n", mac);
+ assert(0);
+ }
+
+ return HMAC(evp_md, key, key_len, d, n, md, (unsigned int *)md_len);
+}
+
+
+/*
+ * lanplus_encrypt_aes_cbc_128
+ *
+ * Encrypt with the AES CBC 128 algorithm
+ *
+ * param iv is the 16 byte initialization vector
+ * param key is the 16 byte key used by the AES algorithm
+ * param input is the data to be encrypted
+ * param input_length is the number of bytes to be encrypted. This MUST
+ * be a multiple of the block size, 16.
+ * param output is the encrypted output
+ * param bytes_written is the number of bytes written. This param is set
+ * to 0 on failure, or if 0 bytes were input.
+ */
+void
+lanplus_encrypt_aes_cbc_128(const uint8_t * iv,
+ const uint8_t * key,
+ const uint8_t * input,
+ uint32_t input_length,
+ uint8_t * output,
+ uint32_t * bytes_written)
+{
+ EVP_CIPHER_CTX ctx;
+ EVP_CIPHER_CTX_init(&ctx);
+ EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+
+ *bytes_written = 0;
+
+ if (input_length == 0)
+ return;
+
+ if (verbose >= 5)
+ {
+ printbuf(iv, 16, "encrypting with this IV");
+ printbuf(key, 16, "encrypting with this key");
+ printbuf(input, input_length, "encrypting this data");
+ }
+
+
+ /*
+ * The default implementation adds a whole block of padding if the input
+ * data is perfectly aligned. We would like to keep that from happening.
+ * We have made a point to have our input perfectly padded.
+ */
+ assert((input_length % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE) == 0);
+
+
+ if(!EVP_EncryptUpdate(&ctx, output, (int *)bytes_written, input, input_length))
+ {
+ /* Error */
+ *bytes_written = 0;
+ return;
+ }
+ else
+ {
+ uint32_t tmplen;
+
+ if(!EVP_EncryptFinal_ex(&ctx, output + *bytes_written, (int *)&tmplen))
+ {
+ *bytes_written = 0;
+ return; /* Error */
+ }
+ else
+ {
+ /* Success */
+ *bytes_written += tmplen;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ }
+ }
+}
+
+
+
+/*
+ * lanplus_decrypt_aes_cbc_128
+ *
+ * Decrypt with the AES CBC 128 algorithm
+ *
+ * param iv is the 16 byte initialization vector
+ * param key is the 16 byte key used by the AES algorithm
+ * param input is the data to be decrypted
+ * param input_length is the number of bytes to be decrypted. This MUST
+ * be a multiple of the block size, 16.
+ * param output is the decrypted output
+ * param bytes_written is the number of bytes written. This param is set
+ * to 0 on failure, or if 0 bytes were input.
+ */
+void
+lanplus_decrypt_aes_cbc_128(const uint8_t * iv,
+ const uint8_t * key,
+ const uint8_t * input,
+ uint32_t input_length,
+ uint8_t * output,
+ uint32_t * bytes_written)
+{
+ EVP_CIPHER_CTX ctx;
+ EVP_CIPHER_CTX_init(&ctx);
+ EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+
+ if (verbose >= 5)
+ {
+ printbuf(iv, 16, "decrypting with this IV");
+ printbuf(key, 16, "decrypting with this key");
+ printbuf(input, input_length, "decrypting this data");
+ }
+
+
+ *bytes_written = 0;
+
+ if (input_length == 0)
+ return;
+
+ /*
+ * The default implementation adds a whole block of padding if the input
+ * data is perfectly aligned. We would like to keep that from happening.
+ * We have made a point to have our input perfectly padded.
+ */
+ assert((input_length % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE) == 0);
+
+
+ if (!EVP_DecryptUpdate(&ctx, output, (int *)bytes_written, input, input_length))
+ {
+ /* Error */
+ lprintf(LOG_DEBUG, "ERROR: decrypt update failed");
+ *bytes_written = 0;
+ return;
+ }
+ else
+ {
+ uint32_t tmplen;
+
+ if (!EVP_DecryptFinal_ex(&ctx, output + *bytes_written, (int *)&tmplen))
+ {
+ char buffer[1000];
+ ERR_error_string(ERR_get_error(), buffer);
+ lprintf(LOG_DEBUG, "the ERR error %s", buffer);
+ lprintf(LOG_DEBUG, "ERROR: decrypt final failed");
+ *bytes_written = 0;
+ return; /* Error */
+ }
+ else
+ {
+ /* Success */
+ *bytes_written += tmplen;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ }
+ }
+
+ if (verbose >= 5)
+ {
+ lprintf(LOG_DEBUG, "Decrypted %d encrypted bytes", input_length);
+ printbuf(output, *bytes_written, "Decrypted this data");
+ }
+}
diff --git a/src/plugins/lanplus/lanplus_crypt_impl.h b/src/plugins/lanplus/lanplus_crypt_impl.h
new file mode 100644
index 0000000..ff534bc
--- /dev/null
+++ b/src/plugins/lanplus/lanplus_crypt_impl.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IPMI_LANPLUS_CRYPT_IMPL_H
+#define IPMI_LANPLUS_CRYPT_IMPL_H
+
+
+int
+lanplus_seed_prng(uint32_t bytes);
+
+int
+lanplus_rand(uint8_t * buffer, uint32_t num_bytes);
+
+uint8_t *
+lanplus_HMAC(uint8_t mac, const void *key, int key_len,
+ const uint8_t *d, int n, uint8_t *md,
+ uint32_t *md_len);
+
+void
+lanplus_encrypt_aes_cbc_128(const uint8_t * iv,
+ const uint8_t * key,
+ const uint8_t * input,
+ uint32_t input_length,
+ uint8_t * output,
+ uint32_t * bytes_written);
+
+
+void
+lanplus_decrypt_aes_cbc_128(const uint8_t * iv,
+ const uint8_t * key,
+ const uint8_t * input,
+ uint32_t input_length,
+ uint8_t * output,
+ uint32_t * bytes_written);
+
+
+#endif /* IPMI_LANPLUS_CRYPT_IMPL_H */
diff --git a/src/plugins/lanplus/lanplus_dump.c b/src/plugins/lanplus/lanplus_dump.c
new file mode 100644
index 0000000..8d52fab
--- /dev/null
+++ b/src/plugins/lanplus/lanplus_dump.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include "lanplus.h"
+#include "lanplus_dump.h"
+
+extern const struct valstr ipmi_rakp_return_codes[];
+extern const struct valstr ipmi_priv_levels[];
+extern const struct valstr ipmi_auth_algorithms[];
+extern const struct valstr ipmi_integrity_algorithms[];
+extern const struct valstr ipmi_encryption_algorithms[];
+
+#define DUMP_PREFIX_INCOMING "<<"
+
+void lanplus_dump_open_session_response(const struct ipmi_rs * rsp)
+{
+ if (verbose < 2)
+ return;
+
+ printf("%sOPEN SESSION RESPONSE\n", DUMP_PREFIX_INCOMING);
+
+ printf("%s Message tag : 0x%02x\n",
+ DUMP_PREFIX_INCOMING,
+ rsp->payload.open_session_response.message_tag);
+ printf("%s RMCP+ status : %s\n",
+ DUMP_PREFIX_INCOMING,
+ val2str(rsp->payload.open_session_response.rakp_return_code,
+ ipmi_rakp_return_codes));
+ printf("%s Maximum privilege level : %s\n",
+ DUMP_PREFIX_INCOMING,
+ val2str(rsp->payload.open_session_response.max_priv_level,
+ ipmi_priv_levels));
+ printf("%s Console Session ID : 0x%08lx\n",
+ DUMP_PREFIX_INCOMING,
+ (long)rsp->payload.open_session_response.console_id);
+
+ /* only tag, status, privlvl, and console id are returned if error */
+ if (rsp->payload.open_session_response.rakp_return_code !=
+ IPMI_RAKP_STATUS_NO_ERRORS)
+ return;
+
+ printf("%s BMC Session ID : 0x%08lx\n",
+ DUMP_PREFIX_INCOMING,
+ (long)rsp->payload.open_session_response.bmc_id);
+ printf("%s Negotiated authenticatin algorithm : %s\n",
+ DUMP_PREFIX_INCOMING,
+ val2str(rsp->payload.open_session_response.auth_alg,
+ ipmi_auth_algorithms));
+ printf("%s Negotiated integrity algorithm : %s\n",
+ DUMP_PREFIX_INCOMING,
+ val2str(rsp->payload.open_session_response.integrity_alg,
+ ipmi_integrity_algorithms));
+ printf("%s Negotiated encryption algorithm : %s\n",
+ DUMP_PREFIX_INCOMING,
+ val2str(rsp->payload.open_session_response.crypt_alg,
+ ipmi_encryption_algorithms));
+ printf("\n");
+}
+
+
+
+void lanplus_dump_rakp2_message(const struct ipmi_rs * rsp, uint8_t auth_alg)
+{
+ int i;
+
+ if (verbose < 2)
+ return;
+
+ printf("%sRAKP 2 MESSAGE\n", DUMP_PREFIX_INCOMING);
+
+ printf("%s Message tag : 0x%02x\n",
+ DUMP_PREFIX_INCOMING,
+ rsp->payload.rakp2_message.message_tag);
+
+ printf("%s RMCP+ status : %s\n",
+ DUMP_PREFIX_INCOMING,
+ val2str(rsp->payload.rakp2_message.rakp_return_code,
+ ipmi_rakp_return_codes));
+
+ printf("%s Console Session ID : 0x%08lx\n",
+ DUMP_PREFIX_INCOMING,
+ (long)rsp->payload.rakp2_message.console_id);
+
+ printf("%s BMC random number : 0x", DUMP_PREFIX_INCOMING);
+ for (i = 0; i < 16; ++i)
+ printf("%02x", rsp->payload.rakp2_message.bmc_rand[i]);
+ printf("\n");
+
+ printf("%s BMC GUID : 0x", DUMP_PREFIX_INCOMING);
+ for (i = 0; i < 16; ++i)
+ printf("%02x", rsp->payload.rakp2_message.bmc_guid[i]);
+ printf("\n");
+
+ switch(auth_alg)
+ {
+ case IPMI_AUTH_RAKP_NONE:
+ printf("%s Key exchange auth code : none\n", DUMP_PREFIX_INCOMING);
+ break;
+ case IPMI_AUTH_RAKP_HMAC_SHA1:
+ printf("%s Key exchange auth code [sha1] : 0x", DUMP_PREFIX_INCOMING);
+ for (i = 0; i < 20; ++i)
+ printf("%02x", rsp->payload.rakp2_message.key_exchange_auth_code[i]);
+ printf("\n");
+ break;
+ case IPMI_AUTH_RAKP_HMAC_MD5:
+ printf("%s Key exchange auth code [md5] : 0x", DUMP_PREFIX_INCOMING);
+ for (i = 0; i < 16; ++i)
+ printf("%02x", rsp->payload.rakp2_message.key_exchange_auth_code[i]);
+ printf("\n");
+ break;
+ default:
+ printf("%s Key exchange auth code : invalid", DUMP_PREFIX_INCOMING);
+ }
+ printf("\n");
+}
+
+
+
+void lanplus_dump_rakp4_message(const struct ipmi_rs * rsp, uint8_t auth_alg)
+{
+ int i;
+
+ if (verbose < 2)
+ return;
+
+ printf("%sRAKP 4 MESSAGE\n", DUMP_PREFIX_INCOMING);
+
+ printf("%s Message tag : 0x%02x\n",
+ DUMP_PREFIX_INCOMING,
+ rsp->payload.rakp4_message.message_tag);
+
+ printf("%s RMCP+ status : %s\n",
+ DUMP_PREFIX_INCOMING,
+ val2str(rsp->payload.rakp4_message.rakp_return_code,
+ ipmi_rakp_return_codes));
+
+ printf("%s Console Session ID : 0x%08lx\n",
+ DUMP_PREFIX_INCOMING,
+ (long)rsp->payload.rakp4_message.console_id);
+
+ switch(auth_alg)
+ {
+ case IPMI_AUTH_RAKP_NONE:
+ printf("%s Key exchange auth code : none\n", DUMP_PREFIX_INCOMING);
+ break;
+ case IPMI_AUTH_RAKP_HMAC_SHA1:
+ printf("%s Key exchange auth code [sha1] : 0x", DUMP_PREFIX_INCOMING);
+ for (i = 0; i < 12; ++i)
+ printf("%02x", rsp->payload.rakp4_message.integrity_check_value[i]);
+ printf("\n");
+ break;
+ case IPMI_AUTH_RAKP_HMAC_MD5:
+ printf("%s Key exchange auth code [md5] : 0x", DUMP_PREFIX_INCOMING);
+ for (i = 0; i < 12; ++i)
+ printf("%02x", rsp->payload.rakp4_message.integrity_check_value[i]);
+ printf("\n");
+ break;
+ default:
+ printf("%s Key exchange auth code : invalid", DUMP_PREFIX_INCOMING);
+ }
+ printf("\n");
+}
+
diff --git a/src/plugins/lanplus/lanplus_dump.h b/src/plugins/lanplus/lanplus_dump.h
new file mode 100644
index 0000000..4e29ebb
--- /dev/null
+++ b/src/plugins/lanplus/lanplus_dump.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#ifndef IPMI_LANPLUS_DUMP_H
+#define IPMI_LANPLUS_DUMP_H
+
+#include <ipmitool/ipmi_intf.h>
+
+/* See the implementation file for documentation */
+void lanplus_dump_open_session_response(const struct ipmi_rs * rsp);
+void lanplus_dump_rakp2_message(const struct ipmi_rs * rsp, uint8_t auth_alg);
+void lanplus_dump_rakp4_message(const struct ipmi_rs * rsp, uint8_t auth_alg);
+
+
+#endif /* IPMI_LANPLUS_DUMP_H */
diff --git a/src/plugins/lanplus/lanplus_strings.c b/src/plugins/lanplus/lanplus_strings.c
new file mode 100644
index 0000000..074f898
--- /dev/null
+++ b/src/plugins/lanplus/lanplus_strings.c
@@ -0,0 +1,39 @@
+#include "lanplus.h"
+#include "ipmitool/ipmi_constants.h"
+
+const struct valstr ipmi_rakp_return_codes[] = {
+
+ { IPMI_RAKP_STATUS_NO_ERRORS, "no errors" },
+ { IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_SESSION, "insufficient resources for session" },
+ { IPMI_RAKP_STATUS_INVALID_SESSION_ID, "invalid session ID" },
+ { IPMI_RAKP_STATUS_INVALID_PAYLOAD_TYPE, "invalid payload type" },
+ { IPMI_RAKP_STATUS_INVALID_AUTHENTICATION_ALGORITHM, "invalid authentication algorithm" },
+ { IPMI_RAKP_STATUS_INVALID_INTEGRITTY_ALGORITHM, "invalid integrity algorithm" },
+ { IPMI_RAKP_STATUS_NO_MATCHING_AUTHENTICATION_PAYLOAD, "no matching authentication algorithm"},
+ { IPMI_RAKP_STATUS_NO_MATCHING_INTEGRITY_PAYLOAD, "no matching integrity payload" },
+ { IPMI_RAKP_STATUS_INACTIVE_SESSION_ID, "inactive session ID" },
+ { IPMI_RAKP_STATUS_INVALID_ROLE, "invalid role" },
+ { IPMI_RAKP_STATUS_UNAUTHORIZED_ROLE_REQUESTED, "unauthorized role requested" },
+ { IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_ROLE, "insufficient resources for role" },
+ { IPMI_RAKP_STATUS_INVALID_NAME_LENGTH, "invalid name length" },
+ { IPMI_RAKP_STATUS_UNAUTHORIZED_NAME, "unauthorized name" },
+ { IPMI_RAKP_STATUS_UNAUTHORIZED_GUID, "unauthorized GUID" },
+ { IPMI_RAKP_STATUS_INVALID_INTEGRITY_CHECK_VALUE, "invalid integrity check value" },
+ { IPMI_RAKP_STATUS_INVALID_CONFIDENTIALITY_ALGORITHM, "invalid confidentiality algorithm" },
+ { IPMI_RAKP_STATUS_NO_CIPHER_SUITE_MATCH, "no matching cipher suite" },
+ { IPMI_RAKP_STATUS_ILLEGAL_PARAMTER, "illegal parameter" },
+ { 0, 0 },
+};
+
+
+const struct valstr ipmi_priv_levels[] = {
+ { IPMI_PRIV_CALLBACK, "callback" },
+ { IPMI_PRIV_USER, "user" },
+ { IPMI_PRIV_OPERATOR, "operator" },
+ { IPMI_PRIV_ADMIN, "admin" },
+ { IPMI_PRIV_OEM, "oem" },
+ { 0, 0 },
+};
+
+
+
diff --git a/src/plugins/lanplus/rmcp.h b/src/plugins/lanplus/rmcp.h
new file mode 100644
index 0000000..51dc44d
--- /dev/null
+++ b/src/plugins/lanplus/rmcp.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IPMI_RMCP_H
+#define IPMI_RMCP_H
+
+#include <ipmitool/helper.h>
+#include "lanplus.h"
+
+#define RMCP_VERSION_1 0x06
+
+#define RMCP_UDP_PORT 0x26f /* port 623 */
+#define RMCP_UDP_SECURE_PORT 0x298 /* port 664 */
+
+#define RMCP_TYPE_MASK 0x80
+#define RMCP_TYPE_NORM 0x00
+#define RMCP_TYPE_ACK 0x01
+
+static const struct valstr rmcp_type_vals[] __attribute__((unused)) = {
+ { RMCP_TYPE_NORM, "Normal RMCP" },
+ { RMCP_TYPE_ACK, "RMCP ACK" },
+ { 0, NULL }
+};
+
+#define RMCP_CLASS_MASK 0x1f
+#define RMCP_CLASS_ASF 0x06
+#define RMCP_CLASS_IPMI 0x07
+#define RMCP_CLASS_OEM 0x08
+
+static const struct valstr rmcp_class_vals[] __attribute__((unused)) = {
+ { RMCP_CLASS_ASF, "ASF" },
+ { RMCP_CLASS_IPMI, "IPMI" },
+ { RMCP_CLASS_OEM, "OEM" },
+ { 0, NULL }
+};
+
+/* RMCP message header */
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct rmcp_hdr {
+ uint8_t ver;
+ uint8_t __reserved;
+ uint8_t seq;
+ uint8_t class;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+int handle_rmcp(struct ipmi_intf * intf, uint8_t * data, int data_len);
+
+#endif /* IPMI_RMCP_H */
diff --git a/src/plugins/lipmi/Makefile.am b/src/plugins/lipmi/Makefile.am
new file mode 100644
index 0000000..61c50f4
--- /dev/null
+++ b/src/plugins/lipmi/Makefile.am
@@ -0,0 +1,39 @@
+# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Sun Microsystems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = -I$(top_srcdir)/include
+
+EXTRA_LTLIBRARIES = libintf_lipmi.la
+noinst_LTLIBRARIES = @INTF_LIPMI_LIB@
+libintf_lipmi_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_lipmi_la_SOURCES = lipmi.c
+
diff --git a/src/plugins/lipmi/Makefile.in b/src/plugins/lipmi/Makefile.in
new file mode 100644
index 0000000..2e97922
--- /dev/null
+++ b/src/plugins/lipmi/Makefile.in
@@ -0,0 +1,538 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 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.
+
+# 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@
+
+# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Sun Microsystems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+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@
+subdir = src/plugins/lipmi
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libintf_lipmi_la_DEPENDENCIES = $(top_builddir)/lib/libipmitool.la
+am_libintf_lipmi_la_OBJECTS = lipmi.lo
+libintf_lipmi_la_OBJECTS = $(am_libintf_lipmi_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+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 = $(libintf_lipmi_la_SOURCES)
+DIST_SOURCES = $(libintf_lipmi_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+ARCH = @ARCH@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASEDIR = @BASEDIR@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTRO = @DISTRO@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTF_BMC = @INTF_BMC@
+INTF_BMC_LIB = @INTF_BMC_LIB@
+INTF_DUMMY = @INTF_DUMMY@
+INTF_DUMMY_LIB = @INTF_DUMMY_LIB@
+INTF_FREE = @INTF_FREE@
+INTF_FREE_LIB = @INTF_FREE_LIB@
+INTF_IMB = @INTF_IMB@
+INTF_IMB_LIB = @INTF_IMB_LIB@
+INTF_LAN = @INTF_LAN@
+INTF_LANPLUS = @INTF_LANPLUS@
+INTF_LANPLUS_LIB = @INTF_LANPLUS_LIB@
+INTF_LAN_LIB = @INTF_LAN_LIB@
+INTF_LIPMI = @INTF_LIPMI@
+INTF_LIPMI_LIB = @INTF_LIPMI_LIB@
+INTF_OPEN = @INTF_OPEN@
+INTF_OPEN_LIB = @INTF_OPEN_LIB@
+INTF_SERIAL = @INTF_SERIAL@
+INTF_SERIAL_LIB = @INTF_SERIAL_LIB@
+IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OS = @OS@
+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@
+POW_LIB = @POW_LIB@
+PSTAMP = @PSTAMP@
+RANLIB = @RANLIB@
+RPMBUILD = @RPMBUILD@
+RPM_RELEASE = @RPM_RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_configure_args = @ac_configure_args@
+ac_ct_AR = @ac_ct_AR@
+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@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+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@
+MAINTAINERCLEANFILES = Makefile.in
+INCLUDES = -I$(top_srcdir)/include
+EXTRA_LTLIBRARIES = libintf_lipmi.la
+noinst_LTLIBRARIES = @INTF_LIPMI_LIB@
+libintf_lipmi_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_lipmi_la_SOURCES = lipmi.c
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(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) --foreign src/plugins/lipmi/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/plugins/lipmi/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: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libintf_lipmi.la: $(libintf_lipmi_la_OBJECTS) $(libintf_lipmi_la_DEPENDENCIES) $(EXTRA_libintf_lipmi_la_DEPENDENCIES)
+ $(LINK) $(libintf_lipmi_la_OBJECTS) $(libintf_lipmi_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lipmi.Plo@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 $(LTLIBRARIES)
+installdirs:
+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:
+ 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:
+
+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."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ 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-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:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES 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-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
+
+
+# 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:
diff --git a/src/plugins/lipmi/lipmi.c b/src/plugins/lipmi/lipmi.c
new file mode 100644
index 0000000..fa7845d
--- /dev/null
+++ b/src/plugins/lipmi/lipmi.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stropts.h>
+
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_intf.h>
+
+#include <sys/lipmi/lipmi_intf.h>
+
+#define IPMI_LIPMI_DEV "/dev/lipmi"
+
+extern int verbose;
+
+static int ipmi_lipmi_open(struct ipmi_intf * intf)
+{
+ intf->fd = open(IPMI_LIPMI_DEV, O_RDWR);
+ if (intf->fd < 0) {
+ perror("Could not open lipmi device");
+ return -1;
+ }
+ intf->opened = 1;
+ intf->manufacturer_id = ipmi_get_oem(intf);
+ return intf->fd;
+}
+
+static void ipmi_lipmi_close(struct ipmi_intf * intf)
+{
+ if (intf && intf->fd >= 0)
+ close(intf->fd);
+ intf->fd = -1;
+ intf->opened = 0;
+ intf->manufacturer_id = IPMI_OEM_UNKNOWN;
+}
+
+static struct ipmi_rs * ipmi_lipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
+{
+ struct strioctl istr;
+ static struct lipmi_reqrsp reqrsp;
+ static struct ipmi_rs rsp;
+ static int curr_seq = 0;
+
+ if (!intf || !req)
+ return NULL;
+
+ if (!intf->opened && intf->open && intf->open(intf) < 0)
+ return NULL;
+
+ memset(&reqrsp, 0, sizeof(reqrsp));
+ reqrsp.req.fn = req->msg.netfn;
+ reqrsp.req.lun = 0;
+ reqrsp.req.cmd = req->msg.cmd;
+ reqrsp.req.datalength = req->msg.data_len;
+ memcpy(reqrsp.req.data, req->msg.data, req->msg.data_len);
+ reqrsp.rsp.datalength = RECV_MAX_PAYLOAD_SIZE;
+
+ istr.ic_cmd = IOCTL_IPMI_KCS_ACTION;
+ istr.ic_timout = 0;
+ istr.ic_dp = (char *)&reqrsp;
+ istr.ic_len = sizeof(struct lipmi_reqrsp);
+
+ if (verbose > 1) {
+ printf("LIPMI req.fn : %x\n", reqrsp.req.fn);
+ printf("LIPMI req.lun : %x\n", reqrsp.req.lun);
+ printf("LIPMI req.cmd : %x\n", reqrsp.req.cmd);
+ printf("LIPMI req.datalength : %d\n", reqrsp.req.datalength);
+ }
+
+ if (ioctl(intf->fd, I_STR, &istr) < 0) {
+ perror("LIPMI IOCTL: I_STR");
+ return NULL;
+ }
+
+ memset(&rsp, 0, sizeof(struct ipmi_rs));
+ rsp.ccode = reqrsp.rsp.ccode;
+ rsp.data_len = reqrsp.rsp.datalength;
+
+ if (!rsp.ccode && rsp.data_len)
+ memcpy(rsp.data, reqrsp.rsp.data, rsp.data_len);
+
+ return &rsp;
+}
+
+struct ipmi_intf ipmi_lipmi_intf = {
+ name: "lipmi",
+ desc: "Solaris x86 LIPMI Interface",
+ open: ipmi_lipmi_open,
+ close: ipmi_lipmi_close,
+ sendrecv: ipmi_lipmi_send_cmd,
+ target_addr: IPMI_BMC_SLAVE_ADDR,
+};
+
diff --git a/src/plugins/open/Makefile.am b/src/plugins/open/Makefile.am
new file mode 100644
index 0000000..89ce711
--- /dev/null
+++ b/src/plugins/open/Makefile.am
@@ -0,0 +1,39 @@
+# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Sun Microsystems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = -I$(top_srcdir)/include
+
+EXTRA_LTLIBRARIES = libintf_open.la
+noinst_LTLIBRARIES = @INTF_OPEN_LIB@
+libintf_open_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_open_la_SOURCES = open.c open.h
+
diff --git a/src/plugins/open/Makefile.in b/src/plugins/open/Makefile.in
new file mode 100644
index 0000000..d6b1f26
--- /dev/null
+++ b/src/plugins/open/Makefile.in
@@ -0,0 +1,538 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 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.
+
+# 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@
+
+# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Sun Microsystems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+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@
+subdir = src/plugins/open
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libintf_open_la_DEPENDENCIES = $(top_builddir)/lib/libipmitool.la
+am_libintf_open_la_OBJECTS = open.lo
+libintf_open_la_OBJECTS = $(am_libintf_open_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+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 = $(libintf_open_la_SOURCES)
+DIST_SOURCES = $(libintf_open_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+ARCH = @ARCH@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASEDIR = @BASEDIR@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTRO = @DISTRO@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTF_BMC = @INTF_BMC@
+INTF_BMC_LIB = @INTF_BMC_LIB@
+INTF_DUMMY = @INTF_DUMMY@
+INTF_DUMMY_LIB = @INTF_DUMMY_LIB@
+INTF_FREE = @INTF_FREE@
+INTF_FREE_LIB = @INTF_FREE_LIB@
+INTF_IMB = @INTF_IMB@
+INTF_IMB_LIB = @INTF_IMB_LIB@
+INTF_LAN = @INTF_LAN@
+INTF_LANPLUS = @INTF_LANPLUS@
+INTF_LANPLUS_LIB = @INTF_LANPLUS_LIB@
+INTF_LAN_LIB = @INTF_LAN_LIB@
+INTF_LIPMI = @INTF_LIPMI@
+INTF_LIPMI_LIB = @INTF_LIPMI_LIB@
+INTF_OPEN = @INTF_OPEN@
+INTF_OPEN_LIB = @INTF_OPEN_LIB@
+INTF_SERIAL = @INTF_SERIAL@
+INTF_SERIAL_LIB = @INTF_SERIAL_LIB@
+IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OS = @OS@
+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@
+POW_LIB = @POW_LIB@
+PSTAMP = @PSTAMP@
+RANLIB = @RANLIB@
+RPMBUILD = @RPMBUILD@
+RPM_RELEASE = @RPM_RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_configure_args = @ac_configure_args@
+ac_ct_AR = @ac_ct_AR@
+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@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+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@
+MAINTAINERCLEANFILES = Makefile.in
+INCLUDES = -I$(top_srcdir)/include
+EXTRA_LTLIBRARIES = libintf_open.la
+noinst_LTLIBRARIES = @INTF_OPEN_LIB@
+libintf_open_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_open_la_SOURCES = open.c open.h
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(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) --foreign src/plugins/open/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/plugins/open/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: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libintf_open.la: $(libintf_open_la_OBJECTS) $(libintf_open_la_DEPENDENCIES) $(EXTRA_libintf_open_la_DEPENDENCIES)
+ $(LINK) $(libintf_open_la_OBJECTS) $(libintf_open_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/open.Plo@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 $(LTLIBRARIES)
+installdirs:
+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:
+ 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:
+
+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."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ 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-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:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES 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-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
+
+
+# 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:
diff --git a/src/plugins/open/open.c b/src/plugins/open/open.c
new file mode 100644
index 0000000..92b6f37
--- /dev/null
+++ b/src/plugins/open/open.c
@@ -0,0 +1,439 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_intf.h>
+#include <ipmitool/helper.h>
+#include <ipmitool/log.h>
+
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#if defined(HAVE_SYS_IOCCOM_H)
+# include <sys/ioccom.h>
+#endif
+
+#if defined(HAVE_OPENIPMI_H)
+# if defined(HAVE_LINUX_COMPILER_H)
+# include <linux/compiler.h>
+# endif
+# include <linux/ipmi.h>
+#elif defined(HAVE_FREEBSD_IPMI_H)
+/* FreeBSD OpenIPMI-compatible header */
+# include <sys/ipmi.h>
+#else
+# include "open.h"
+#endif
+
+/**
+ * Maximum input message size for KCS/SMIC is 40 with 2 utility bytes and
+ * 38 bytes of data.
+ * Maximum input message size for BT is 42 with 4 utility bytes and
+ * 38 bytes of data.
+ */
+#define IPMI_OPENIPMI_MAX_RQ_DATA_SIZE 38
+
+/**
+ * Maximum output message size for KCS/SMIC is 38 with 2 utility bytes, a byte
+ * for completion code and 35 bytes of data.
+ * Maximum output message size for BT is 40 with 4 utility bytes, a byte
+ * for completion code and 35 bytes of data.
+ */
+#define IPMI_OPENIPMI_MAX_RS_DATA_SIZE 35
+
+extern int verbose;
+
+static int
+ipmi_openipmi_open(struct ipmi_intf * intf)
+{
+ int i = 0;
+
+ char ipmi_dev[16];
+ char ipmi_devfs[16];
+ char ipmi_devfs2[16];
+ int devnum = 0;
+
+ devnum = intf->devnum;
+
+ sprintf(ipmi_dev, "/dev/ipmi%d", devnum);
+ sprintf(ipmi_devfs, "/dev/ipmi/%d", devnum);
+ sprintf(ipmi_devfs2, "/dev/ipmidev/%d", devnum);
+ lprintf(LOG_DEBUG, "Using ipmi device %d", devnum);
+
+ intf->fd = open(ipmi_dev, O_RDWR);
+
+ if (intf->fd < 0) {
+ intf->fd = open(ipmi_devfs, O_RDWR);
+ if (intf->fd < 0) {
+ intf->fd = open(ipmi_devfs2, O_RDWR);
+ }
+ if (intf->fd < 0) {
+ lperror(LOG_ERR, "Could not open device at %s or %s or %s",
+ ipmi_dev, ipmi_devfs , ipmi_devfs2);
+ return -1;
+ }
+ }
+
+ if (ioctl(intf->fd, IPMICTL_SET_GETS_EVENTS_CMD, &i) < 0) {
+ lperror(LOG_ERR, "Could not enable event receiver");
+ return -1;
+ }
+
+ intf->opened = 1;
+
+ /* This is never set to 0, the default is IPMI_BMC_SLAVE_ADDR */
+ if (intf->my_addr != 0) {
+ if (intf->set_my_addr(intf, intf->my_addr) < 0) {
+ lperror(LOG_ERR, "Could not set IPMB address");
+ return -1;
+ }
+ lprintf(LOG_DEBUG, "Set IPMB address to 0x%x",
+ intf->my_addr );
+ }
+
+ intf->manufacturer_id = ipmi_get_oem(intf);
+ return intf->fd;
+}
+static int
+ipmi_openipmi_set_my_addr(struct ipmi_intf *intf, uint8_t addr)
+{
+ unsigned int a = addr;
+ if (ioctl(intf->fd, IPMICTL_SET_MY_ADDRESS_CMD, &a) < 0) {
+ lperror(LOG_ERR, "Could not set IPMB address");
+ return -1;
+ }
+ intf->my_addr = addr;
+ return 0;
+}
+
+static void
+ipmi_openipmi_close(struct ipmi_intf * intf)
+{
+ if (intf->fd >= 0) {
+ close(intf->fd);
+ intf->fd = -1;
+ }
+
+ intf->opened = 0;
+ intf->manufacturer_id = IPMI_OEM_UNKNOWN;
+}
+
+static struct ipmi_rs *
+ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
+{
+ struct ipmi_recv recv;
+ struct ipmi_addr addr;
+ struct ipmi_system_interface_addr bmc_addr = {
+ addr_type: IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
+ channel: IPMI_BMC_CHANNEL,
+ };
+ struct ipmi_ipmb_addr ipmb_addr = {
+ addr_type: IPMI_IPMB_ADDR_TYPE,
+ };
+ struct ipmi_req _req;
+ static struct ipmi_rs rsp;
+ static int curr_seq = 0;
+ fd_set rset;
+
+ uint8_t * data = NULL;
+ int data_len = 0;
+
+
+ if (intf == NULL || req == NULL)
+ return NULL;
+
+ ipmb_addr.channel = intf->target_channel & 0x0f;
+
+ if (intf->opened == 0 && intf->open != NULL)
+ if (intf->open(intf) < 0)
+ return NULL;
+
+ if (verbose > 2)
+ printbuf(req->msg.data, req->msg.data_len,
+ "OpenIPMI Request Message");
+
+ /*
+ * setup and send message
+ */
+
+ memset(&_req, 0, sizeof(struct ipmi_req));
+
+ if (intf->target_addr != 0 &&
+ intf->target_addr != intf->my_addr) {
+ /* use IPMB address if needed */
+ ipmb_addr.slave_addr = intf->target_addr;
+ ipmb_addr.lun = req->msg.lun;
+ lprintf(LOG_DEBUG, "Sending request 0x%x to "
+ "IPMB target @ 0x%x:0x%x (from 0x%x)",
+ req->msg.cmd,
+ intf->target_addr,intf->target_channel, intf->my_addr);
+
+ if(intf->transit_addr != 0 && intf->transit_addr != intf->my_addr) {
+ uint8_t index = 0;
+
+ lprintf(LOG_DEBUG, "Encapsulating data sent to "
+ "end target [0x%02x,0x%02x] using transit [0x%02x,0x%02x] from 0x%x ",
+ (0x40 | intf->target_channel),
+ intf->target_addr,
+ intf->transit_channel,
+ intf->transit_addr,
+ intf->my_addr
+ );
+
+ /* Convert Message to 'Send Message' */
+ /* Supplied req : req , internal req : _req */
+
+ if (verbose > 4) {
+ fprintf(stderr, "Converting message:\n");
+ fprintf(stderr, " netfn = 0x%x\n", req->msg.netfn );
+ fprintf(stderr, " cmd = 0x%x\n", req->msg.cmd);
+ if (recv.msg.data && recv.msg.data_len) {
+ fprintf(stderr, " data_len = %d\n", req->msg.data_len);
+ fprintf(stderr, " data = %s\n",
+ buf2str(req->msg.data,req->msg.data_len));
+ }
+ }
+
+ /* Modify target address to use 'transit' instead */
+ ipmb_addr.slave_addr = intf->transit_addr;
+ ipmb_addr.channel = intf->transit_channel;
+
+ /* FIXME backup "My address" */
+ data_len = req->msg.data_len + 8;
+ data = malloc(data_len);
+ if (data == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return NULL;
+ }
+
+ memset(data, 0, data_len);
+
+ data[index++] = (0x40|intf->target_channel);
+ data[index++] = intf->target_addr;
+ data[index++] = ( req->msg.netfn << 2 ) | req->msg.lun ;
+ data[index++] = ipmi_csum(data+1, 2);
+ data[index++] = 0xFF; /* normally 0x20 , overwritten by IPMC */
+ data[index++] = ( (0) << 2) | 0 ; /* FIXME */
+ data[index++] = req->msg.cmd;
+ memcpy( (data+index) , req->msg.data, req->msg.data_len);
+ index += req->msg.data_len;
+ data[index++] = ipmi_csum( (data+4),(req->msg.data_len + 3) );
+
+ if (verbose > 4) {
+ fprintf(stderr, "Encapsulated message:\n");
+ fprintf(stderr, " netfn = 0x%x\n", IPMI_NETFN_APP );
+ fprintf(stderr, " cmd = 0x%x\n", 0x34 );
+ if (data && data_len) {
+ fprintf(stderr, " data_len = %d\n", data_len);
+ fprintf(stderr, " data = %s\n",
+ buf2str(data,data_len));
+ }
+ }
+ }
+ _req.addr = (unsigned char *) &ipmb_addr;
+ _req.addr_len = sizeof(ipmb_addr);
+ } else {
+ /* otherwise use system interface */
+ lprintf(LOG_DEBUG+2, "Sending request 0x%x to "
+ "System Interface", req->msg.cmd);
+ bmc_addr.lun = req->msg.lun;
+ _req.addr = (unsigned char *) &bmc_addr;
+ _req.addr_len = sizeof(bmc_addr);
+ }
+
+ _req.msgid = curr_seq++;
+
+ /* In case of a bridge request */
+ if( data != NULL && data_len != 0 ) {
+ _req.msg.data = data;
+ _req.msg.data_len = data_len;
+ _req.msg.netfn = IPMI_NETFN_APP;
+ _req.msg.cmd = 0x34;
+
+ } else {
+ _req.msg.data = req->msg.data;
+ _req.msg.data_len = req->msg.data_len;
+ _req.msg.netfn = req->msg.netfn;
+ _req.msg.cmd = req->msg.cmd;
+ }
+
+ if (ioctl(intf->fd, IPMICTL_SEND_COMMAND, &_req) < 0) {
+ lperror(LOG_ERR, "Unable to send command");
+ if (data != NULL) {
+ free(data);
+ data = NULL;
+ }
+ return NULL;
+ }
+
+ /*
+ * wait for and retrieve response
+ */
+
+ if (intf->noanswer) {
+ if (data != NULL) {
+ free(data);
+ data = NULL;
+ }
+ return NULL;
+ }
+
+ FD_ZERO(&rset);
+ FD_SET(intf->fd, &rset);
+
+ if (select(intf->fd+1, &rset, NULL, NULL, NULL) < 0) {
+ lperror(LOG_ERR, "I/O Error");
+ if (data != NULL) {
+ free(data);
+ data = NULL;
+ }
+ return NULL;
+ }
+ if (FD_ISSET(intf->fd, &rset) == 0) {
+ lprintf(LOG_ERR, "No data available");
+ if (data != NULL) {
+ free(data);
+ data = NULL;
+ }
+ return NULL;
+ }
+
+ recv.addr = (unsigned char *) &addr;
+ recv.addr_len = sizeof(addr);
+ recv.msg.data = rsp.data;
+ recv.msg.data_len = sizeof(rsp.data);
+
+ /* get data */
+ if (ioctl(intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv) < 0) {
+ lperror(LOG_ERR, "Error receiving message");
+ if (errno != EMSGSIZE) {
+ if (data != NULL) {
+ free(data);
+ data = NULL;
+ }
+ return NULL;
+ }
+ }
+
+ if (verbose > 4) {
+ fprintf(stderr, "Got message:");
+ fprintf(stderr, " type = %d\n", recv.recv_type);
+ fprintf(stderr, " channel = 0x%x\n", addr.channel);
+ fprintf(stderr, " msgid = %ld\n", recv.msgid);
+ fprintf(stderr, " netfn = 0x%x\n", recv.msg.netfn);
+ fprintf(stderr, " cmd = 0x%x\n", recv.msg.cmd);
+ if (recv.msg.data && recv.msg.data_len) {
+ fprintf(stderr, " data_len = %d\n", recv.msg.data_len);
+ fprintf(stderr, " data = %s\n",
+ buf2str(recv.msg.data, recv.msg.data_len));
+ }
+ }
+
+ if(intf->transit_addr != 0 && intf->transit_addr != intf->my_addr) {
+ uint8_t index = 0;
+
+ /* ipmb_addr.transit_slave_addr = intf->transit_addr; */
+ lprintf(LOG_DEBUG, "Decapsulating data received from transit "
+ "IPMB target @ 0x%x", intf->transit_addr);
+
+ /* comp code */
+ /* Check data */
+
+ if( recv.msg.data[0] == 0 ) {
+ recv.msg.netfn = recv.msg.data[2] >> 2;
+ recv.msg.cmd = recv.msg.data[6];
+
+ recv.msg.data = memmove(recv.msg.data ,recv.msg.data+7 , recv.msg.data_len - 7);
+ recv.msg.data_len -=8;
+
+ if (verbose > 4) {
+ fprintf(stderr, "Decapsulated message:\n");
+ fprintf(stderr, " netfn = 0x%x\n", recv.msg.netfn );
+ fprintf(stderr, " cmd = 0x%x\n", recv.msg.cmd);
+ if (recv.msg.data && recv.msg.data_len) {
+ fprintf(stderr, " data_len = %d\n", recv.msg.data_len);
+ fprintf(stderr, " data = %s\n",
+ buf2str(recv.msg.data,recv.msg.data_len));
+ }
+ }
+ }
+ }
+
+ /* save completion code */
+ rsp.ccode = recv.msg.data[0];
+ rsp.data_len = recv.msg.data_len - 1;
+
+ /* save response data for caller */
+ if (rsp.ccode == 0 && rsp.data_len > 0) {
+ memmove(rsp.data, rsp.data + 1, rsp.data_len);
+ rsp.data[rsp.data_len] = 0;
+ }
+
+ if (data != NULL) {
+ free(data);
+ data = NULL;
+ }
+
+ return &rsp;
+}
+
+int ipmi_openipmi_setup(struct ipmi_intf * intf)
+{
+ /* set default payload size */
+ intf->max_request_data_size = IPMI_OPENIPMI_MAX_RQ_DATA_SIZE;
+ intf->max_response_data_size = IPMI_OPENIPMI_MAX_RS_DATA_SIZE;
+
+ return 0;
+}
+
+struct ipmi_intf ipmi_open_intf = {
+ name: "open",
+ desc: "Linux OpenIPMI Interface",
+ setup: ipmi_openipmi_setup,
+ open: ipmi_openipmi_open,
+ close: ipmi_openipmi_close,
+ sendrecv: ipmi_openipmi_send_cmd,
+ set_my_addr: ipmi_openipmi_set_my_addr,
+ my_addr: IPMI_BMC_SLAVE_ADDR,
+ target_addr: 0, /* init so -m local_addr does not cause bridging */
+};
diff --git a/src/plugins/open/open.h b/src/plugins/open/open.h
new file mode 100644
index 0000000..5d7aa5b
--- /dev/null
+++ b/src/plugins/open/open.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IPMI_OPENIPMI_H
+#define IPMI_OPENIPMI_H
+
+#define IPMI_MAX_ADDR_SIZE 0x20
+#define IPMI_BMC_CHANNEL 0xf
+#define IPMI_NUM_CHANNELS 0x10
+
+#define IPMI_SYSTEM_INTERFACE_ADDR_TYPE 0x0c
+#define IPMI_IPMB_ADDR_TYPE 0x01
+#define IPMI_IPMB_BROADCAST_ADDR_TYPE 0x41
+
+#define IPMI_RESPONSE_RECV_TYPE 1
+#define IPMI_ASYNC_EVENT_RECV_TYPE 2
+#define IPMI_CMD_RECV_TYPE 3
+
+struct ipmi_addr {
+ int addr_type;
+ short channel;
+ char data[IPMI_MAX_ADDR_SIZE];
+};
+
+struct ipmi_msg {
+ unsigned char netfn;
+ unsigned char cmd;
+ unsigned short data_len;
+ unsigned char *data;
+};
+
+struct ipmi_req {
+ unsigned char *addr;
+ unsigned int addr_len;
+ long msgid;
+ struct ipmi_msg msg;
+};
+
+struct ipmi_recv {
+ int recv_type;
+ unsigned char *addr;
+ unsigned int addr_len;
+ long msgid;
+ struct ipmi_msg msg;
+};
+
+struct ipmi_cmdspec {
+ unsigned char netfn;
+ unsigned char cmd;
+};
+
+struct ipmi_system_interface_addr {
+ int addr_type;
+ short channel;
+ unsigned char lun;
+};
+
+struct ipmi_ipmb_addr {
+ int addr_type;
+ short channel;
+ unsigned char slave_addr;
+ unsigned char lun;
+};
+
+#define IPMI_IOC_MAGIC 'i'
+#define IPMICTL_RECEIVE_MSG_TRUNC _IOWR(IPMI_IOC_MAGIC, 11, struct ipmi_recv)
+#define IPMICTL_RECEIVE_MSG _IOWR(IPMI_IOC_MAGIC, 12, struct ipmi_recv)
+#define IPMICTL_SEND_COMMAND _IOR(IPMI_IOC_MAGIC, 13, struct ipmi_req)
+#define IPMICTL_REGISTER_FOR_CMD _IOR(IPMI_IOC_MAGIC, 14, struct ipmi_cmdspec)
+#define IPMICTL_UNREGISTER_FOR_CMD _IOR(IPMI_IOC_MAGIC, 15, struct ipmi_cmdspec)
+#define IPMICTL_SET_GETS_EVENTS_CMD _IOR(IPMI_IOC_MAGIC, 16, int)
+#define IPMICTL_SET_MY_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 17, unsigned int)
+#define IPMICTL_GET_MY_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 18, unsigned int)
+#define IPMICTL_SET_MY_LUN_CMD _IOR(IPMI_IOC_MAGIC, 19, unsigned int)
+#define IPMICTL_GET_MY_LUN_CMD _IOR(IPMI_IOC_MAGIC, 20, unsigned int)
+
+#endif /*IPMI_OPENIPMI_H*/
diff --git a/src/plugins/serial/Makefile.am b/src/plugins/serial/Makefile.am
new file mode 100644
index 0000000..5bfbd0d
--- /dev/null
+++ b/src/plugins/serial/Makefile.am
@@ -0,0 +1,38 @@
+# * Copyright (c) 2012 Pigeon Point Systems. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Pigeon Point Systems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# PIGEON POINT SYSTEMS ("PPS") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# PPS OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF PPS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = -I$(top_srcdir)/include
+
+EXTRA_LTLIBRARIES = libintf_serial.la
+noinst_LTLIBRARIES = @INTF_SERIAL_LIB@
+libintf_serial_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_serial_la_SOURCES = serial_terminal.c serial_basic.c
diff --git a/src/plugins/serial/Makefile.in b/src/plugins/serial/Makefile.in
new file mode 100644
index 0000000..5abad44
--- /dev/null
+++ b/src/plugins/serial/Makefile.in
@@ -0,0 +1,539 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 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.
+
+# 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@
+
+# * Copyright (c) 2012 Pigeon Point Systems. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# Redistribution of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# Redistribution in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# Neither the name of Pigeon Point Systems, Inc. or the names of
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# This software is provided "AS IS," without a warranty of any kind.
+# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+# PIGEON POINT SYSTEMS ("PPS") AND ITS LICENSORS SHALL NOT BE LIABLE
+# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+# PPS OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+# EVEN IF PPS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+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@
+subdir = src/plugins/serial
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libintf_serial_la_DEPENDENCIES = $(top_builddir)/lib/libipmitool.la
+am_libintf_serial_la_OBJECTS = serial_terminal.lo serial_basic.lo
+libintf_serial_la_OBJECTS = $(am_libintf_serial_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+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 = $(libintf_serial_la_SOURCES)
+DIST_SOURCES = $(libintf_serial_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+ARCH = @ARCH@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASEDIR = @BASEDIR@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTRO = @DISTRO@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTF_BMC = @INTF_BMC@
+INTF_BMC_LIB = @INTF_BMC_LIB@
+INTF_DUMMY = @INTF_DUMMY@
+INTF_DUMMY_LIB = @INTF_DUMMY_LIB@
+INTF_FREE = @INTF_FREE@
+INTF_FREE_LIB = @INTF_FREE_LIB@
+INTF_IMB = @INTF_IMB@
+INTF_IMB_LIB = @INTF_IMB_LIB@
+INTF_LAN = @INTF_LAN@
+INTF_LANPLUS = @INTF_LANPLUS@
+INTF_LANPLUS_LIB = @INTF_LANPLUS_LIB@
+INTF_LAN_LIB = @INTF_LAN_LIB@
+INTF_LIPMI = @INTF_LIPMI@
+INTF_LIPMI_LIB = @INTF_LIPMI_LIB@
+INTF_OPEN = @INTF_OPEN@
+INTF_OPEN_LIB = @INTF_OPEN_LIB@
+INTF_SERIAL = @INTF_SERIAL@
+INTF_SERIAL_LIB = @INTF_SERIAL_LIB@
+IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OS = @OS@
+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@
+POW_LIB = @POW_LIB@
+PSTAMP = @PSTAMP@
+RANLIB = @RANLIB@
+RPMBUILD = @RPMBUILD@
+RPM_RELEASE = @RPM_RELEASE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_configure_args = @ac_configure_args@
+ac_ct_AR = @ac_ct_AR@
+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@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+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@
+MAINTAINERCLEANFILES = Makefile.in
+INCLUDES = -I$(top_srcdir)/include
+EXTRA_LTLIBRARIES = libintf_serial.la
+noinst_LTLIBRARIES = @INTF_SERIAL_LIB@
+libintf_serial_la_LIBADD = $(top_builddir)/lib/libipmitool.la
+libintf_serial_la_SOURCES = serial_terminal.c serial_basic.c
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(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) --foreign src/plugins/serial/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/plugins/serial/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: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libintf_serial.la: $(libintf_serial_la_OBJECTS) $(libintf_serial_la_DEPENDENCIES) $(EXTRA_libintf_serial_la_DEPENDENCIES)
+ $(LINK) $(libintf_serial_la_OBJECTS) $(libintf_serial_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serial_basic.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serial_terminal.Plo@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 $(LTLIBRARIES)
+installdirs:
+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:
+ 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:
+
+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."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ 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-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:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES 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-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
+
+
+# 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:
diff --git a/src/plugins/serial/serial_basic.c b/src/plugins/serial/serial_basic.c
new file mode 100644
index 0000000..5f4b926
--- /dev/null
+++ b/src/plugins/serial/serial_basic.c
@@ -0,0 +1,1029 @@
+/*
+ * Copyright (c) 2012 Pigeon Point Systems. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Pigeon Point Systems nor the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * PIGEON POINT SYSTEMS ("PPS") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * PPS OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF PPS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/* Serial Interface, Basic Mode plugin. */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/poll.h>
+#include <termios.h>
+
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_intf.h>
+#include <ipmitool/helper.h>
+#include <ipmitool/log.h>
+
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#define SERIAL_BM_MAX_MSG_SIZE 47
+#define SERIAL_BM_MAX_RQ_SIZE 33 /* 40 - 7 */
+#define SERIAL_BM_MAX_RS_SIZE 32 /* 40 - 8 */
+#define SERIAL_BM_TIMEOUT 5
+#define SERIAL_BM_RETRY_COUNT 5
+#define SERIAL_BM_MAX_BUFFER_SIZE 250
+
+#define BM_START 0xA0
+#define BM_STOP 0xA5
+#define BM_HANDSHAKE 0xA6
+#define BM_ESCAPE 0xAA
+
+/*
+ * IPMB message header
+ */
+struct ipmb_msg_hdr {
+ unsigned char rsSA;
+ unsigned char netFn; /* NET FN | RS LUN */
+ unsigned char csum1;
+ unsigned char rqSA;
+ unsigned char rqSeq; /* RQ SEQ | RQ LUN */
+ unsigned char cmd;
+ unsigned char data[0];
+};
+
+/*
+ * Send Message command request for IPMB-format
+ */
+struct ipmi_send_message_rq {
+ unsigned char channel;
+ struct ipmb_msg_hdr msg;
+};
+
+/*
+ * Get Message command response for IPMB-format
+ */
+struct ipmi_get_message_rp {
+ unsigned char completion;
+ unsigned char channel;
+ unsigned char netFn;
+ unsigned char csum1;
+ unsigned char rsSA;
+ unsigned char rqSeq;
+ unsigned char cmd;
+ unsigned char data[0];
+};
+
+/*
+ * State for the received message
+ */
+enum {
+ MSG_NONE,
+ MSG_IN_PROGRESS,
+ MSG_DONE
+};
+
+/*
+ * Message parsing context
+ */
+struct serial_bm_parse_ctx{
+ int state;
+ uint8_t * msg;
+ size_t msg_len;
+ size_t max_len;
+ int escape;
+};
+
+/*
+ * Receiving context
+ */
+struct serial_bm_recv_ctx {
+ char buffer[SERIAL_BM_MAX_BUFFER_SIZE];
+ size_t buffer_size;
+ size_t max_buffer_size;
+};
+
+/*
+ * Sending context
+ */
+struct serial_bm_request_ctx {
+ uint8_t rsSA;
+ uint8_t netFn;
+ uint8_t rqSA;
+ uint8_t rqSeq;
+ uint8_t cmd;
+};
+
+/*
+ * Table of supported baud rates
+ */
+static const struct {
+ int baudinit;
+ int baudrate;
+} rates[] = {
+ { B2400, 2400 },
+ { B9600, 9600 },
+ { B19200, 19200 },
+ { B38400, 38400 },
+ { B57600, 57600 },
+ { B115200, 115200 },
+ { B230400, 230400 },
+#ifdef B460800
+ { B460800, 460800 },
+#endif
+};
+
+/*
+ * Table of special characters
+ */
+static const struct {
+ uint8_t character;
+ uint8_t escape;
+} characters[] = {
+ { BM_START, 0xB0 }, /* start */
+ { BM_STOP, 0xB5 }, /* stop */
+ { BM_HANDSHAKE, 0xB6 }, /* packet handshake */
+ { BM_ESCAPE, 0xBA }, /* data escape */
+ { 0x1B, 0x3B } /* escape */
+};
+
+static int is_system;
+
+/*
+ * Setup serial interface
+ */
+static int
+serial_bm_setup(struct ipmi_intf * intf)
+{
+ intf->session = malloc(sizeof(struct ipmi_session));
+ if (intf->session == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return -1;
+ }
+ memset(intf->session, 0, sizeof(struct ipmi_session));
+
+ /* setup default LAN maximum request and response sizes */
+ intf->max_request_data_size = SERIAL_BM_MAX_RQ_SIZE;
+ intf->max_response_data_size = SERIAL_BM_MAX_RS_SIZE;
+ return 0;
+}
+
+/*
+ * Open serial interface
+ */
+static int
+serial_bm_open(struct ipmi_intf * intf)
+{
+ struct termios ti;
+ unsigned int rate = 9600;
+ char *p;
+ int i;
+
+ if (!intf->devfile) {
+ lprintf(LOG_ERR, "Serial device is not specified");
+ return -1;
+ }
+
+ is_system = 0;
+
+ /* check if baud rate is specified */
+ if ((p = strchr(intf->devfile, ':'))) {
+ char * pp;
+
+ /* separate device name from baud rate */
+ *p++ = '\0';
+
+ /* check for second colon */
+ if ((pp = strchr(p, ':'))) {
+ /* this is needed to normally acquire baud rate */
+ *pp++ = '\0';
+
+ /* check if it is a system interface */
+ if (pp[0] == 'S' || pp[0] == 's') {
+ is_system = 1;
+ }
+ }
+
+ if (str2uint(p, &rate)) {
+ lprintf(LOG_ERR, "Invalid baud rate specified\n");
+ return -1;
+ }
+ }
+
+ intf->fd = open(intf->devfile, O_RDWR | O_NONBLOCK, 0);
+ if (intf->fd < 0) {
+ lperror(LOG_ERR, "Could not open device at %s", intf->devfile);
+ return -1;
+ }
+
+ for (i = 0; i < sizeof(rates) / sizeof(rates[0]); i++) {
+ if (rates[i].baudrate == rate) {
+ break;
+ }
+ }
+ if (i >= sizeof(rates) / sizeof(rates[0])) {
+ lprintf(LOG_ERR, "Unsupported baud rate %i specified", rate);
+ return -1;
+ }
+
+ tcgetattr(intf->fd, &ti);
+
+ cfsetispeed(&ti, rates[i].baudinit);
+ cfsetospeed(&ti, rates[i].baudinit);
+
+ /* 8N1 */
+ ti.c_cflag &= ~PARENB;
+ ti.c_cflag &= ~CSTOPB;
+ ti.c_cflag &= ~CSIZE;
+ ti.c_cflag |= CS8;
+
+ /* enable the receiver and set local mode */
+ ti.c_cflag |= (CLOCAL | CREAD);
+
+ /* no flow control */
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | INPCK | ISTRIP
+ | IXON | IXOFF | IXANY);
+#ifdef IUCLC
+ /* Only disable uppercase-to-lowercase mapping on input for
+ platforms supporting the flag. */
+ ti.c_iflag &= ~(IUCLC);
+#endif
+
+
+ ti.c_oflag &= ~(OPOST);
+ ti.c_lflag &= ~(ICANON | ISIG | ECHO | ECHONL | NOFLSH);
+
+ /* set the new options for the port with flushing */
+ tcsetattr(intf->fd, TCSAFLUSH, &ti);
+
+ if (intf->session->timeout == 0)
+ intf->session->timeout = SERIAL_BM_TIMEOUT;
+ if (intf->session->retry == 0)
+ intf->session->retry = SERIAL_BM_RETRY_COUNT;
+
+ intf->opened = 1;
+
+ return 0;
+}
+
+/*
+ * Close serial interface
+ */
+static void
+serial_bm_close(struct ipmi_intf * intf)
+{
+ if (intf->opened) {
+ close(intf->fd);
+ intf->fd = -1;
+ }
+
+ if (intf->session) {
+ free(intf->session);
+ intf->session = NULL;
+ }
+
+ intf->opened = 0;
+}
+
+/*
+ * Allocate sequence number for tracking
+ */
+static uint8_t
+serial_bm_alloc_seq(void)
+{
+ static uint8_t seq = 0;
+ if (++seq == 64) {
+ seq = 0;
+ }
+ return seq;
+}
+
+/*
+ * Flush the buffers
+ */
+static int
+serial_bm_flush(struct ipmi_intf * intf)
+{
+#if defined(TCFLSH)
+ return ioctl(intf->fd, TCFLSH, TCIOFLUSH);
+#elif defined(TIOCFLUSH)
+ return ioctl(intf->fd, TIOCFLUSH);
+#else
+# error "unsupported platform, missing flush support (TCFLSH/TIOCFLUSH)"
+#endif
+}
+
+/*
+ * Return escaped character for the given one
+ */
+static inline uint8_t
+serial_bm_get_escaped_char(uint8_t c)
+{
+ int i;
+
+ for (i = 0; i < 5; i++) {
+ if (characters[i].character == c) {
+ return characters[i].escape;
+ }
+ }
+
+ return c;
+}
+
+/*
+ * Return unescaped character for the given one
+ */
+static inline uint8_t
+serial_bm_get_unescaped_char(uint8_t c)
+{
+ int i;
+
+ for (i = 0; i < 5; i++) {
+ if (characters[i].escape == c) {
+ return characters[i].character;
+ }
+ }
+
+ return c;
+}
+
+/*
+ * Send message to serial port
+ */
+static int
+serial_bm_send_msg(struct ipmi_intf * intf, uint8_t * msg, int msg_len)
+{
+ int i, size, tmp = 0;
+ uint8_t * buf, * data;
+
+ if (verbose > 3) {
+ fprintf(stderr, "Sending request:\n");
+ fprintf(stderr, " rsSA = 0x%x\n", msg[0]);
+ fprintf(stderr, " NetFN/rsLUN = 0x%x\n", msg[1]);
+ fprintf(stderr, " rqSA = 0x%x\n", msg[3]);
+ fprintf(stderr, " rqSeq/rqLUN = 0x%x\n", msg[4]);
+ fprintf(stderr, " cmd = 0x%x\n", msg[5]);
+ if (msg_len > 7) {
+ fprintf(stderr, " data_len = %d\n", msg_len - 7);
+ fprintf(stderr, " data = %s\n",
+ buf2str(msg + 6, msg_len - 7));
+ }
+ }
+
+ if (verbose > 4) {
+ fprintf(stderr, "Message data:\n");
+ fprintf(stderr, " %s\n", buf2str(msg, msg_len));
+ }
+
+ /* calculate escaped characters number */
+ for (i = 0; i < msg_len; i++) {
+ if (serial_bm_get_escaped_char(msg[i]) != msg[i]) {
+ tmp++;
+ }
+ }
+
+ /* calculate required buffer size */
+ size = msg_len + tmp + 2;
+
+ /* allocate buffer for output data */
+ buf = data = (uint8_t *) alloca(size);
+
+ if (!buf) {
+ lperror(LOG_ERR, "ipmitool: alloca error");
+ return -1;
+ }
+
+ /* start character */
+ *buf++ = 0xA0;
+
+ for (i = 0; i < msg_len; i++) {
+ tmp = serial_bm_get_escaped_char(msg[i]);
+ if (tmp != msg[i]) {
+ *buf++ = 0xAA;
+ }
+
+ *buf++ = tmp;
+ }
+
+ /* stop character */
+ *buf++ = 0xA5;
+
+ if (verbose > 5) {
+ fprintf(stderr, "Sent serial data:\n %s\n", buf2str(data, size));
+ }
+
+ /* write data to serial port */
+ tmp = write(intf->fd, data, size);
+ if (tmp <= 0) {
+ lperror(LOG_ERR, "ipmitool: write error");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * This function waits for incoming data
+ */
+static int
+serial_bm_wait_for_data(struct ipmi_intf * intf)
+{
+ int n;
+ struct pollfd pfd;
+
+ pfd.fd = intf->fd;
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+
+ n = poll(&pfd, 1, intf->session->timeout*1000);
+ if (n < 0) {
+ lperror(LOG_ERR, "Poll for serial data failed");
+ return -1;
+ } else if (!n) {
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * This function parses incoming data in basic mode format to IPMB message
+ */
+static int
+serial_bm_parse_buffer(const uint8_t * data, int data_len,
+ struct serial_bm_parse_ctx * ctx)
+{
+ int i, tmp;
+
+ for (i = 0; i < data_len; i++) {
+ /* check for start of new message */
+ if (data[i] == BM_START) {
+ ctx->state = MSG_IN_PROGRESS;
+ ctx->escape = 0;
+ ctx->msg_len = 0;
+ /* check if message is not started */
+ } else if (ctx->state != MSG_IN_PROGRESS) {
+ /* skip character */
+ continue;
+ /* continue escape sequence */
+ } else if (ctx->escape) {
+ /* get original character */
+ tmp = serial_bm_get_unescaped_char(data[i]);
+
+ /* check if not special character */
+ if (tmp == data[i]) {
+ lprintf(LOG_ERR, "ipmitool: bad response");
+ /* reset message state */
+ ctx->state = MSG_NONE;
+ continue;
+ }
+
+ /* check message length */
+ if (ctx->msg_len >= ctx->max_len) {
+ lprintf(LOG_ERR, "ipmitool: response is too long");
+ /* reset message state */
+ ctx->state = MSG_NONE;
+ continue;
+ }
+
+ /* add parsed character */
+ ctx->msg[ctx->msg_len++] = tmp;
+
+ /* clear escape flag */
+ ctx->escape = 0;
+ /* check for escape character */
+ } else if (data[i] == BM_ESCAPE) {
+ ctx->escape = 1;
+ continue;
+ /* check for stop character */
+ } else if (data[i] == BM_STOP) {
+ ctx->state = MSG_DONE;
+ return i + 1;
+ /* check for packet handshake character */
+ } else if (data[i] == BM_HANDSHAKE) {
+ /* just skip it */
+ continue;
+ } else {
+ /* check message length */
+ if (ctx->msg_len >= ctx->max_len) {
+ lprintf(LOG_ERR, "ipmitool: response is too long");
+ return -1;
+ }
+
+ /* add parsed character */
+ ctx->msg[ctx->msg_len++] = data[i];
+ }
+ }
+
+ /* return number of parsed characters */
+ return i;
+}
+
+/*
+ * Read and parse data from serial port
+ */
+static int
+serial_bm_recv_msg(struct ipmi_intf * intf,
+ struct serial_bm_recv_ctx * recv_ctx,
+ uint8_t * msg_data, size_t msg_len)
+{
+ struct serial_bm_parse_ctx parse_ctx;
+ int rv;
+
+ parse_ctx.state = MSG_NONE;
+ parse_ctx.msg = msg_data;
+ parse_ctx.max_len = msg_len;
+
+ do {
+ /* wait for data in the port */
+ if (serial_bm_wait_for_data(intf)) {
+ return 0;
+ }
+
+ /* read data into buffer */
+ rv = read(intf->fd, recv_ctx->buffer + recv_ctx->buffer_size,
+ recv_ctx->max_buffer_size - recv_ctx->buffer_size);
+
+ if (rv < 0) {
+ lperror(LOG_ERR, "ipmitool: read error");
+ return -1;
+ }
+
+ if (verbose > 5) {
+ fprintf(stderr, "Received serial data:\n %s\n",
+ buf2str(recv_ctx->buffer + recv_ctx->buffer_size, rv));
+ }
+
+ /* increment buffer size */
+ recv_ctx->buffer_size += rv;
+
+ /* parse buffer */
+ rv = serial_bm_parse_buffer(recv_ctx->buffer,
+ recv_ctx->buffer_size, &parse_ctx);
+
+ if (rv < recv_ctx->buffer_size) {
+ /* move non-parsed part of the buffer to the beginning */
+ memmove(recv_ctx->buffer, recv_ctx->buffer + rv,
+ recv_ctx->buffer_size - rv);
+ }
+
+ /* decrement buffer size */
+ recv_ctx->buffer_size -= rv;
+ } while (parse_ctx.state != MSG_DONE);
+
+ if (verbose > 4) {
+ printf("Received message:\n %s\n",
+ buf2str(msg_data, parse_ctx.msg_len));
+ }
+
+ /* received a message */
+ return parse_ctx.msg_len;
+}
+
+/*
+ * Build IPMB message to be transmitted
+ */
+static int
+serial_bm_build_msg(const struct ipmi_intf * intf,
+ const struct ipmi_rq * req, uint8_t * msg, size_t max_len,
+ struct serial_bm_request_ctx * ctx, int * msg_len
+ )
+{
+ uint8_t * data = msg, seq;
+ struct ipmb_msg_hdr * hdr = (struct ipmb_msg_hdr *) msg;
+ struct ipmi_send_message_rq * inner_rq = NULL, * outer_rq = NULL;
+ int bridging_level;
+
+ /* acquire bridging level */
+ if (intf->target_addr && intf->target_addr != intf->my_addr) {
+ if (intf->transit_addr != 0) {
+ bridging_level = 2;
+ } else {
+ bridging_level = 1;
+ }
+ } else {
+ bridging_level = 0;
+ }
+
+ /* check overall packet length */
+ if(req->msg.data_len + 7 + bridging_level * 8 > max_len) {
+ lprintf(LOG_ERR, "ipmitool: Message data is too long");
+ return -1;
+ }
+
+ /* allocate new sequence number */
+ seq = serial_bm_alloc_seq() << 2;
+
+ if (bridging_level) {
+ /* compose send message request */
+ hdr->netFn = 0x18;
+ hdr->cmd = 0x34;
+
+ /* set pointer to send message request data */
+ outer_rq = (struct ipmi_send_message_rq *) (hdr + 1);
+
+ /* compose the outer send message request */
+ if (bridging_level == 2) {
+ outer_rq->channel = intf->transit_channel | 0x40;
+ outer_rq->msg.rsSA = intf->transit_addr;
+ outer_rq->msg.netFn = 0x18;
+ outer_rq->msg.csum1 = -(outer_rq->msg.rsSA + outer_rq->msg.netFn);
+ outer_rq->msg.rqSA = intf->my_addr;
+ outer_rq->msg.rqSeq = seq;
+ outer_rq->msg.cmd = 0x34;
+
+ /* inner send message request is further */
+ inner_rq = (outer_rq + 1);
+ } else {
+ /* there is only outer send message reuest */
+ inner_rq = outer_rq;
+ }
+
+ /* compose the inner send message request */
+ inner_rq->channel = intf->target_channel | 0x40;
+ inner_rq->msg.rsSA = intf->target_addr;
+ inner_rq->msg.netFn = (req->msg.netfn << 2) | req->msg.lun;
+ inner_rq->msg.csum1 = -(inner_rq->msg.rsSA + inner_rq->msg.netFn);
+ inner_rq->msg.rqSA = intf->my_addr;
+ inner_rq->msg.rqSeq = seq;
+ inner_rq->msg.cmd = req->msg.cmd;
+
+ /* check if interface is the system one */
+ if (is_system) {
+ /* need response to LUN 2 */
+ outer_rq->msg.rqSeq |= 2;
+
+ /* do not track response */
+ outer_rq->channel &= ~0x40;
+
+ /* restore BMC SA if bridging not to primary IPMB channel */
+ if (outer_rq->channel) {
+ outer_rq->msg.rqSA = IPMI_BMC_SLAVE_ADDR;
+ }
+ }
+
+ /* fill-in the second context */
+ ctx[1].rsSA = outer_rq->msg.rsSA;
+ ctx[1].netFn = outer_rq->msg.netFn;
+ ctx[1].rqSA = outer_rq->msg.rqSA;
+ ctx[1].rqSeq = outer_rq->msg.rqSeq;
+ ctx[1].cmd = outer_rq->msg.cmd;
+
+ /* move write pointer */
+ msg = (uint8_t *)(inner_rq + 1);
+ } else {
+ /* compose direct request */
+ hdr->netFn = (req->msg.netfn << 2) | req->msg.lun;
+ hdr->cmd = req->msg.cmd;
+
+ /* move write pointer */
+ msg = (uint8_t *)(hdr + 1);
+ }
+
+ /* fill-in the rest header fields */
+ hdr->rsSA = IPMI_BMC_SLAVE_ADDR;
+ hdr->csum1 = -(hdr->rsSA + hdr->netFn);
+ hdr->rqSA = IPMI_REMOTE_SWID;
+ hdr->rqSeq = seq;
+
+ /* fill-in the first context */
+ ctx[0].rsSA = hdr->rsSA;
+ ctx[0].netFn = hdr->netFn;
+ ctx[0].rqSA = hdr->rqSA;
+ ctx[0].rqSeq = hdr->rqSeq;
+ ctx[0].cmd = hdr->cmd;
+
+ /* write request data */
+ memcpy(msg, req->msg.data, req->msg.data_len);
+
+ /* move write pointer */
+ msg += req->msg.data_len;
+
+ if (bridging_level) {
+ /* write inner message checksum */
+ *msg++ = ipmi_csum(&inner_rq->msg.rqSA, req->msg.data_len + 3);
+
+ /* check for double bridging */
+ if (bridging_level == 2) {
+ /* write outer message checksum */
+ *msg++ = ipmi_csum(&outer_rq->msg.rqSA, 4);
+ }
+
+ /* write overall message checksum */
+ *msg++ = ipmi_csum(&hdr->rqSA, 4);
+ } else {
+ /* write overall message checksum */
+ *msg++ = ipmi_csum(&hdr->rqSA, req->msg.data_len + 3);
+ }
+
+ /* save message length */
+ *msg_len = msg - data;
+
+ /* return bridging level */
+ return bridging_level;
+}
+
+/*
+ * Wait for request response
+ */
+static int
+serial_bm_wait_response(struct ipmi_intf * intf,
+ struct serial_bm_request_ctx * req_ctx, struct serial_bm_recv_ctx * read_ctx,
+ uint8_t * msg, size_t max_len)
+{
+ struct ipmb_msg_hdr * hdr = (struct ipmb_msg_hdr *) msg;
+ int msg_len, netFn, rqSeq;
+
+ /* receive and match message */
+ while ((msg_len = serial_bm_recv_msg(intf, read_ctx, msg, max_len)) > 0) {
+ /* validate message size */
+ if (msg_len < 8) {
+ lprintf(LOG_ERR, "ipmitool: response is too short");
+ continue;
+ }
+
+ /* validate checksum 1 */
+ if (ipmi_csum(msg, 3)) {
+ lprintf(LOG_ERR, "ipmitool: bad checksum 1");
+ continue;
+ }
+
+ /* validate checksum 2 */
+ if (ipmi_csum(msg + 3, msg_len - 3)) {
+ lprintf(LOG_ERR, "ipmitool: bad checksum 2");
+ continue;
+ }
+
+ /* swap requester and responder LUNs */
+ netFn = ((req_ctx->netFn|4) & ~3) | (req_ctx->rqSeq & 3);
+ rqSeq = (req_ctx->rqSeq & ~3) | (req_ctx->netFn & 3);
+
+ /* check for the waited response */
+ if (hdr->rsSA == req_ctx->rqSA
+ && hdr->netFn == netFn
+ && hdr->rqSA == req_ctx->rsSA
+ && hdr->rqSeq == rqSeq
+ && hdr->cmd == req_ctx->cmd) {
+ /* check if something new has been parsed */
+ if (verbose > 3) {
+ fprintf(stderr, "Got response:\n");
+ fprintf(stderr, " rsSA = 0x%x\n", msg[0]);
+ fprintf(stderr, " NetFN/rsLUN = 0x%x\n", msg[1]);
+ fprintf(stderr, " rqSA = 0x%x\n", msg[3]);
+ fprintf(stderr, " rqSeq/rqLUN = 0x%x\n", msg[4]);
+ fprintf(stderr, " cmd = 0x%x\n", msg[5]);
+ fprintf(stderr, " completion code = 0x%x\n", msg[6]);
+ if (msg_len > 8) {
+ fprintf(stderr, " data_len = %d\n", msg_len - 8);
+ fprintf(stderr, " data = %s\n",
+ buf2str(msg + 7, msg_len - 8));
+ }
+ }
+
+ /* copy only completion and response data */
+ memmove(msg, hdr + 1, msg_len - sizeof (*hdr) - 1);
+
+ /* update message length */
+ msg_len -= sizeof (*hdr) + 1;
+
+ /* the waited one */
+ break;
+ }
+ }
+
+ return msg_len;
+}
+
+/*
+ * Get message from receive message queue
+ */
+static int
+serial_bm_get_message(struct ipmi_intf * intf,
+ struct serial_bm_request_ctx * req_ctx,
+ struct serial_bm_recv_ctx * read_ctx,
+ uint8_t * msg, size_t max_len)
+{
+ uint8_t data[SERIAL_BM_MAX_MSG_SIZE];
+ struct serial_bm_request_ctx tmp_ctx;
+ struct ipmi_get_message_rp * rp = (struct ipmi_get_message_rp *) data;
+ struct ipmb_msg_hdr * hdr = (struct ipmb_msg_hdr *) data;
+ clock_t start, tm;
+ int rv, netFn, rqSeq;
+
+ start = clock();
+
+ do {
+ /* fill-in request context */
+ tmp_ctx.rsSA = IPMI_BMC_SLAVE_ADDR;
+ tmp_ctx.netFn = 0x18;
+ tmp_ctx.rqSA = IPMI_REMOTE_SWID;
+ tmp_ctx.rqSeq = serial_bm_alloc_seq() << 2;
+ tmp_ctx.cmd = 0x33;
+
+ /* fill-in request data */
+ hdr->rsSA = tmp_ctx.rsSA;
+ hdr->netFn = tmp_ctx.netFn;
+ hdr->csum1 = ipmi_csum(data, 2);
+ hdr->rqSA = tmp_ctx.rqSA;
+ hdr->rqSeq = tmp_ctx.rqSeq;
+ hdr->cmd = tmp_ctx.cmd;
+ hdr->data[0] = ipmi_csum(&hdr->rqSA, 3);
+
+ /* send request */
+ serial_bm_flush(intf);
+ serial_bm_send_msg(intf, data, 7);
+
+ /* wait for response */
+ rv = serial_bm_wait_response(intf, &tmp_ctx, read_ctx,
+ data, sizeof (data));
+
+ /* check for IO error or timeout */
+ if (rv <= 0) {
+ return rv;
+ }
+
+ /* check completion code */
+ if (rp->completion == 0) {
+ /* swap requester and responder LUNs */
+ netFn = ((req_ctx->netFn|4) & ~3) | (req_ctx->rqSeq & 3);
+ rqSeq = (req_ctx->rqSeq & ~3) | (req_ctx->netFn & 3);
+
+ /* check for the waited response */
+ if (rp->netFn == netFn
+ && rp->rsSA == req_ctx->rsSA
+ && rp->rqSeq == rqSeq
+ && rp->cmd == req_ctx->cmd) {
+ /* copy the rest of message */
+ memcpy(msg, rp->data, rv - sizeof (*rp) - 1);
+ return rv - sizeof (*rp) - 1;
+ }
+ } else if (rp->completion != 0x80) {
+ return 0;
+ }
+
+ tm = clock() - start;
+
+ tm /= CLOCKS_PER_SEC;
+ } while (tm < intf->session->timeout);
+
+ return 0;
+}
+
+static struct ipmi_rs *
+serial_bm_send_request(struct ipmi_intf * intf, struct ipmi_rq * req)
+{
+ static struct ipmi_rs rsp;
+ uint8_t msg[SERIAL_BM_MAX_MSG_SIZE], * resp = msg;
+ struct serial_bm_request_ctx req_ctx[3];
+ struct serial_bm_recv_ctx read_ctx;
+ int retry, rv, msg_len, bridging_level;
+
+ if (!intf->opened && intf->open && intf->open(intf) < 0) {
+ return NULL;
+ }
+
+ /* reset receive context */
+ read_ctx.buffer_size = 0;
+ read_ctx.max_buffer_size = SERIAL_BM_MAX_BUFFER_SIZE;
+
+ /* Send the message and receive the answer */
+ for (retry = 0; retry < intf->session->retry; retry++) {
+ /* build output message */
+ bridging_level = serial_bm_build_msg(intf, req, msg,
+ sizeof (msg), req_ctx, &msg_len);
+ if (msg_len < 0) {
+ return NULL;
+ }
+
+ /* send request */
+ serial_bm_flush(intf);
+ serial_bm_send_msg(intf, msg, msg_len);
+
+ /* wait for response */
+ rv = serial_bm_wait_response(intf, &req_ctx[0],
+ &read_ctx, msg, sizeof (msg));
+
+ /* check for IO error */
+ if (rv < 0) {
+ return NULL;
+ }
+
+ /* check for timeout */
+ if (rv == 0) {
+ continue;
+ }
+
+ /* check for bridging */
+ if (bridging_level && msg[0] == 0) {
+ /* in the case of payload interface we check receive message queue */
+ if (is_system) {
+ /* check message flags */
+ rv = serial_bm_get_message(intf, &req_ctx[1],
+ &read_ctx, msg, sizeof (msg));
+
+ /* check for IO error */
+ if (rv < 0) {
+ return NULL;
+ }
+
+ /* check for timeout */
+ if (rv == 0) {
+ continue;
+ }
+ /* check if response for inner request is not encapsulated */
+ } else if (rv == 1) {
+ /* wait for response for inner request */
+ rv = serial_bm_wait_response(intf, &req_ctx[0],
+ &read_ctx, msg, sizeof (msg));
+
+ /* check for IO error */
+ if (rv < 0) {
+ return NULL;
+ }
+
+ /* check for timeout */
+ if (rv == 0) {
+ continue;
+ }
+ } else {
+ /* skip outer level header */
+ resp = msg + 7;
+ /* decrement response size */
+ rv -= 8;
+ }
+
+ /* check response size */
+ if (resp[0] == 0 && bridging_level == 2 && rv < 8) {
+ lprintf(LOG_ERR, "ipmitool: Message response is too short");
+ /* invalid message length */
+ return NULL;
+ }
+ }
+
+ /* check for double bridging */
+ if (bridging_level == 2 && resp[0] == 0) {
+ /* get completion code */
+ rsp.ccode = resp[7];
+ rsp.data_len = rv - 9;
+ memcpy(rsp.data, resp + 8, rsp.data_len);
+ } else {
+ rsp.ccode = resp[0];
+ rsp.data_len = rv - 1;
+ memcpy(rsp.data, resp + 1, rsp.data_len);
+ }
+
+ /* return response */
+ return &rsp;
+ }
+
+ /* no valid response */
+ return NULL;
+}
+
+int
+serial_bm_set_my_addr(struct ipmi_intf * intf, uint8_t addr)
+{
+ intf->my_addr = addr;
+ return 0;
+}
+
+/*
+ * Serial BM interface
+ */
+struct ipmi_intf ipmi_serial_bm_intf = {
+ name: "serial-basic",
+ desc: "Serial Interface, Basic Mode",
+ setup: serial_bm_setup,
+ open: serial_bm_open,
+ close: serial_bm_close,
+ sendrecv: serial_bm_send_request,
+ set_my_addr:serial_bm_set_my_addr
+};
diff --git a/src/plugins/serial/serial_terminal.c b/src/plugins/serial/serial_terminal.c
new file mode 100644
index 0000000..41d3753
--- /dev/null
+++ b/src/plugins/serial/serial_terminal.c
@@ -0,0 +1,919 @@
+/*
+ * Copyright (c) 2007-2012 Pigeon Point Systems. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Pigeon Point Systems nor the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind.
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
+ * PIGEON POINT SYSTEMS ("PPS") AND ITS LICENSORS SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
+ * PPS OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF PPS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/* Serial Interface, Terminal Mode plugin. */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/poll.h>
+#include <termios.h>
+
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_intf.h>
+#include <ipmitool/helper.h>
+#include <ipmitool/log.h>
+
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#define IPMI_SERIAL_TIMEOUT 5
+#define IPMI_SERIAL_RETRY 5
+#define IPMI_SERIAL_MAX_RESPONSE 256
+
+/*
+ * Terminal Mode interface is required to support 40 byte transactions.
+ */
+#define IPMI_SERIAL_MAX_RQ_SIZE 37 /* 40 - 3 */
+#define IPMI_SERIAL_MAX_RS_SIZE 36 /* 40 - 4 */
+
+/*
+ * IPMB message header
+ */
+struct ipmb_msg_hdr {
+ unsigned char rsSA;
+ unsigned char netFn; /* NET FN | RS LUN */
+ unsigned char csum1;
+ unsigned char rqSA;
+ unsigned char rqSeq; /* RQ SEQ | RQ LUN */
+ unsigned char cmd;
+ unsigned char data[0];
+};
+
+/*
+ * Send Message command request for IPMB-format
+ */
+struct ipmi_send_message_rq {
+ unsigned char channel;
+ struct ipmb_msg_hdr msg;
+};
+
+/*
+ * Get Message command response for IPMB-format
+ */
+struct ipmi_get_message_rp {
+ unsigned char completion;
+ unsigned char channel;
+ unsigned char netFn;
+ unsigned char csum1;
+ unsigned char rsSA;
+ unsigned char rqSeq;
+ unsigned char cmd;
+ unsigned char data[0];
+};
+
+/*
+ * Terminal mode message header
+ */
+struct serial_term_hdr {
+ unsigned char netFn;
+ unsigned char seq;
+ unsigned char cmd;
+};
+
+/*
+ * Sending context
+ */
+struct serial_term_request_ctx {
+ uint8_t netFn;
+ uint8_t sa;
+ uint8_t seq;
+ uint8_t cmd;
+};
+
+/*
+ * Table of supported baud rates
+ */
+static const struct {
+ int baudinit;
+ int baudrate;
+} rates[] = {
+ { B2400, 2400 },
+ { B9600, 9600 },
+ { B19200, 19200 },
+ { B38400, 38400 },
+ { B57600, 57600 },
+ { B115200, 115200 },
+ { B230400, 230400 },
+#ifdef B460800
+ { B460800, 460800 },
+#endif
+};
+
+static int is_system;
+
+static int
+ipmi_serial_term_open(struct ipmi_intf * intf)
+{
+ struct termios ti;
+ unsigned int rate = 9600;
+ char *p;
+ int i;
+
+ if (!intf->devfile) {
+ lprintf(LOG_ERR, "Serial device is not specified");
+ return -1;
+ }
+
+ is_system = 0;
+
+ /* check if baud rate is specified */
+ if ((p = strchr(intf->devfile, ':'))) {
+ char * pp;
+
+ /* separate device name from baud rate */
+ *p++ = '\0';
+
+ /* check for second colon */
+ if ((pp = strchr(p, ':'))) {
+ /* this is needed to normally acquire baud rate */
+ *pp++ = '\0';
+
+ /* check if it is a system interface */
+ if (pp[0] == 'S' || pp[0] == 's') {
+ is_system = 1;
+ }
+ }
+
+ if (str2uint(p, &rate)) {
+ lprintf(LOG_ERR, "Invalid baud rate specified\n");
+ return -1;
+ }
+ }
+
+ intf->fd = open(intf->devfile, O_RDWR | O_NONBLOCK, 0);
+ if (intf->fd < 0) {
+ lperror(LOG_ERR, "Could not open device at %s", intf->devfile);
+ return -1;
+ }
+
+ for (i = 0; i < sizeof(rates) / sizeof(rates[0]); i++) {
+ if (rates[i].baudrate == rate) {
+ break;
+ }
+ }
+ if (i >= sizeof(rates) / sizeof(rates[0])) {
+ lprintf(LOG_ERR, "Unsupported baud rate %i specified", rate);
+ return -1;
+ }
+
+ tcgetattr(intf->fd, &ti);
+
+ cfsetispeed(&ti, rates[i].baudinit);
+ cfsetospeed(&ti, rates[i].baudinit);
+
+ /* 8N1 */
+ ti.c_cflag &= ~PARENB;
+ ti.c_cflag &= ~CSTOPB;
+ ti.c_cflag &= ~CSIZE;
+ ti.c_cflag |= CS8;
+
+ /* enable the receiver and set local mode */
+ ti.c_cflag |= (CLOCAL | CREAD);
+
+ /* no flow control */
+ ti.c_cflag &= ~CRTSCTS;
+ ti.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | INPCK | ISTRIP
+ | IXON | IXOFF | IXANY);
+#ifdef IUCLC
+ /* Only disable uppercase-to-lowercase mapping on input for
+ platforms supporting the flag. */
+ ti.c_iflag &= ~(IUCLC);
+#endif
+
+ ti.c_oflag &= ~(OPOST);
+ ti.c_lflag &= ~(ICANON | ISIG | ECHO | ECHONL | NOFLSH);
+
+ /* set the new options for the port with flushing */
+ tcsetattr(intf->fd, TCSAFLUSH, &ti);
+
+ if (intf->session->timeout == 0)
+ intf->session->timeout = IPMI_SERIAL_TIMEOUT;
+ if (intf->session->retry == 0)
+ intf->session->retry = IPMI_SERIAL_RETRY;
+
+ intf->opened = 1;
+
+ return 0;
+}
+
+static void
+ipmi_serial_term_close(struct ipmi_intf * intf)
+{
+ if (intf->opened) {
+ close(intf->fd);
+ intf->fd = -1;
+ }
+
+ if (intf->session) {
+ free(intf->session);
+ intf->session = NULL;
+ }
+
+ intf->opened = 0;
+}
+
+/*
+ * This function waits for incoming byte during timeout (ms).
+ */
+static int
+serial_wait_for_data(struct ipmi_intf * intf)
+{
+ int n;
+ struct pollfd pfd;
+
+ pfd.fd = intf->fd;
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+
+ n = poll(&pfd, 1, intf->session->timeout*1000);
+ if (n < 0) {
+ lperror(LOG_ERR, "Poll for serial data failed");
+ return -1;
+ } else if (!n) {
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Read a line from serial port
+ * Returns > 0 if there is a line, < 0 on error or timeout
+ */
+static int
+serial_read_line(struct ipmi_intf * intf, char *str, int len)
+{
+ int rv, i;
+
+ *str = 0;
+ i = 0;
+ while (i < len) {
+ if (serial_wait_for_data(intf)) {
+ return -1;
+ }
+ rv = read(intf->fd, str + i, 1);
+ if (rv < 0) {
+ return -1;
+ } else if (!rv) {
+ lperror(LOG_ERR, "Serial read failed: %s", strerror(errno));
+ return -1;
+ }
+ if (str[i] == '\n' || str[i] == '\r') {
+ if (verbose > 4) {
+ char c = str[i];
+ str[i] = '\0';
+ fprintf(stderr, "Received data: %s\n", str);
+ str[i] = c;
+ }
+ return i + 1;
+ } else {
+ i++;
+ }
+ }
+
+ lprintf(LOG_ERR, "Serial data is too long");
+ return -1;
+}
+
+/*
+ * Send zero-terminated string to serial port
+ * Returns the string length or negative error code
+ */
+static int
+serial_write_line(struct ipmi_intf * intf, const char *str)
+{
+ int rv, cnt = 0;
+ int cb = strlen(str);
+
+ while (cnt < cb) {
+ rv = write(intf->fd, str + cnt, cb - cnt);
+ if (rv < 0) {
+ return -1;
+ } else if (rv == 0) {
+ return -1;
+ }
+ cnt += rv;
+ }
+
+ return cnt;
+}
+
+/*
+ * Flush the buffers
+ */
+static int
+serial_flush(struct ipmi_intf * intf)
+{
+#if defined(TCFLSH)
+ return ioctl(intf->fd, TCFLSH, TCIOFLUSH);
+#elif defined(TIOCFLUSH)
+ return ioctl(intf->fd, TIOCFLUSH);
+#else
+# error "unsupported platform, missing flush support (TCFLSH/TIOCFLUSH)"
+#endif
+
+}
+
+/*
+ * Receive IPMI response from the device
+ * Len: buffer size
+ * Returns: -1 or response lenth on success
+ */
+static int
+recv_response(struct ipmi_intf * intf, unsigned char *data, int len)
+{
+ char hex_rs[IPMI_SERIAL_MAX_RESPONSE * 3];
+ int i, j, resp_len = 0;
+ unsigned long rv;
+ char *p, *pp;
+ char ch, str_hex[3];
+
+ p = hex_rs;
+ while (1) {
+ if ((rv = serial_read_line(intf, p, sizeof(hex_rs) - resp_len)) < 0) {
+ /* error */
+ return -1;
+ }
+ p += rv;
+ resp_len += rv;
+ if (*(p - 2) == ']' && (*(p - 1) == '\n' || *(p - 1) == '\r')) {
+ *p = 0;
+ break;
+ }
+ }
+
+ p = strrchr(hex_rs, '[');
+ if (!p) {
+ lprintf(LOG_ERR, "Serial response is invalid");
+ return -1;
+ }
+
+ p++;
+ pp = strchr(p, ']');
+ if (!pp) {
+ lprintf(LOG_ERR, "Serial response is invalid");
+ return -1;
+ }
+ *pp = 0;
+
+ /* was it an error? */
+ if (strncmp(p, "ERR ", 4) == 0) {
+ serial_write_line(intf, "\r\r\r\r");
+ sleep(1);
+ serial_flush(intf);
+ errno = 0;
+ rv = strtoul(p + 4, &p, 16);
+ if ((rv && rv < 0x100 && *p == '\0')
+ || (rv == 0 && !errno)) {
+ /* The message didn't get it through. The upper
+ level will have to re-send */
+ return 0;
+ } else {
+ lprintf(LOG_ERR, "Serial response is invalid");
+ return -1;
+ }
+ }
+
+ /* this is needed for correct string to long conversion */
+ str_hex[2] = 0;
+
+ /* parse the response */
+ i = 0;
+ j = 0;
+ while (*p) {
+ if (i >= len) {
+ lprintf(LOG_ERR, "Serial response is too long(%d, %d)", i, len);
+ return -1;
+ }
+ ch = *(p++);
+ if (isxdigit(ch)) {
+ str_hex[j++] = ch;
+ } else {
+ if (j == 1 || !isspace(ch)) {
+ lprintf(LOG_ERR, "Serial response is invalid");
+ return -1;
+ }
+ }
+ if (j == 2) {
+ unsigned long tmp;
+ errno = 0;
+ /* parse the hex number */
+ tmp = strtoul(str_hex, NULL, 16);
+ if ( tmp > 0xFF || ( !tmp && errno ) ) {
+ lprintf(LOG_ERR, "Serial response is invalid");
+ return -1;
+ }
+ data[i++] = tmp;
+ j = 0;
+ }
+ }
+
+ return i;
+}
+
+/*
+ * Allocate sequence number for tracking
+ */
+static uint8_t
+serial_term_alloc_seq(void)
+{
+ static uint8_t seq = 0;
+ if (++seq == 64) {
+ seq = 0;
+ }
+ return seq;
+}
+
+/*
+ * Build IPMB message to be transmitted
+ */
+static int
+serial_term_build_msg(const struct ipmi_intf * intf,
+ const struct ipmi_rq * req, uint8_t * msg, size_t max_len,
+ struct serial_term_request_ctx * ctx, int * msg_len)
+{
+ uint8_t * data = msg, seq;
+ struct serial_term_hdr * term_hdr = (struct serial_term_hdr *) msg;
+ struct ipmi_send_message_rq * outer_rq = NULL;
+ struct ipmi_send_message_rq * inner_rq = NULL;
+ int bridging_level;
+
+ /* acquire bridging level */
+ if (intf->target_addr && intf->target_addr != intf->my_addr) {
+ if (intf->transit_addr != 0) {
+ bridging_level = 2;
+ } else {
+ bridging_level = 1;
+ }
+ } else {
+ bridging_level = 0;
+ }
+
+ /* check overall packet length */
+ if(req->msg.data_len + 3 + bridging_level * 8 > max_len) {
+ lprintf(LOG_ERR, "ipmitool: Message data is too long");
+ return -1;
+ }
+
+ /* allocate new sequence number */
+ seq = serial_term_alloc_seq() << 2;
+
+ /* check for bridging */
+ if (bridging_level) {
+ /* compose terminal message header */
+ term_hdr->netFn = 0x18;
+ term_hdr->seq = seq;
+ term_hdr->cmd = 0x34;
+
+ /* set pointer to send message request data */
+ outer_rq = (struct ipmi_send_message_rq *) (term_hdr + 1);
+
+ if (bridging_level == 2) {
+ /* compose the outer send message request */
+ outer_rq->channel = intf->transit_channel | 0x40;
+ outer_rq->msg.rsSA = intf->transit_addr;
+ outer_rq->msg.netFn = 0x18;
+ outer_rq->msg.csum1 = -(outer_rq->msg.rsSA + outer_rq->msg.netFn);
+ outer_rq->msg.rqSA = intf->my_addr;
+ outer_rq->msg.rqSeq = seq;
+ outer_rq->msg.cmd = 0x34;
+
+ /* inner request is further */
+ inner_rq = (outer_rq + 1);
+ } else {
+ /* there is only one header */
+ inner_rq = outer_rq;
+ }
+
+ /* compose the inner send message request */
+ inner_rq->channel = intf->target_channel | 0x40;
+ inner_rq->msg.rsSA = intf->target_addr;
+ inner_rq->msg.netFn = (req->msg.netfn << 2) | req->msg.lun;
+ inner_rq->msg.csum1 = -(inner_rq->msg.rsSA + inner_rq->msg.netFn);
+ inner_rq->msg.rqSA = intf->my_addr;
+ inner_rq->msg.rqSeq = seq;
+ inner_rq->msg.cmd = req->msg.cmd;
+
+ /* check if interface is the system one */
+ if (is_system) {
+ /* need response to LUN 2 */
+ outer_rq->msg.rqSeq |= 2;
+
+ /* do not track response */
+ outer_rq->channel &= ~0x40;
+
+ /* restore BMC SA if bridging not to primary IPMB channel */
+ if (outer_rq->channel) {
+ outer_rq->msg.rqSA = IPMI_BMC_SLAVE_ADDR;
+ }
+ }
+
+ /* fill the second context */
+ ctx[1].netFn = outer_rq->msg.netFn;
+ ctx[1].sa = outer_rq->msg.rsSA;
+ ctx[1].seq = outer_rq->msg.rqSeq;
+ ctx[1].cmd = outer_rq->msg.cmd;
+
+ /* move write pointer */
+ msg = (uint8_t *)(inner_rq + 1);
+ } else {
+ /* compose terminal message header */
+ term_hdr->netFn = (req->msg.netfn << 2) | req->msg.lun;
+ term_hdr->seq = seq;
+ term_hdr->cmd = req->msg.cmd;
+
+ /* move write pointer */
+ msg = (uint8_t *)(term_hdr + 1);
+ }
+
+ /* fill the first context */
+ ctx[0].netFn = term_hdr->netFn;
+ ctx[0].seq = term_hdr->seq;
+ ctx[0].cmd = term_hdr->cmd;
+
+ /* write request data */
+ memcpy(msg, req->msg.data, req->msg.data_len);
+
+ /* move write pointer */
+ msg += req->msg.data_len;
+
+ if (bridging_level) {
+ /* write inner message checksum */
+ *msg++ = ipmi_csum(&inner_rq->msg.rqSA, req->msg.data_len + 3);
+
+ /* check for double bridging */
+ if (bridging_level == 2) {
+ /* write outer message checksum */
+ *msg++ = ipmi_csum(&outer_rq->msg.rqSA, 4);
+ }
+ }
+
+
+ /* save message length */
+ *msg_len = msg - data;
+
+ /* return bridging level */
+ return bridging_level;
+}
+
+/*
+ * Send message to serial port
+ */
+static int
+serial_term_send_msg(struct ipmi_intf * intf, uint8_t * msg, int msg_len)
+{
+ int i, size, tmp = 0;
+ uint8_t * buf, * data;
+
+ if (verbose > 3) {
+ fprintf(stderr, "Sending request:\n");
+ fprintf(stderr, " NetFN/rsLUN = 0x%x\n", msg[0]);
+ fprintf(stderr, " rqSeq = 0x%x\n", msg[1]);
+ fprintf(stderr, " cmd = 0x%x\n", msg[2]);
+ if (msg_len > 7) {
+ fprintf(stderr, " data_len = %d\n", msg_len - 3);
+ fprintf(stderr, " data = %s\n",
+ buf2str(msg + 3, msg_len - 3));
+ }
+ }
+
+ if (verbose > 4) {
+ fprintf(stderr, "Message data:\n");
+ fprintf(stderr, " %s\n", buf2str(msg, msg_len));
+ }
+
+ /* calculate required buffer size */
+ size = msg_len * 2 + 4;
+
+ /* allocate buffer for output data */
+ buf = data = (uint8_t *) alloca(size);
+
+ if (!buf) {
+ lperror(LOG_ERR, "ipmitool: alloca error");
+ return -1;
+ }
+
+ /* start character */
+ *buf++ = '[';
+
+ /* body */
+ for (i = 0; i < msg_len; i++) {
+ buf += sprintf( buf, "%02x", msg[i]);
+ }
+
+ /* stop character */
+ *buf++ = ']';
+
+ /* carriage return */
+ *buf++ = '\r';
+
+ /* line feed */
+ *buf++ = '\n';
+
+ /* write data to serial port */
+ tmp = write(intf->fd, data, size);
+ if (tmp <= 0) {
+ lperror(LOG_ERR, "ipmitool: write error");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Wait for request response
+ */
+static int
+serial_term_wait_response(struct ipmi_intf * intf,
+ struct serial_term_request_ctx * req_ctx,
+ uint8_t * msg, size_t max_len)
+{
+ struct serial_term_hdr * hdr = (struct serial_term_hdr *) msg;
+ int msg_len;
+
+ /* wait for response(s) */
+ do {
+ /* receive message */
+ msg_len = recv_response(intf, msg, max_len);
+
+ /* check if valid message received */
+ if (msg_len > 0) {
+ /* validate message size */
+ if (msg_len < 4) {
+ /* either bad response or non-related message */
+ continue;
+ }
+
+ /* check for the waited response */
+ if (hdr->netFn == (req_ctx->netFn|4)
+ && (hdr->seq & ~3) == req_ctx->seq
+ && hdr->cmd == req_ctx->cmd) {
+ /* check if something new has been parsed */
+ if (verbose > 3) {
+ fprintf(stderr, "Got response:\n");
+ fprintf(stderr, " NetFN/rsLUN = 0x%x\n", msg[0]);
+ fprintf(stderr, " rqSeq/Bridge = 0x%x\n", msg[1]);
+ fprintf(stderr, " cmd = 0x%x\n", msg[2]);
+ fprintf(stderr, " completion code = 0x%x\n", msg[3]);
+ if (msg_len > 8) {
+ fprintf(stderr, " data_len = %d\n",
+ msg_len - 4);
+ fprintf(stderr, " data = %s\n",
+ buf2str(msg + 4, msg_len - 4));
+ }
+ }
+
+ /* move to start from completion code */
+ memmove(msg, hdr + 1, msg_len - sizeof (*hdr));
+
+ /* the waited one */
+ return msg_len - sizeof (*hdr);
+ }
+ }
+ } while (msg_len > 0);
+
+ return 0;
+}
+
+/*
+ * Get message from receive message queue
+ */
+static int
+serial_term_get_message(struct ipmi_intf * intf,
+ struct serial_term_request_ctx * req_ctx,
+ uint8_t * msg, size_t max_len)
+{
+ uint8_t data[IPMI_SERIAL_MAX_RESPONSE];
+ struct serial_term_request_ctx tmp_ctx;
+ struct ipmi_get_message_rp * rp = (struct ipmi_get_message_rp *) data;
+ struct serial_term_hdr hdr;
+ clock_t start, tm;
+ int rv, netFn, rqSeq;
+
+ start = clock();
+
+ do {
+ /* fill-in request context */
+ tmp_ctx.netFn = 0x18;
+ tmp_ctx.seq = serial_term_alloc_seq() << 2;
+ tmp_ctx.cmd = 0x33;
+
+ /* fill-in request data */
+ hdr.netFn = tmp_ctx.netFn;
+ hdr.seq = tmp_ctx.seq;
+ hdr.cmd = tmp_ctx.cmd;
+
+ /* send request */
+ serial_flush(intf);
+ serial_term_send_msg(intf, (uint8_t *) &hdr, 3);
+
+ /* wait for response */
+ rv = serial_term_wait_response(intf, &tmp_ctx, data, sizeof (data));
+
+ /* check for IO error or timeout */
+ if (rv <= 0) {
+ return rv;
+ }
+
+ netFn = (req_ctx->netFn & ~3)|(req_ctx->seq & 3)|4;
+ rqSeq = req_ctx->seq & ~3;
+
+ /* check completion code */
+ if (rp->completion == 0) {
+ /* check for the waited response */
+ if (rp->netFn == netFn
+ && rp->rsSA == req_ctx->sa
+ && rp->rqSeq == rqSeq
+ && rp->cmd == req_ctx->cmd) {
+ /* copy the rest of message */
+ memcpy(msg, rp + 1, rv - sizeof (*rp) - 1);
+ return rv - sizeof (*rp) - 1;
+ }
+ } else if (rp->completion != 0x80) {
+ return 0;
+ }
+
+ tm = clock() - start;
+
+ tm /= CLOCKS_PER_SEC;
+ } while (tm < intf->session->timeout);
+
+ return 0;
+}
+
+static struct ipmi_rs *
+ipmi_serial_term_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
+{
+ static struct ipmi_rs rsp;
+ uint8_t msg[IPMI_SERIAL_MAX_RESPONSE], * resp = msg;
+ struct serial_term_request_ctx req_ctx[2];
+ int retry, rv, msg_len, bridging_level;
+
+ if (!intf->opened && intf->open && intf->open(intf) < 0) {
+ return NULL;
+ }
+
+ /* Send the message and receive the answer */
+ for (retry = 0; retry < intf->session->retry; retry++) {
+ /* build output message */
+ bridging_level = serial_term_build_msg(intf, req, msg,
+ sizeof (msg), req_ctx, &msg_len);
+ if (msg_len < 0) {
+ return NULL;
+ }
+
+ /* send request */
+ serial_flush(intf);
+ serial_term_send_msg(intf, msg, msg_len);
+
+ /* wait for response */
+ rv = serial_term_wait_response(intf, &req_ctx[0], msg, sizeof (msg));
+
+ /* check for IO error */
+ if (rv < 0) {
+ return NULL;
+ }
+
+ /* check for timeout */
+ if (rv == 0) {
+ continue;
+ }
+
+ /* check for bridging */
+ if (bridging_level && msg[0] == 0) {
+ /* in the case of payload interface we check receive message queue */
+ if (is_system) {
+ /* check message flags */
+ rv = serial_term_get_message(intf, &req_ctx[1],
+ msg, sizeof (msg));
+
+ /* check for IO error */
+ if (rv < 0) {
+ return NULL;
+ }
+
+ /* check for timeout */
+ if (rv == 0) {
+ continue;
+ }
+ /* check if response for inner request is not encapsulated */
+ } else if (rv == 1) {
+ /* wait for response for inner request */
+ rv = serial_term_wait_response(intf, &req_ctx[1],
+ msg, sizeof (msg));
+
+ /* check for IO error */
+ if (rv < 0) {
+ return NULL;
+ }
+
+ /* check for timeout */
+ if (rv == 0) {
+ continue;
+ }
+ } else {
+ /* skip outer level header */
+ resp = msg + sizeof (struct ipmb_msg_hdr) + 1;
+ /* decrement response size */
+ rv -= + sizeof (struct ipmb_msg_hdr) + 2;
+ }
+
+ /* check response size */
+ if (resp[0] == 0 && bridging_level == 2 && rv < 8) {
+ lprintf(LOG_ERR, "ipmitool: Message response is too short");
+ /* invalid message length */
+ return NULL;
+ }
+ }
+
+ /* check for double bridging */
+ if (bridging_level == 2 && resp[0] == 0) {
+ /* get completion code */
+ rsp.ccode = resp[7];
+ rsp.data_len = rv - 9;
+ memcpy(rsp.data, resp + 8, rsp.data_len);
+ } else {
+ rsp.ccode = resp[0];
+ rsp.data_len = rv - 1;
+ memcpy(rsp.data, resp + 1, rsp.data_len);
+ }
+
+ /* return response */
+ return &rsp;
+ }
+
+ /* no valid response */
+ return NULL;
+}
+
+static int
+ipmi_serial_term_setup(struct ipmi_intf * intf)
+{
+ intf->session = malloc(sizeof(struct ipmi_session));
+ if (intf->session == NULL) {
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
+ return -1;
+ }
+
+ memset(intf->session, 0, sizeof(struct ipmi_session));
+
+ /* setup default LAN maximum request and response sizes */
+ intf->max_request_data_size = IPMI_SERIAL_MAX_RQ_SIZE;
+ intf->max_response_data_size = IPMI_SERIAL_MAX_RS_SIZE;
+ return 0;
+}
+
+int
+ipmi_serial_term_set_my_addr(struct ipmi_intf * intf, uint8_t addr)
+{
+ intf->my_addr = addr;
+ return 0;
+}
+
+struct ipmi_intf ipmi_serial_term_intf = {
+ name: "serial-terminal",
+ desc: "Serial Interface, Terminal Mode",
+ setup: ipmi_serial_term_setup,
+ open: ipmi_serial_term_open,
+ close: ipmi_serial_term_close,
+ sendrecv: ipmi_serial_term_send_cmd,
+ set_my_addr:ipmi_serial_term_set_my_addr
+};