diff --git a/configure.in b/configure.in index 0d1796fe8..59fdacc3a 100644 --- a/configure.in +++ b/configure.in @@ -1,765 +1,772 @@ dnl dnl autoconf for Agents dnl dnl License: GNU General Public License (GPL) dnl =============================================== dnl Bootstrap dnl =============================================== AC_PREREQ(2.53) dnl Suggested structure: dnl information on the package dnl checks for programs dnl checks for libraries dnl checks for header files dnl checks for types dnl checks for structures dnl checks for compiler characteristics dnl checks for library functions dnl checks for system services AC_INIT(resource-agents, 1.0.0, pacemaker@oss.clusterlabs.org) CRM_DTD_VERSION="1.0" PKG_FEATURES="" AC_CONFIG_AUX_DIR(.) AC_CANONICAL_HOST dnl Where #defines go (e.g. `AC_CHECK_HEADERS' below) dnl dnl Internal header: include/config.h dnl - Contains ALL defines dnl - include/config.h.in is generated automatically by autoheader dnl - NOT to be included in any header files except lha_internal.h dnl (which is also not to be included in any other header files) dnl dnl External header: include/agent_config.h dnl - Contains a subset of defines checked here dnl - Manually edit include/agent_config.h.in to have configure include new defines dnl - Should not include HAVE_* defines dnl - Safe to include anywhere AM_CONFIG_HEADER(include/config.h include/agent_config.h) ALL_LINGUAS="en fr" AC_ARG_WITH(version, [ --with-version=version Override package version (if you're a packager needing to pretend) ], [ PACKAGE_VERSION="$withval" ]) AC_ARG_WITH(pkg-name, [ --with-pkg-name=name Override package name (if you're a packager needing to pretend) ], [ PACKAGE_NAME="$withval" ]) AM_INIT_AUTOMAKE($PACKAGE_NAME, $PACKAGE_VERSION) AC_DEFINE_UNQUOTED(AGENTS_VERSION, "$PACKAGE_VERSION", Current agents version) CC_IN_CONFIGURE=yes export CC_IN_CONFIGURE LDD=ldd dnl ======================================================================== dnl Compiler characteristics dnl ======================================================================== AC_PROG_CC dnl Can force other with environment variable "CC". AM_PROG_CC_C_O AC_PROG_CC_STDC AC_C_STRINGIZE AC_TYPE_SIZE_T AC_CHECK_SIZEOF(char) AC_CHECK_SIZEOF(short) AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(long long) AC_STRUCT_TIMEZONE dnl =============================================== dnl Helpers dnl =============================================== cc_supports_flag() { local CFLAGS="$@" AC_MSG_CHECKING(whether $CC supports "$@") AC_COMPILE_IFELSE([int main(){return 0;}] ,[RC=0; AC_MSG_RESULT(yes)],[RC=1; AC_MSG_RESULT(no)]) return $RC } extract_header_define() { AC_MSG_CHECKING(for $2 in $1) Cfile=/tmp/extract_define.$2.${$} printf "#include \n" > ${Cfile}.c printf "#include <%s>\n" $1 >> ${Cfile}.c printf "int main(int argc, char **argv) { printf(\"%%s\", %s); return 0; }\n" $2 >> ${Cfile}.c $CC $CFLAGS ${Cfile}.c -o ${Cfile} value=`${Cfile}` AC_MSG_RESULT($value) printf $value rm -f ${Cfile}.c ${Cfile} } dnl =============================================== dnl Configure Options dnl =============================================== dnl Some systems, like Solaris require a custom package name AC_ARG_WITH(pkgname, [ --with-pkgname=name name for pkg (typically for Solaris) ], [ PKGNAME="$withval" ], [ PKGNAME="LXHAhb" ], ) AC_SUBST(PKGNAME) AC_ARG_ENABLE([ansi], [ --enable-ansi force GCC to compile to ANSI/ANSI standard for older compilers. [default=yes]]) AC_ARG_ENABLE([fatal-warnings], [ --enable-fatal-warnings very pedantic and fatal warnings for gcc [default=yes]]) INITDIR="" AC_ARG_WITH(initdir, [ --with-initdir=DIR directory for init (rc) scripts [${INITDIR}]], [ INITDIR="$withval" ]) OCF_ROOT_DIR="/usr/lib/ocf" AC_ARG_WITH(ocf-root, [ --with-ocf-root=DIR directory for OCF scripts [${OCF_ROOT_DIR}]], [ if test x"$withval" = xprefix; then OCF_ROOT_DIR=${prefix}; else OCF_ROOT_DIR="$withval"; fi ]) dnl =============================================== dnl General Processing dnl =============================================== INIT_EXT="" echo Our Host OS: $host_os/$host AC_MSG_NOTICE(Sanitizing prefix: ${prefix}) case $prefix in NONE) prefix=/usr;; esac AC_MSG_NOTICE(Sanitizing exec_prefix: ${exec_prefix}) case $exec_prefix in dnl For consistency with Heartbeat, map NONE->$prefix NONE) exec_prefix=$prefix;; prefix) exec_prefix=$prefix;; esac AC_MSG_NOTICE(Sanitizing INITDIR: ${INITDIR}) case $INITDIR in prefix) INITDIR=$prefix;; "") AC_MSG_CHECKING(which init (rc) directory to use) for initdir in /etc/init.d /etc/rc.d/init.d /sbin/init.d \ /usr/local/etc/rc.d /etc/rc.d do if test -d $initdir then INITDIR=$initdir break fi done AC_MSG_RESULT($INITDIR);; esac AC_SUBST(INITDIR) AC_MSG_NOTICE(Sanitizing libdir: ${libdir}) case $libdir in dnl For consistency with Heartbeat, map NONE->$prefix *prefix*|NONE) AC_MSG_CHECKING(which lib directory to use) for aDir in lib64 lib do trydir="${exec_prefix}/${aDir}" if test -d ${trydir} then libdir=${trydir} break fi done AC_MSG_RESULT($libdir); ;; esac dnl Expand autoconf variables so that we dont end up with '${prefix}' dnl in #defines and python scripts dnl NOTE: Autoconf deliberately leaves them unexpanded to allow dnl make exec_prefix=/foo install dnl No longer being able to do this seems like no great loss to me... eval prefix="`eval echo ${prefix}`" eval exec_prefix="`eval echo ${exec_prefix}`" eval bindir="`eval echo ${bindir}`" eval sbindir="`eval echo ${sbindir}`" eval libexecdir="`eval echo ${libexecdir}`" eval datadir="`eval echo ${datadir}`" eval sysconfdir="`eval echo ${sysconfdir}`" eval sharedstatedir="`eval echo ${sharedstatedir}`" eval localstatedir="`eval echo ${localstatedir}`" eval libdir="`eval echo ${libdir}`" eval includedir="`eval echo ${includedir}`" eval oldincludedir="`eval echo ${oldincludedir}`" eval infodir="`eval echo ${infodir}`" eval mandir="`eval echo ${mandir}`" dnl Home-grown variables eval INITDIR="${INITDIR}" eval docdir="`eval echo ${docdir}`" for j in prefix exec_prefix bindir sbindir libexecdir datadir sysconfdir \ sharedstatedir localstatedir libdir includedir oldincludedir infodir \ mandir INITDIR docdir do dirname=`eval echo '${'${j}'}'` if test ! -d "$dirname" then AC_MSG_WARN([$j directory ($dirname) does not exist!]) fi done dnl This OS-based decision-making is poor autotools practice; dnl feature-based mechanisms are strongly preferred. dnl dnl So keep this section to a bare minimum; regard as a "necessary evil". REBOOT_OPTIONS="-f" POWEROFF_OPTIONS="-f" case "$host_os" in *bsd*) LIBS="-L/usr/local/lib" CPPFLAGS="$CPPFLAGS -I/usr/local/include" INIT_EXT=".sh" ;; *solaris*) REBOOT_OPTIONS="-n" POWEROFF_OPTIONS="-n" ;; *linux*) AC_DEFINE_UNQUOTED(ON_LINUX, 1, Compiling for Linux platform) POWEROFF_OPTIONS="-nf" REBOOT_OPTIONS="-nf" ;; darwin*) AC_DEFINE_UNQUOTED(ON_DARWIN, 1, Compiling for Darwin platform) LIBS="$LIBS -L${prefix}/lib" CFLAGS="$CFLAGS -I${prefix}/include" ;; esac dnl Eventually remove this dnl CFLAGS="$CFLAGS -I${prefix}/include/heartbeat" AC_SUBST(INIT_EXT) AC_DEFINE_UNQUOTED(HA_LOG_FACILITY, LOG_DAEMON, Default logging facility) AC_MSG_NOTICE(Host CPU: $host_cpu) case "$host_cpu" in ppc64|powerpc64) case $CFLAGS in *powerpc64*) ;; *) if test "$GCC" = yes; then CFLAGS="$CFLAGS -m64" fi ;; esac esac AC_MSG_CHECKING(which format is needed to print uint64_t) case "$host_cpu" in s390x)U64T="%lu";; *64*) U64T="%lu";; *) U64T="%llu";; esac AC_MSG_RESULT($U64T) AC_DEFINE_UNQUOTED(U64T, "$U64T", Correct printf format for logging uint64_t) dnl Variables needed for substitution AC_CHECK_HEADERS(glue_config.h) if test "X$OCF_ROOT_DIR" = X; then if test "$ac_cv_header_glue_config_h" != "yes"; then AC_MSG_FAILURE(The cluster-glue development headers were not found) fi OCF_ROOT_DIR=`extract_header_define glue_config.h OCF_ROOT_DIR` fi AC_DEFINE_UNQUOTED(OCF_ROOT_DIR,"$OCF_ROOT_DIR", OCF root directory - specified by the OCF standard) AC_SUBST(OCF_ROOT_DIR) GLUE_STATE_DIR=${localstatedir}/run AC_DEFINE_UNQUOTED(GLUE_STATE_DIR,"$GLUE_STATE_DIR", Where to keep state files and sockets) AC_SUBST(GLUE_STATE_DIR) AC_DEFINE_UNQUOTED(HA_VARRUNDIR,"$GLUE_STATE_DIR", Where Heartbeat keeps state files and sockets - old name) HA_VARRUNDIR="$GLUE_STATE_DIR" AC_SUBST(HA_VARRUNDIR) dnl Eventually move out of the heartbeat dir tree and create symlinks when needed HA_VARLIBHBDIR=${localstatedir}/lib/heartbeat AC_DEFINE_UNQUOTED(HA_VARLIBHBDIR,"$HA_VARLIBHBDIR", Whatever this used to mean) AC_SUBST(HA_VARLIBHBDIR) OCF_RA_DIR="${OCF_ROOT_DIR}/resource.d/" AC_DEFINE_UNQUOTED(OCF_RA_DIR,"$OCF_RA_DIR", Location for OCF RAs) AC_SUBST(OCF_RA_DIR) AC_PATH_PROGS(HG, hg false) AC_MSG_CHECKING(build version) BUILD_VERSION=unknown if test -f $srcdir/.hg_archival.txt; then BUILD_VERSION=`cat $srcdir/.hg_archival.txt | awk '/node:/ { print $2 }'` elif test -x $HG -a -d .hg; then BUILD_VERSION=`$HG id -itb` if test $? != 0; then BUILD_VERSION=unknown fi fi AC_DEFINE_UNQUOTED(BUILD_VERSION, "$BUILD_VERSION", Build version) AC_MSG_RESULT($BUILD_VERSION) AC_SUBST(BUILD_VERSION) dnl =============================================== dnl Program Paths dnl =============================================== PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin" export PATH AM_PATH_PYTHON AC_CHECK_PROGS(MAKE, gmake make) AC_PATH_PROGS(SSH, ssh, /usr/bin/ssh) AC_PATH_PROGS(SCP, scp, /usr/bin/scp) AC_PATH_PROGS(HG, hg, /bin/false) AC_PATH_PROGS(TAR, tar) AC_PATH_PROGS(MD5, md5) AC_PATH_PROGS(TEST, test) AC_PATH_PROGS(PING, ping, /bin/ping) AC_PATH_PROGS(IFCONFIG, ifconfig, /sbin/ifconfig) AC_PATH_PROGS(MAILCMD, mailx mail) AC_PATH_PROGS(EGREP, egrep) AC_PATH_PROGS(PKGCONFIG, pkg-config) AC_SUBST(MAILCMD) AC_SUBST(EGREP) AC_SUBST(SHELL) AC_SUBST(PING) AC_SUBST(TEST) +AC_DEFINE(ROUTEPARM, "-n get", paramters for route to retrieve route information) +AC_DEFINE(PROCROUTE, "/proc/net/route", path were to find route information in proc) +AC_PATH_PROGS(ROUTE, route) +AC_DEFINE_UNQUOTED(ROUTE, "$ROUTE", path to route command) +AC_SUBST(ROUTEPARM) +AC_SUBST(PROCROUTE) + AC_MSG_CHECKING(ifconfig option to list interfaces) for IFCONFIG_A_OPT in "-A" "-a" "" do $IFCONFIG $IFCONFIG_A_OPT > /dev/null 2>&1 if test "$?" = 0 then AC_DEFINE_UNQUOTED(IFCONFIG_A_OPT, "$IFCONFIG_A_OPT", option for ifconfig command) AC_MSG_RESULT($IFCONFIG_A_OPT) break fi done AC_SUBST(IFCONFIG_A_OPT) if test x"${MAKE}" = x""; then AC_MSG_ERROR(You need (g)make installed in order to build ${PACKAGE}) fi dnl =============================================== dnl Libraries dnl =============================================== AC_CHECK_LIB(socket, socket) AC_CHECK_LIB(gnugetopt, getopt_long) dnl if available if test x"${PKGCONFIG}" = x""; then AC_MSG_ERROR(You need pkgconfig installed in order to build ${PACKAGE}) fi if test "x${enable_thread_safe}" = "xyes"; then GPKGNAME="gthread-2.0" else GPKGNAME="glib-2.0" fi if $PKGCONFIG --exists $GPKGNAME then GLIBCONFIG="$PKGCONFIG $GPKGNAME" else set -x echo PKG_CONFIG_PATH=$PKG_CONFIG_PATH $PKGCONFIG --exists $GPKGNAME; echo $? $PKGCONFIG --cflags $GPKGNAME; echo $? $PKGCONFIG $GPKGNAME; echo $? set +x AC_MSG_ERROR(You need glib2-devel installed in order to build ${PACKAGE}) fi AC_MSG_RESULT(using $GLIBCONFIG) if test "X$GLIBCONFIG" != X; then AC_MSG_CHECKING(for special glib includes: ) GLIBHEAD=`$GLIBCONFIG --cflags` AC_MSG_RESULT($GLIBHEAD) CPPFLAGS="$CPPFLAGS $GLIBHEAD" AC_MSG_CHECKING(for glib library flags) GLIBLIB=`$GLIBCONFIG --libs` AC_MSG_RESULT($GLIBLIB) LIBS="$LIBS $GLIBLIB" fi dnl ======================================================================== dnl Headers dnl ======================================================================== AC_HEADER_STDC dnl ======================================================================== dnl Functions dnl ======================================================================== dnl 'reboot()' system call: one argument (e.g. Linux) or two (e.g. Solaris)? dnl AC_CACHE_CHECK([number of arguments in reboot system call], ac_cv_REBOOT_ARGS,[ AC_TRY_COMPILE( [#include ], [(void)reboot(0);], ac_cv_REBOOT_ARGS=1, [AC_TRY_COMPILE( [#include ], [(void)reboot(0,(void *)0);], ac_cv_REBOOT_ARGS=2, ac_cv_REBOOT_ARGS=0 )], ac_cv_REBOOT_ARGS=0 ) ] ) dnl Argument count of 0 suggests no known 'reboot()' call. if test "$ac_cv_REBOOT_ARGS" -ge "1"; then AC_DEFINE_UNQUOTED(REBOOT_ARGS,$ac_cv_REBOOT_ARGS,[number of arguments for reboot system call]) fi AC_PATH_PROGS(REBOOT, reboot, /sbin/reboot) AC_SUBST(REBOOT) AC_SUBST(REBOOT_OPTIONS) AC_DEFINE_UNQUOTED(REBOOT, "$REBOOT", path to the reboot command) AC_DEFINE_UNQUOTED(REBOOT_OPTIONS, "$REBOOT_OPTIONS", reboot options) AC_PATH_PROGS(POWEROFF_CMD, poweroff, /sbin/poweroff) AC_SUBST(POWEROFF_CMD) AC_SUBST(POWEROFF_OPTIONS) AC_DEFINE_UNQUOTED(POWEROFF_CMD, "$POWEROFF_CMD", path to the poweroff command) AC_DEFINE_UNQUOTED(POWEROFF_OPTIONS, "$POWEROFF_OPTIONS", poweroff options) dnl ======================================================================== dnl Functions dnl ======================================================================== AC_CHECK_FUNCS(getopt, AC_DEFINE(HAVE_DECL_GETOPT, 1, [Have getopt function])) dnl ======================================================================== dnl libnet dnl ======================================================================== AC_ARG_ENABLE([libnet], [ --enable-libnet Use libnet for ARP based funcationality, [default=try]], [enable_libnet=$withval], [enable_libnet=try]) libnet="" libnet_version="none" LIBNETLIBS="" LIBNETDEFINES="" AC_MSG_CHECKING(if libnet is required) libnet_fatal=$enable_libnet case $enable_libnet in no) ;; yes|libnet10|libnet11|10|11) libnet_fatal=yes;; try) case $host_os in *Linux*|*linux*) libnet_fatal=no;; *) libnet_fatal=yes;; dnl legacy behavior esac ;; *) libnet_fatal=yes; enable_libnet=try;; esac AC_MSG_RESULT($libnet_fatal) if test "x$enable_libnet" != "xno"; then AC_PATH_PROGS(LIBNETCONFIG, libnet-config) AC_CHECK_LIB(nsl, t_open) dnl -lnsl AC_CHECK_LIB(socket, socket) dnl -lsocket AC_CHECK_LIB(net, libnet_get_hwaddr, LIBNETLIBS=" -lnet", []) fi AC_MSG_CHECKING(for libnet) if test "x$LIBNETLIBS" != "x" -o "x$enable_libnet" = "xlibnet11"; then LIBNETDEFINES="" if test "$ac_cv_lib_nsl_t_open" = yes; then LIBNETLIBS="-lnsl $LIBNETLIBS" fi if test "$ac_cv_lib_socket_socket" = yes; then LIBNETLIBS="-lsocket $LIBNETLIBS" fi libnet=net libnet_version="libnet1.1" fi if test "x$enable_libnet" = "xtry" -o "x$enable_libnet" = "xlibnet10"; then if test "x$LIBNETLIBS" = x -a "x${LIBNETCONFIG}" != "x" ; then LIBNETDEFINES="`$LIBNETCONFIG --defines` `$LIBNETCONFIG --cflags`"; LIBNETLIBS="`$LIBNETCONFIG --libs`"; libnet_version="libnet1.0 (old)" case $LIBNETLIBS in *-l*) libnet=`echo $LIBNETLIBS | sed 's%.*-l%%'`;; *) libnet_version=none;; esac CPPFLAGS="$CPPFLAGS $LIBNETDEFINES" AC_CHECK_HEADERS(libnet.h) if test "$ac_cv_header_libnet_h" = no; then libnet_version=none fi fi fi AC_MSG_RESULT(found $libnet_version) if test "$libnet_version" = none; then LIBNETLIBS="" LIBNETDEFINES="" if test $libnet_fatal = yes; then AC_MSG_ERROR(libnet not found) fi else AC_CHECK_LIB($libnet,libnet_init, [new_libnet=yes; AC_DEFINE(HAVE_LIBNET_1_1_API, 1, Libnet 1.1 API)], [new_libnet=no; AC_DEFINE(HAVE_LIBNET_1_0_API, 1, Libnet 1.0 API)],$LIBNETLIBS) AC_SUBST(LIBNETLIBS) fi sendarp_linux=0 case $host_os in *Linux*|*linux*) sendarp_linux=1;; esac AC_SUBST(LIBNETLIBS) AC_SUBST(LIBNETDEFINES) AC_DEFINE(HAVE_LIBNET_API, test "x$libnet_version" != "xnone", Libnet API) AM_CONDITIONAL(SENDARP_LINUX, test $sendarp_linux = 1 ) AM_CONDITIONAL(USE_LIBNET, test "x$libnet_version" != "xnone" ) dnl ************************************************************************ dnl * Check for netinet/icmp6.h to enable the IPv6addr resource agent AC_CHECK_HEADERS(netinet/icmp6.h,[],[],[#include ]) AM_CONDITIONAL(USE_IPV6ADDR, test "$ac_cv_header_netinet_icmp6_h" = yes -a "$new_libnet" = yes ) dnl ======================================================================== dnl checks for library functions to replace them dnl dnl NoSuchFunctionName: dnl is a dummy function which no system supplies. It is here to make dnl the system compile semi-correctly on OpenBSD which doesn't know dnl how to create an empty archive dnl dnl scandir: Only on BSD. dnl System-V systems may have it, but hidden and/or deprecated. dnl A replacement function is supplied for it. dnl dnl setenv: is some bsdish function that should also be avoided (use dnl putenv instead) dnl On the other hand, putenv doesn't provide the right API for the dnl code and has memory leaks designed in (sigh...) Fortunately this dnl A replacement function is supplied for it. dnl dnl strerror: returns a string that corresponds to an errno. dnl A replacement function is supplied for it. dnl dnl unsetenv: is some bsdish function that should also be avoided (No dnl replacement) dnl A replacement function is supplied for it. dnl dnl strnlen: is a gnu function similar to strlen, but safer. dnl We wrote a tolearably-fast replacement function for it. dnl dnl strndup: is a gnu function similar to strdup, but safer. dnl We wrote a tolearably-fast replacement function for it. dnl dnl daemon: is a GNU function. The daemon() function is for programs wishing to dnl detach themselves from the controlling terminal and run in the dnl background as system daemon dnl A replacement function is supplied for it. AC_REPLACE_FUNCS(alphasort inet_pton NoSuchFunctionName scandir setenv strerror unsetenv strnlen strndup daemon strlcpy strlcat) dnl ======================================================================== dnl Compiler flags dnl ======================================================================== dnl Make sure that CFLAGS is not exported. If the user did dnl not have CFLAGS in their environment then this should have dnl no effect. However if CFLAGS was exported from the user's dnl environment, then the new CFLAGS will also be exported dnl to sub processes. CC_ERRORS="" CC_EXTRAS="" if export | fgrep " CFLAGS=" > /dev/null; then export -n CFLAGS || true # We don't want to bomb out if this fails fi if test "$GCC" != yes; then CFLAGS="$CFLAGS -g" enable_fatal_warnings=no else CFLAGS="$CFLAGS -ggdb3 -O0" # We had to eliminate -Wnested-externs because of libtool changes EXTRA_FLAGS="-fgnu89-inline -fstack-protector-all -Wall -Waggregate-return -Wbad-function-cast -Wcast-qual -Wcast-align -Wdeclaration-after-statement -Wendif-labels -Wfloat-equal -Wformat=2 -Wformat-security -Wformat-nonliteral -Winline -Wmissing-prototypes -Wmissing-declarations -Wmissing-format-attribute -Wnested-externs -Wno-long-long -Wno-strict-aliasing -Wpointer-arith -Wstrict-prototypes -Wunsigned-char -Wwrite-strings" # Additional warnings it might be nice to enable one day # -Wshadow # -Wunreachable-code for j in $EXTRA_FLAGS do if cc_supports_flag $j then CC_EXTRAS="$CC_EXTRAS $j" fi done dnl In lib/ais/Makefile.am there's a gcc option available as of v4.x GCC_MAJOR=`gcc -v 2>&1 | awk 'END{print $3}' | sed 's/[.].*//'` AM_CONDITIONAL(GCC_4, test "${GCC_MAJOR}" = 4) dnl System specific options case "$host_os" in *linux*|*bsd*) if test "${enable_fatal_warnings}" = "unknown"; then enable_fatal_warnings=yes fi ;; esac if test "x${enable_fatal_warnings}" != xno && cc_supports_flag -Werror ; then enable_fatal_warnings=yes else enable_fatal_warnings=no fi if test "x${enable_ansi}" != xno && cc_supports_flag -std=iso9899:199409 ; then AC_MSG_NOTICE(Enabling ANSI Compatibility) CC_EXTRAS="$CC_EXTRAS -ansi -D_GNU_SOURCE -DANSI_ONLY" fi AC_MSG_NOTICE(Activated additional gcc flags: ${CC_EXTRAS}) fi CFLAGS="$CFLAGS $CC_EXTRAS" NON_FATAL_CFLAGS="$CFLAGS" AC_SUBST(NON_FATAL_CFLAGS) dnl dnl We reset CFLAGS to include our warnings *after* all function dnl checking goes on, so that our warning flags don't keep the dnl AC_*FUNCS() calls above from working. In particular, -Werror will dnl *always* cause us troubles if we set it before here. dnl dnl if test "x${enable_fatal_warnings}" = xyes ; then AC_MSG_NOTICE(Enabling Fatal Warnings) CFLAGS="$CFLAGS -Werror" fi AC_SUBST(CFLAGS) dnl This is useful for use in Makefiles that need to remove one specific flag CFLAGS_COPY="$CFLAGS" AC_SUBST(CFLAGS_COPY) AC_SUBST(LOCALE) AC_SUBST(CC) AC_SUBST(MAKE) dnl The Makefiles and shell scripts we output AC_CONFIG_FILES(Makefile \ heartbeat/Makefile \ heartbeat/.ocf-binaries \ heartbeat/.ocf-directories \ heartbeat/.ocf-shellfuncs \ heartbeat/ocf-returncodes \ heartbeat/ocf-shellfuncs \ tools/Makefile \ tools/ocf-tester \ ) dnl Now process the entire list of files added by previous dnl calls to AC_CONFIG_FILES() AC_OUTPUT() dnl ***************** dnl Configure summary dnl ***************** AC_MSG_RESULT([]) AC_MSG_RESULT([$PACKAGE configuration:]) AC_MSG_RESULT([ Version = ${VERSION} (Build: $BUILD_VERSION)]) AC_MSG_RESULT([ Features =${PKG_FEATURES}]) AC_MSG_RESULT([]) AC_MSG_RESULT([ Prefix = ${prefix}]) AC_MSG_RESULT([ Executables = ${sbindir}]) AC_MSG_RESULT([ Man pages = ${mandir}]) AC_MSG_RESULT([ Libraries = ${libdir}]) AC_MSG_RESULT([ Header files = ${includedir}]) AC_MSG_RESULT([ Arch-independent files = ${datadir}]) AC_MSG_RESULT([ State information = ${localstatedir}]) AC_MSG_RESULT([ System configuration = ${sysconfdir}]) AC_MSG_RESULT([ AIS Plugins = ${LCRSODIR}]) AC_MSG_RESULT([]) AC_MSG_RESULT([ CFLAGS = ${CFLAGS}]) AC_MSG_RESULT([ Libraries = ${LIBS}]) AC_MSG_RESULT([ Stack Libraries = ${CLUSTERLIBS}]) diff --git a/tools/findif.c b/tools/findif.c index e58a7ff31..7da150c56 100644 --- a/tools/findif.c +++ b/tools/findif.c @@ -1,812 +1,813 @@ /* * findif.c: Finds an interface which can route a given address * * It's really simple to write in C, but hard to write in the shell... * * This code is dependent on IPV4 addressing conventions... * Sorry. * * Copyright (C) 2000 Alan Robertson * Copyright (C) 2001 Matt Soffen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * *********************************************************** * * All our arguments come through the environment as OCF * environment variables as below: * * OCF_RESKEY_ip * OCF_RESKEY_broadcast * OCF_RESKEY_nic * OCF_RESKEY_cidr_netmask * * If the CIDR netmask is omitted, we choose the netmask associated with * the route we selected. * * If the broadcast address was omitted, we assume the highest address * in the subnet. * * If the interface is omitted, we choose the interface associated with * the route we selected. * * * See http://www.doom.net/docs/netmask.html for a table explaining * CIDR address format and their relationship to life, the universe * and everything. * */ #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_SYS_SOCKIO_H #include #endif #include #include #include #ifdef __linux__ #undef __OPTIMIZE__ /* * This gets rid of some silly -Wtraditional warnings on Linux * because the netinet header has some slightly funky constants * in it. */ #endif /* __linux__ */ #include #include #define DEBUG 0 +#define EOS '\0' /* * "route -n get iii.jjj.kkk.lll" can, on Solaris at least, * return the word "default" as the value from "mask" and "dest", * typically if the host is remote, reached over a default route. * We should probably treat such a mask as "0.0.0.0". * * Define "MASK_DEFAULT_TO_ZERO" to enable this interpretation. * * This is better for Solaris and is probably suitable (or irrelevant) * for others OSes also. But if it breaks another OS, then reduce the * "hash-if 1" below to exclude that OS. * (David Lee, Jan 2006) */ #if 1 # define MASK_DEFAULT_TO_ZERO #endif static int OutputInCIDR=0; /* * Different OSes offer different mechnisms to obtain this information. * Not all this can be determined at configure-time; need a run-time element. * * typedef ... SearchRoute ...: * For routines that interface on these mechanisms. * Return code: * <0: mechanism invalid, so try next mechanism * 0: mechanism worked: good answer * >0: mechanism worked: bad answer * On non-zero, errmsg may have been filled with an error message */ typedef int SearchRoute (char *address, struct in_addr *in , struct in_addr *addr_out, char *best_if, size_t best_iflen , unsigned long *best_netmask, char *errmsg , int errmsglen); static SearchRoute SearchUsingProcRoute; static SearchRoute SearchUsingRouteCmd; static SearchRoute *search_mechs[] = { &SearchUsingProcRoute, &SearchUsingRouteCmd, NULL }; void GetAddress (char **address, char **netmaskbits , char **bcast_arg, char **if_specified); void ValidateNetmaskBits (char *netmaskbits, unsigned long *netmask); int ValidateIFName (const char *ifname, struct ifreq *ifr); int netmask_bits (unsigned long netmask); char * get_first_loopback_netdev(char * ifname); int is_loopback_interface(char * ifname); char * get_ifname(char * buf, char * ifname); int ConvertQuadToInt(char *dest); static const char *cmdname = "findif"; void usage(void); #define PATH_PROC_NET_DEV "/proc/net/dev" #define DELIM '/' #define BAD_BROADCAST (0L) #define MAXSTR 128 static int SearchUsingProcRoute (char *address, struct in_addr *in , struct in_addr *addr_out, char *best_if, size_t best_iflen , unsigned long *best_netmask , char *errmsg, int errmsglen) { unsigned long flags, refcnt, use, gw, mask; unsigned long dest; long metric = LONG_MAX; long best_metric = LONG_MAX; int rc = 0; char buf[2048]; char interface[MAXSTR]; FILE *routefd = NULL; if ((routefd = fopen(PROCROUTE, "r")) == NULL) { snprintf(errmsg, errmsglen , "Cannot open %s for reading" , PROCROUTE); rc = -1; goto out; } /* Skip first (header) line */ if (fgets(buf, sizeof(buf), routefd) == NULL) { snprintf(errmsg, errmsglen , "Cannot skip first line from %s" , PROCROUTE); rc = -1; goto out; } while (fgets(buf, sizeof(buf), routefd) != NULL) { if (sscanf(buf, "%[^\t]\t%lx%lx%lx%lx%lx%lx%lx" , interface, &dest, &gw, &flags, &refcnt, &use , &metric, &mask) != 8) { snprintf(errmsg, errmsglen, "Bad line in %s: %s" , PROCROUTE, buf); rc = -1; goto out; } if ( (in->s_addr&mask) == (in_addr_t)(dest&mask) && metric < best_metric) { best_metric = metric; *best_netmask = mask; strncpy(best_if, interface, best_iflen); } } if (best_metric == LONG_MAX) { snprintf(errmsg, errmsglen, "No route to %s\n", address); rc = 1; } out: if (routefd) { fclose(routefd); } return(rc); } static int SearchUsingRouteCmd (char *address, struct in_addr *in , struct in_addr *addr_out, char *best_if, size_t best_iflen , unsigned long *best_netmask , char *errmsg, int errmsglen) { char mask[20]; char routecmd[MAXSTR]; int best_metric = INT_MAX; char buf[2048]; char interface[MAXSTR]; char *cp, *sp; int done = 0; FILE *routefd = NULL; uint32_t maskbits; /* Open route and get the information */ snprintf (routecmd, sizeof(routecmd), "%s %s %s" , ROUTE, ROUTEPARM, address); routefd = popen (routecmd, "r"); if (routefd == NULL) return (-1); mask[0] = EOS; interface[0] = EOS; while ((done < 3) && fgets(buf, sizeof(buf), routefd)) { int buflen = strnlen(buf, sizeof(buf)); cp = buf; sp = buf + buflen; while (sp!=buf && isspace((int)*(sp-1))) { --sp; } *sp = EOS; buf[buflen] = EOS; if (strstr (buf, "mask:")) { /*strsep(&cp, ":");cp++;*/ cp = strtok(buf, ":"); cp = strtok(NULL, ":");cp++; strncpy(mask, cp, sizeof(mask)); done++; } if (strstr (buf, "interface:")) { /*strsep(&cp, ":");cp++;*/ cp = strtok(buf, ":"); cp = strtok(NULL, ":");cp++; strncpy(interface, cp, sizeof(interface)); done++; } } fclose(routefd); /* * Check to see if mask isn't available. It may not be * returned if multiple IP's are defined. * use 255.255.255.255 for mask then */ /* I'm pretty sure this is the wrong behavior... * I think the right behavior is to declare an error and give up. * The admin didn't define his routes correctly. Fix them. * It's useless to take over an IP address with no way to * return packets to the originator. Without the right subnet * mask, you can't reply to any packets you receive. */ if (strnlen(mask, sizeof(mask)) == 0) { strncpy (mask, "255.255.255.255", sizeof(mask)); } /* * Solaris (at least) can return the word "default" for mask and dest. * For the moment, let's interpret this as: * mask: 0.0.0.0 * This was manifesting itself under "BasicSanityCheck", which tries * to use a remote IP number; these typically use the "default" route. * Better schemes are warmly invited... */ #ifdef MASK_DEFAULT_TO_ZERO if (strncmp(mask, "default", sizeof("default")) == 0) { strncpy (mask, "0.0.0.0", sizeof(mask)); } #endif if (inet_pton(AF_INET, mask, &maskbits) <= 0) { snprintf(errmsg, errmsglen, "mask [%s] not valid.", mask); return(1); } if (inet_pton(AF_INET, address, addr_out) <= 0) { snprintf(errmsg, errmsglen , "IP address [%s] not valid.", address); usage(); return(1); } if ((in->s_addr & maskbits) == (addr_out->s_addr & maskbits)) { if (interface[0] == EOS) { snprintf(errmsg, errmsglen, "No interface found."); return(1); } best_metric = 0; *best_netmask = maskbits; strncpy(best_if, interface, best_iflen); } if (best_metric == INT_MAX) { snprintf(errmsg, errmsglen, "No route to %s\n", address); return(1); } return (0); } /* * Getaddress gets all its real parameters from the OCF environment * variables that its callers already use. */ void GetAddress (char **address, char **netmaskbits , char **bcast_arg, char **if_specified) { /* * Here are out input environment variables: * * OCF_RESKEY_ip ip address * OCF_RESKEY_cidr_netmask netmask of interface * OCF_RESKEY_broadcast broadcast address for interface * OCF_RESKEY_nic interface to assign to * */ *address = getenv("OCF_RESKEY_ip"); *netmaskbits = getenv("OCF_RESKEY_cidr_netmask"); if (*netmaskbits == NULL || **netmaskbits == EOS) { *netmaskbits = getenv("OCF_RESKEY_netmask"); } *bcast_arg = getenv("OCF_RESKEY_broadcast"); *if_specified = getenv("OCF_RESKEY_nic"); } void ValidateNetmaskBits (char *netmaskbits, unsigned long *netmask) { if (netmaskbits != NULL && *netmaskbits != EOS) { size_t nmblen = strnlen(netmaskbits, 3); /* Maximum netmask is 32 */ if (nmblen > 2 || nmblen == 0 || (strspn(netmaskbits, "0123456789") != nmblen)) { fprintf(stderr, "Invalid netmask specification" " [%s]", netmaskbits); usage(); }else{ unsigned long bits = atoi(netmaskbits); if (bits < 1 || bits > 32) { fprintf(stderr , "Invalid netmask specification [%s]" , netmaskbits); usage(); /*not reached */ exit(1); } bits = 32 - bits; *netmask = (1L<<(bits))-1L; *netmask = ((~(*netmask))&0xffffffffUL); *netmask = htonl(*netmask); } } } int ValidateIFName(const char *ifname, struct ifreq *ifr) { int skfd = -1; char *colonptr; if ( (skfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1 ) { fprintf(stderr, "%s\n", strerror(errno)); return 0; } strncpy(ifr->ifr_name, ifname, IFNAMSIZ); /* Contain a ":"? Probably an error, but treat as warning at present */ if ((colonptr = strchr(ifname, ':')) != NULL) { fprintf(stderr, "%s: warning: name may be invalid\n", ifr->ifr_name); } if (ioctl(skfd, SIOCGIFFLAGS, ifr) < 0) { fprintf(stderr, "%s: unknown interface: %s\n" , ifr->ifr_name, strerror(errno)); close(skfd); /* return -1 only if ifname is known to be invalid */ return -1; } close(skfd); return 0; } int netmask_bits(unsigned long netmask) { int j; netmask = netmask & 0xFFFFFFFFUL; for (j=0; j <= 32; ++j) { if ((netmask >> j)&0x1) { break; } } return 32 - j; } char * get_first_loopback_netdev(char * output) { char buf[512]; FILE * fd = NULL; char *rc = NULL; if (!output) { fprintf(stderr, "output buf is a null pointer.\n"); goto out; } fd = fopen(PATH_PROC_NET_DEV, "r"); if (!fd) { fprintf(stderr, "Warning: cannot open %s (%s).\n", PATH_PROC_NET_DEV, strerror(errno)); goto out; } /* Skip the first two lines */ if (!fgets(buf, sizeof(buf), fd) || !fgets(buf, sizeof(buf), fd)) { fprintf(stderr, "Warning: cannot read header from %s.\n", PATH_PROC_NET_DEV); goto out; } while (fgets(buf, sizeof(buf), fd)) { char name[IFNAMSIZ]; if (NULL == get_ifname(buf, name)) { /* Maybe somethin is wrong, anyway continue */ continue; } if (is_loopback_interface(name)) { strncpy(output, name, IFNAMSIZ); rc = output; goto out; } } out: if (fd) { fclose(fd); } return rc; } int is_loopback_interface(char * ifname) { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); if (ValidateIFName(ifname, &ifr) < 0) return 0; if (ifr.ifr_flags & IFF_LOOPBACK) { /* this is a loopback device. */ return 1; } else { return 0; } } char * get_ifname(char * buf, char * ifname) { char * start, * end, * buf_border; buf_border = buf + strnlen(buf, 512); start = buf; while (isspace((int) *start) && (start != buf_border)) { start++; } end = start; while ((*end != ':') && (end != buf_border)) { end++; } if ( start == buf_border || end == buf_border ) { /* Over the border of buf */ return NULL; } *end = '\0'; strncpy(ifname, start, IFNAMSIZ); return ifname; } int ConvertQuadToInt(char *dest) { struct in_addr ad; int bits, j; inet_pton(AF_INET, dest, &ad); bits = 0; j = ntohl(ad.s_addr); while(j != 0){ bits++; j <<= 1; } return (bits); } int main(int argc, char ** argv) { char * address = NULL; char * bcast_arg = NULL; char * netmaskbits = NULL; struct in_addr in; struct in_addr addr_out; unsigned long netmask; char best_if[MAXSTR]; char * if_specified = NULL; struct ifreq ifr; unsigned long best_netmask = INT_MAX; int argerrs = 0; cmdname=argv[0]; memset(&addr_out, 0, sizeof(addr_out)); memset(&in, 0, sizeof(in)); memset(&ifr, 0, sizeof(ifr)); switch (argc) { case 1: /* No -C argument */ break; case 2: /* Hopefully a -C argument */ if (strncmp(argv[1], "-C", sizeof("-C")) != 0) { argerrs=1; } OutputInCIDR=1; break; default: argerrs=1; break; } if (argerrs) { usage(); return(1); } GetAddress (&address, &netmaskbits, &bcast_arg , &if_specified); if (address == NULL || *address == EOS) { fprintf(stderr, "ERROR: IP address parameter is mandatory."); usage(); return(1); } /* Is the IP address we're supposed to find valid? */ if (inet_pton(AF_INET, address, (void *)&in) <= 0) { fprintf(stderr, "IP address [%s] not valid.", address); usage(); return(1); } if(netmaskbits != NULL && *netmaskbits != EOS && strchr(netmaskbits, '.') != NULL) { int len = strlen(netmaskbits); snprintf(netmaskbits, len, "%d", ConvertQuadToInt(netmaskbits)); fprintf(stderr, "Converted dotted-quad netmask to CIDR as: %s\n", netmaskbits); } /* Validate the netmaskbits field */ ValidateNetmaskBits (netmaskbits, &netmask); if (if_specified != NULL && *if_specified != EOS) { if(ValidateIFName(if_specified, &ifr) < 0) { usage(); } strncpy(best_if, if_specified, sizeof(best_if)); *(best_if + sizeof(best_if) - 1) = '\0'; }else{ SearchRoute **sr = search_mechs; char errmsg[MAXSTR] = "No valid mecahnisms"; int rc = -1; - strlcpy(best_if, "UNKNOWN", sizeof(best_if)); /* just in case */ + strcpy(best_if, "UNKNOWN"); while (*sr) { errmsg[0] = '\0'; rc = (*sr) (address, &in, &addr_out, best_if , sizeof(best_if) , &best_netmask, errmsg, sizeof(errmsg)); if (rc >= 0) { /* Mechanism worked */ break; } sr++; } if (rc != 0) { /* No route, or all mechanisms failed */ if (*errmsg) { fprintf(stderr, "%s", errmsg); return(1); } } } if (netmaskbits) { best_netmask = netmask; }else if (best_netmask == 0L) { /* On some distirbutions, there is no loopback related route item, this leads to the error here. My fix may be not good enough, please FIXME */ if (0 == strncmp(address, "127", 3)) { if (NULL != get_first_loopback_netdev(best_if)) { best_netmask = 0x000000ff; } else { fprintf(stderr, "No loopback interface found.\n"); return(1); } } else { fprintf(stderr , "ERROR: Cannot use default route w/o netmask [%s]\n" , address); return(1); } } /* Did they tell us the broadcast address? */ if (bcast_arg && *bcast_arg != EOS) { /* Yes, they gave us a broadcast address. * It at least should be a valid IP address */ struct in_addr bcast_addr; if (inet_pton(AF_INET, bcast_arg, (void *)&bcast_addr) <= 0) { fprintf(stderr, "Invalid broadcast address [%s].", bcast_arg); usage(); } best_netmask = htonl(best_netmask); if (!OutputInCIDR) { printf("%s\tnetmask %d.%d.%d.%d\tbroadcast %s\n" , best_if , (int)((best_netmask>>24) & 0xff) , (int)((best_netmask>>16) & 0xff) , (int)((best_netmask>>8) & 0xff) , (int)(best_netmask & 0xff) , bcast_arg); }else{ printf("%s\tnetmask %d\tbroadcast %s\n" , best_if , netmask_bits(best_netmask) , bcast_arg); } }else{ /* No, we use a common broadcast address convention */ unsigned long def_bcast; /* Common broadcast address */ def_bcast = (in.s_addr | (~best_netmask)); #if DEBUG fprintf(stderr, "best_netmask = %08lx, def_bcast = %08lx\n" , best_netmask, def_bcast); #endif /* Make things a bit more machine-independent */ best_netmask = htonl(best_netmask); def_bcast = htonl(def_bcast); if (!OutputInCIDR) { printf("%s\tnetmask %d.%d.%d.%d\tbroadcast %d.%d.%d.%d\n" , best_if , (int)((best_netmask>>24) & 0xff) , (int)((best_netmask>>16) & 0xff) , (int)((best_netmask>>8) & 0xff) , (int)(best_netmask & 0xff) , (int)((def_bcast>>24) & 0xff) , (int)((def_bcast>>16) & 0xff) , (int)((def_bcast>>8) & 0xff) , (int)(def_bcast & 0xff)); }else{ printf("%s\tnetmask %d\tbroadcast %d.%d.%d.%d\n" , best_if , netmask_bits(best_netmask) , (int)((def_bcast>>24) & 0xff) , (int)((def_bcast>>16) & 0xff) , (int)((def_bcast>>8) & 0xff) , (int)(def_bcast & 0xff)); } } return(0); } void usage(void) { fprintf(stderr, "\n" - "%s version " VERSION " Copyright Alan Robertson\n" + "%s version 2.99.1 Copyright Alan Robertson\n" "\n" "Usage: %s [-C]\n" "Options:\n" " -C: Output netmask as the number of bits rather " "than as 4 octets.\n" "Environment variables:\n" "OCF_RESKEY_ip ip address (mandatory!)\n" "OCF_RESKEY_cidr_netmask netmask of interface\n" "OCF_RESKEY_broadcast broadcast address for interface\n" "OCF_RESKEY_nic interface to assign to\n" , cmdname, cmdname); exit(1); } /* Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT eth0 33D60987 00000000 0005 0 0 0 FFFFFFFF 0 0 0 eth0 00D60987 00000000 0001 0 0 0 00FFFFFF 0 0 0 lo 0000007F 00000000 0001 0 0 0 000000FF 0 0 0 eth0 00000000 FED60987 0003 0 0 0 00000000 0 0 0 netstat -rn outpug from RedHat Linux 6.0 Kernel IP routing table Destination Gateway Genmask Flags MSS Window irtt Iface 192.168.85.2 0.0.0.0 255.255.255.255 UH 0 0 0 eth1 10.0.0.2 0.0.0.0 255.255.255.255 UH 0 0 0 eth2 208.132.134.61 0.0.0.0 255.255.255.255 UH 0 0 0 eth0 208.132.134.32 0.0.0.0 255.255.255.224 U 0 0 0 eth0 192.168.85.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1 10.0.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth2 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo 0.0.0.0 208.132.134.33 0.0.0.0 UG 0 0 0 eth0 |-------------------------------------------------------------------------------- netstat -rn output from FreeBSD 3.3 Routing tables Internet: Destination Gateway Flags Refs Use Netif Expire default 209.61.94.161 UGSc 3 8 pn0 192.168 link#1 UC 0 0 xl0 192.168.0.2 0:60:8:a4:91:fd UHLW 0 38 lo0 192.168.0.255 ff:ff:ff:ff:ff:ff UHLWb 1 7877 xl0 209.61.94.160/29 link#2 UC 0 0 pn0 209.61.94.161 0:a0:cc:26:c2:ea UHLW 6 17265 pn0 1105 209.61.94.162 0:a0:cc:27:1c:fb UHLW 1 568 pn0 1098 209.61.94.163 0:a0:cc:29:1f:86 UHLW 0 4749 pn0 1095 209.61.94.166 0:a0:cc:27:2d:e1 UHLW 0 12 lo0 209.61.94.167 ff:ff:ff:ff:ff:ff UHLWb 0 10578 pn0 |-------------------------------------------------------------------------------- netstat -rn output from FreeBSD 4.2 Routing tables Internet: Destination Gateway Flags Refs Use Netif Expire default 64.65.195.1 UGSc 1 11 dc0 64.65.195/24 link#1 UC 0 0 dc0 => 64.65.195.1 0:3:42:3b:0:dd UHLW 2 0 dc0 1131 64.65.195.184 0:a0:cc:29:1f:86 UHLW 2 18098 dc0 1119 64.65.195.194 0:a0:cc:27:2d:e1 UHLW 3 335161 dc0 943 64.65.195.200 52:54:0:db:33:b3 UHLW 0 13 dc0 406 64.65.195.255 ff:ff:ff:ff:ff:ff UHLWb 1 584 dc0 127.0.0.1 127.0.0.1 UH 0 0 lo0 192.168/16 link#2 UC 0 0 vx0 => 192.168.0.1 0:20:af:e2:f0:36 UHLW 0 2 lo0 192.168.255.255 ff:ff:ff:ff:ff:ff UHLWb 0 1 vx0 Internet6: Destination Gateway Flags Netif Expire ::1 ::1 UH lo0 fe80::%dc0/64 link#1 UC dc0 fe80::%vx0/64 link#2 UC vx0 fe80::%lo0/64 fe80::1%lo0 Uc lo0 ff01::/32 ::1 U lo0 ff02::%dc0/32 link#1 UC dc0 ff02::%vx0/32 link#2 UC vx0 ff02::%lo0/32 fe80::1%lo0 UC lo0 */