keepalived-1.2.2
authorAlexandre Cassen <acassen@freebox.fr>
Sun, 9 Jan 2011 21:58:56 +0000 (22:58 +0100)
committerAlexandre Cassen <acassen@freebox.fr>
Sun, 9 Jan 2011 22:03:11 +0000 (23:03 +0100)
* IPv6 duty ;)
* IPv6 : extended autoconf script to support libnl detection.
         IPv6 IPVS kernel subsystem is reachable through
         generic netlink configuration interface.
* IPv6 : Enhanced libipvs-2.6 to support generic netlink
         configuration interface. If generic netlink is
         available with kernel then it will be the
         prefered path to configure IPVS.
* IPv6 : Enhanced the whole checker API to use
         sockaddr_storage.
* IPv6 : Enhanced the whole core framework to use
         sockaddr_storage.
* IPv6 : Enhanced all checkers to use sockaddr_storage.
* fixed a long time pending issue in all checkers. If
  first connection attempt to remote peer was failing
  no more check was performed to service... Up on error
  connecting remote peer simply register a new timer for
  next check. This is specially needed in IPv6 context
  where a unreachable host can be reached at delayed time.

35 files changed:
ChangeLog
VERSION
configure
configure.in
keepalived.spec.in
keepalived/check/check_api.c
keepalived/check/check_daemon.c
keepalived/check/check_data.c
keepalived/check/check_http.c
keepalived/check/check_misc.c
keepalived/check/check_parser.c
keepalived/check/check_smtp.c
keepalived/check/check_ssl.c
keepalived/check/check_tcp.c
keepalived/check/ipvswrapper.c
keepalived/check/ipwrapper.c
keepalived/core/global_data.c
keepalived/core/global_parser.c
keepalived/core/layer4.c
keepalived/core/smtp.c
keepalived/include/check_api.h
keepalived/include/check_data.h
keepalived/include/check_http.h
keepalived/include/check_smtp.h
keepalived/include/check_tcp.h
keepalived/include/global_data.h
keepalived/include/ipvswrapper.h
keepalived/include/layer4.h
keepalived/include/smtp.h
keepalived/libipvs-2.6/Makefile.in
keepalived/libipvs-2.6/libipvs.c
keepalived/libipvs-2.6/libipvs.h
keepalived/vrrp/vrrp_netlink.c
lib/utils.c
lib/utils.h

index 29d58d5..1aabe8a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2011-01-09  Alexandre Cassen  <acassen@linux-vs.org>
+       * keepalived-1.2.2 released.
+       * IPv6 : extended autoconf script to support libnl detection.
+                IPv6 IPVS kernel subsystem is reachable through
+                generic netlink configuration interface.
+       * IPv6 : Enhanced libipvs-2.6 to support generic netlink
+                configuration interface. If generic netlink is
+                available with kernel then it will be the
+                prefered path to configure IPVS.
+       * IPv6 : Enhanced the whole checker API to use
+                sockaddr_storage.
+       * IPv6 : Enhanced the whole core framework to use
+                sockaddr_storage.
+       * IPv6 : Enhanced all checkers to use sockaddr_storage.
+       * fixed a long time pending issue in all checkers. If
+         first connection attempt to remote peer was failing
+         no more check was performed to service... Up on error
+         connecting remote peer simply register a new timer for
+         next check. This is specially needed in IPv6 context
+         where a unreachable host can be reached at delayed time.
+
 2010-12-08  Alexandre Cassen  <acassen@linux-vs.org>
        * keepalived-1.2.1 released.
        * Vincent Bernat <bernat <at> luffy.cx>:
diff --git a/VERSION b/VERSION
index 6085e94..23aa839 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.2.1
+1.2.2
index e8a4429..4b6bc79 100755 (executable)
--- a/configure
+++ b/configure
@@ -594,6 +594,7 @@ ac_includes_default="\
 ac_subst_vars='LTLIBOBJS
 LIBOBJS
 VRRP_SUPPORT
+USE_NL
 IPVS_SUPPORT
 VERSION_DATE
 VERSION
@@ -3841,6 +3842,55 @@ else
   as_fn_error "Popt libraries is required" "$LINENO" 5
 fi
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_handle_alloc in -lnl" >&5
+$as_echo_n "checking for nl_handle_alloc in -lnl... " >&6; }
+if test "${ac_cv_lib_nl_nl_handle_alloc+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char nl_handle_alloc ();
+int
+main ()
+{
+return nl_handle_alloc ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_nl_nl_handle_alloc=yes
+else
+  ac_cv_lib_nl_nl_handle_alloc=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nl_nl_handle_alloc" >&5
+$as_echo "$ac_cv_lib_nl_nl_handle_alloc" >&6; }
+if test "x$ac_cv_lib_nl_nl_handle_alloc" = x""yes; then :
+
+    USE_NL="LIBIPVS_USE_NL"
+    LIBS="$LIBS -lnl"
+
+else
+
+    USE_NL="LIBIPVS_DONTUSE_NL"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: keepalived will be built without libnl support." >&5
+$as_echo "$as_me: WARNING: keepalived will be built without libnl support." >&2;}
+
+fi
+
 
 CPPFLAGS="$CPPFLAGS -I$kernelinc"
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for kernel version" >&5
@@ -3987,6 +4037,7 @@ fi
 
 
 
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
 $as_echo_n "checking for an ANSI C-conforming const... " >&6; }
 if test "${ac_cv_c_const+set}" = set; then :
@@ -4275,8 +4326,6 @@ if test "$IPVS_SUPPORT" = "_WITH_LVS_"; then
     OUTPUT_TARGET="$OUTPUT_TARGET keepalived/libipvs-2.6/Makefile"
   elif test "$KERN" = "_KRNL_2_4_"; then
     OUTPUT_TARGET="$OUTPUT_TARGET keepalived/libipvs-2.4/Makefile"
-  else
-    OUTPUT_TARGET="$OUTPUT_TARGET keepalived/libipfwc/Makefile"
   fi
 fi
 ac_config_files="$ac_config_files $OUTPUT_TARGET"
@@ -5446,6 +5495,11 @@ if test "${IPVS_SUPPORT}" = "_WITH_LVS_"; then
   elif test "${IPVS_SYNCD}" = "_WITHOUT_IPVS_SYNCD_"; then
     echo "IPVS sync daemon support : No"
   fi
+  if test "${USE_NL}" = "LIBIPVS_USE_NL"; then
+    echo "IPVS use libnl           : Yes"
+  else
+    echo "IPVS use libnl           : No"
+  fi
 else
   echo "Use IPVS Framework       : No"
   echo "IPVS sync daemon support : No"
index 96af8ef..fd41a9d 100644 (file)
@@ -51,6 +51,15 @@ dnl ----[ Checks for libraries ]----
 AC_CHECK_LIB(crypto, MD5_Init,,AC_MSG_ERROR([OpenSSL libraries are required]))
 AC_CHECK_LIB(ssl, SSL_CTX_new,,AC_MSG_ERROR([OpenSSL libraries are required]))
 AC_CHECK_LIB(popt, poptGetContext,,AC_MSG_ERROR([Popt libraries is required]))
+AC_CHECK_LIB(nl, nl_handle_alloc,
+  [
+    USE_NL="LIBIPVS_USE_NL"
+    LIBS="$LIBS -lnl"
+  ],
+  [
+    USE_NL="LIBIPVS_DONTUSE_NL"
+    AC_MSG_WARN([keepalived will be built without libnl support.])
+  ])
 
 dnl ----[ Kernel version check ]----
 CPPFLAGS="$CPPFLAGS -I$kernelinc"
@@ -170,6 +179,7 @@ fi
 AC_SUBST(VERSION)
 AC_SUBST(VERSION_DATE)
 AC_SUBST(IPVS_SUPPORT)
+AC_SUBST(USE_NL)
 AC_SUBST(VRRP_SUPPORT)
 
 dnl ----[ Checks for typedefs, structures, and compiler characteristics ]----
@@ -194,8 +204,6 @@ if test "$IPVS_SUPPORT" = "_WITH_LVS_"; then
     OUTPUT_TARGET="$OUTPUT_TARGET keepalived/libipvs-2.6/Makefile"
   elif test "$KERN" = "_KRNL_2_4_"; then
     OUTPUT_TARGET="$OUTPUT_TARGET keepalived/libipvs-2.4/Makefile"
-  else
-    OUTPUT_TARGET="$OUTPUT_TARGET keepalived/libipfwc/Makefile"
   fi
 fi
 AC_OUTPUT($OUTPUT_TARGET)
@@ -223,6 +231,11 @@ if test "${IPVS_SUPPORT}" = "_WITH_LVS_"; then
   elif test "${IPVS_SYNCD}" = "_WITHOUT_IPVS_SYNCD_"; then
     echo "IPVS sync daemon support : No"
   fi
+  if test "${USE_NL}" = "LIBIPVS_USE_NL"; then
+    echo "IPVS use libnl           : Yes"
+  else
+    echo "IPVS use libnl           : No"
+  fi
 else
   echo "Use IPVS Framework       : No"
   echo "IPVS sync daemon support : No"
index 69fa2cd..82c8bc6 100644 (file)
@@ -6,7 +6,7 @@
 
 Summary: HA monitor built upon LVS, VRRP and services poller
 Name: keepalived
-Version: 1.2.0
+Version: 1.2.2
 Release: 5
 License: GPL
 Group: Applications/System
index 40c2750..e95f2af 100644 (file)
@@ -52,8 +52,9 @@ static void
 dump_checker(void *data_obj)
 {
        checker *checker_obj = data_obj;
-       log_message(LOG_INFO, " %s:%d", inet_ntop2(CHECKER_RIP(checker_obj))
-              , ntohs(CHECKER_RPORT(checker_obj)));
+       log_message(LOG_INFO, " %s:%d"
+                           , inet_sockaddrtos(&checker_obj->rs->addr)
+                           , ntohs(inet_sockaddrport(&checker_obj->rs->addr)));
        (*checker_obj->dump_func) (checker_obj);
 }
 
@@ -91,6 +92,28 @@ queue_checker(void (*free_func) (void *), void (*dump_func) (void *)
        }
 }
 
+/* Set dst */
+void
+checker_set_dst(struct sockaddr_storage *dst)
+{
+       virtual_server *vs = LIST_TAIL_DATA(check_data->vs);
+       real_server *rs = LIST_TAIL_DATA(vs->rs);
+
+       *dst = rs->addr;
+}
+
+void
+checker_set_dst_port(struct sockaddr_storage *dst, uint16_t port)
+{
+       if (dst->ss_family == AF_INET6) {
+               struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) dst;
+               addr6->sin6_port = port;
+       } else {
+               struct sockaddr_in *addr4 = (struct sockaddr_in *) dst;
+               addr4->sin_port = port;
+       }
+}
+
 /* dump the checkers_queue */
 void
 dump_checkers_queue(void)
@@ -126,10 +149,9 @@ register_checkers_thread(void)
 
        for (e = LIST_HEAD(checkers_queue); e; ELEMENT_NEXT(e)) {
                checker_obj = ELEMENT_DATA(e);
-               log_message(LOG_INFO,
-                      "Activating healtchecker for service [%s:%d]",
-                      inet_ntop2(CHECKER_RIP(checker_obj)),
-                      ntohs(CHECKER_RPORT(checker_obj)));
+               log_message(LOG_INFO, "Activating healtchecker for service [%s:%d]"
+                                   , inet_sockaddrtos(&checker_obj->rs->addr)
+                                   , ntohs(inet_sockaddrport(&checker_obj->rs->addr)));
                CHECKER_ENABLE(checker_obj);
                if (checker_obj->launch)
                        thread_add_timer(master, checker_obj->launch, checker_obj,
@@ -139,34 +161,50 @@ register_checkers_thread(void)
 
 /* Sync checkers activity with netlink kernel reflection */
 void
-update_checker_activity(uint32_t address, int enable)
+update_checker_activity(sa_family_t family, void *address, int enable)
 {
        checker *checker_obj;
+       sa_family_t vip_family;
        element e;
+       char addr_str[INET6_ADDRSTRLEN];
+       void *addr;
 
        /* Display netlink operation */
-       if (debug & 32)
-               log_message(LOG_INFO, "Netlink reflector reports IP %s %s",
-                      inet_ntop2(address), (enable) ? "added" : "removed");
+       if (debug & 32) {
+               inet_ntop(family, address, addr_str, sizeof(addr_str));
+               log_message(LOG_INFO, "Netlink reflector reports IP %s %s"
+                                   , addr_str, (enable) ? "added" : "removed");
+       }
 
        /* Processing Healthcheckers queue */
-       if (!LIST_ISEMPTY(checkers_queue))
+       if (!LIST_ISEMPTY(checkers_queue)) {
                for (e = LIST_HEAD(checkers_queue); e; ELEMENT_NEXT(e)) {
                        checker_obj = ELEMENT_DATA(e);
-                       if (CHECKER_VIP(checker_obj) == address && CHECKER_HA_SUSPEND(checker_obj)) {
+                       vip_family = checker_obj->vs->addr.ss_family;
+
+                       if (vip_family != family)
+                               continue;
+
+                       if (family == AF_INET6) {
+                               addr = (void *) &((struct sockaddr_in6 *)&checker_obj->vs->addr)->sin6_addr;
+                       } else {
+                               addr = (void *) &((struct sockaddr_in *)&checker_obj->vs->addr)->sin_addr;
+                       }
+
+                       if (inaddr_equal(family, addr, address) &&
+                           CHECKER_HA_SUSPEND(checker_obj)) {
                                if (!CHECKER_ENABLED(checker_obj) && enable)
-                                       log_message(LOG_INFO,
-                                              "Activating healtchecker for service [%s:%d]",
-                                              inet_ntop2(CHECKER_RIP(checker_obj)),
-                                              ntohs(CHECKER_RPORT(checker_obj)));
+                                       log_message(LOG_INFO, "Activating healtchecker for service [%s:%d]"
+                                                           , inet_sockaddrtos(&checker_obj->rs->addr)
+                                                           , ntohs(inet_sockaddrport(&checker_obj->rs->addr)));
                                if (CHECKER_ENABLED(checker_obj) && !enable)
-                                       log_message(LOG_INFO,
-                                              "Suspending healtchecker for service [%s:%d]",
-                                              inet_ntop2(CHECKER_RIP(checker_obj)),
-                                              ntohs(CHECKER_RPORT(checker_obj)));
+                                       log_message(LOG_INFO, "Suspending healtchecker for service [%s:%d]"
+                                                           , inet_sockaddrtos(&checker_obj->rs->addr)
+                                                           , ntohs(inet_sockaddrport(&checker_obj->rs->addr)));
                                checker_obj->enabled = enable;
                        }
                }
+       }
 }
 
 /* Install checkers keywords */
index a17f800..877b524 100644 (file)
@@ -22,6 +22,8 @@
 
 #include "check_daemon.h"
 #include "check_parser.h"
+#include "ipwrapper.h"
+#include "ipvswrapper.h"
 #include "check_data.h"
 #include "check_ssl.h"
 #include "check_api.h"
index 1f963ef..e1a7fbe 100644 (file)
@@ -20,6 +20,7 @@
  * Copyright (C) 2001-2010 Alexandre Cassen, <acassen@freebox.fr>
  */
 
+#include <netdb.h>
 #include "check_data.h"
 #include "check_api.h"
 #include "logger.h"
@@ -103,13 +104,13 @@ dump_vsg_entry(void *data)
                log_message(LOG_INFO, "   FWMARK = %d", vsg_entry->vfwmark);
        else if (vsg_entry->range)
                log_message(LOG_INFO, "   VIP Range = %s-%d, VPORT = %d"
-                      , inet_ntop2(SVR_IP(vsg_entry))
-                      , vsg_entry->range
-                      , ntohs(SVR_PORT(vsg_entry)));
+                                   , inet_sockaddrtos(&vsg_entry->addr)
+                                   , vsg_entry->range
+                                   , ntohs(inet_sockaddrport(&vsg_entry->addr)));
        else
                log_message(LOG_INFO, "   VIP = %s, VPORT = %d"
-                      , inet_ntop2(SVR_IP(vsg_entry))
-                      , ntohs(SVR_PORT(vsg_entry)));
+                                   , inet_sockaddrtos(&vsg_entry->addr)
+                                   , ntohs(inet_sockaddrport(&vsg_entry->addr)));
 }
 void
 alloc_vsg(char *gname)
@@ -138,9 +139,8 @@ alloc_vsg_entry(vector strvec)
                new->vfwmark = atoi(VECTOR_SLOT(strvec, 1));
                list_add(vsg->vfwmark, new);
        } else {
-               inet_ston(VECTOR_SLOT(strvec, 0), &new->addr_ip);
                new->range = inet_stor(VECTOR_SLOT(strvec, 0));
-               new->addr_port = htons(atoi(VECTOR_SLOT(strvec, 1)));
+               inet_stosockaddr(VECTOR_SLOT(strvec, 0), VECTOR_SLOT(strvec, 1), &new->addr);
                if (!new->range)
                        list_add(vsg->addr_ip, new);
                else
@@ -171,8 +171,8 @@ dump_vs(void *data)
        else if (vs->vfwmark)
                log_message(LOG_INFO, " VS FWMARK = %d", vs->vfwmark);
        else
-               log_message(LOG_INFO, " VIP = %s, VPORT = %d", inet_ntop2(SVR_IP(vs))
-                      , ntohs(SVR_PORT(vs)));
+               log_message(LOG_INFO, " VIP = %s, VPORT = %d"
+                                   , inet_sockaddrtos(&vs->addr), ntohs(inet_sockaddrport(&vs->addr)));
        if (vs->virtualhost)
                log_message(LOG_INFO, "   VirtualHost = %s", vs->virtualhost);
        log_message(LOG_INFO, "   delay_loop = %lu, lb_algo = %s",
@@ -214,9 +214,9 @@ dump_vs(void *data)
        }
 
        if (vs->s_svr) {
-               log_message(LOG_INFO, "   sorry server = %s:%d",
-                      inet_ntop2(SVR_IP(vs->s_svr))
-                      , ntohs(SVR_PORT(vs->s_svr)));
+               log_message(LOG_INFO, "   sorry server = %s:%d"
+                                   , inet_sockaddrtos(&vs->s_svr->addr)
+                                   , ntohs(inet_sockaddrport(&vs->s_svr->addr)));
        }
        if (!LIST_ISEMPTY(vs->rs))
                dump_list(vs->rs);
@@ -236,9 +236,9 @@ alloc_vs(char *ip, char *port)
        } else if (!strcmp(ip, "fwmark")) {
                new->vfwmark = atoi(port);
        } else {
-               inet_ston(ip, &new->addr_ip);
-               new->addr_port = htons(atoi(port));
+               inet_stosockaddr(ip, port, &new->addr);
        }
+
        new->delay_loop = KEEPALIVED_DEFAULT_DELAY;
        strncpy(new->timeout_persistence, "0", 1);
        new->virtualhost = NULL;
@@ -262,8 +262,7 @@ alloc_ssvr(char *ip, char *port)
        vs->s_svr = (real_server *) MALLOC(sizeof (real_server));
        vs->s_svr->weight = 1;
        vs->s_svr->iweight = 1;
-       inet_ston(ip, &vs->s_svr->addr_ip);
-       vs->s_svr->addr_port = htons(atoi(port));
+       inet_stosockaddr(ip, port, &vs->s_svr->addr);
 }
 
 /* Real server facility functions */
@@ -280,10 +279,11 @@ static void
 dump_rs(void *data)
 {
        real_server *rs = data;
-       log_message(LOG_INFO, "   RIP = %s, RPORT = %d, WEIGHT = %d",
-              inet_ntop2(SVR_IP(rs))
-              , ntohs(SVR_PORT(rs))
-              , rs->weight);
+
+       log_message(LOG_INFO, "   RIP = %s, RPORT = %d, WEIGHT = %d"
+                           , inet_sockaddrtos(&rs->addr)
+                           , ntohs(inet_sockaddrport(&rs->addr))
+                           , rs->weight);
        if (rs->inhibit)
                log_message(LOG_INFO, "     -> Inhibit service on failure");
        if (rs->notify_up)
@@ -307,9 +307,8 @@ alloc_rs(char *ip, char *port)
        real_server *new;
 
        new = (real_server *) MALLOC(sizeof (real_server));
+       inet_stosockaddr(ip, port, &new->addr);
 
-       inet_ston(ip, &new->addr_ip);
-       new->addr_port = htons(atoi(port));
        new->weight = 1;
        new->iweight = 1;
        new->failed_checkers = alloc_list(free_failed_checkers, NULL);
index 39f5621..5f2c0c4 100644 (file)
@@ -76,12 +76,9 @@ dump_http_get_check(void *data)
                log_message(LOG_INFO, "   Keepalive method = HTTP_GET");
        else
                log_message(LOG_INFO, "   Keepalive method = SSL_GET");
-       if (http_get_chk->connection_port)
-               log_message(LOG_INFO, "   Connection port = %d",
-                      ntohs(http_get_chk->connection_port));
-       if (http_get_chk->bindto)
-               log_message(LOG_INFO, "   Bind to = %s",
-                      inet_ntop2(http_get_chk->bindto));
+       log_message(LOG_INFO, "   Connection port = %d", ntohs(inet_sockaddrport(&http_get_chk->dst)));
+       if (http_get_chk->bindto.ss_family)
+               log_message(LOG_INFO, "   Bind to = %s", inet_sockaddrtos(&http_get_chk->bindto));
        log_message(LOG_INFO, "   Connection timeout = %lu",
               http_get_chk->connection_to/TIMER_HZ);
        log_message(LOG_INFO, "   Nb get retry = %d", http_get_chk->nb_get_retry);
@@ -112,6 +109,7 @@ http_get_handler(vector strvec)
 
        /* queue new checker */
        http_get_chk = alloc_http_get(str);
+       checker_set_dst(&http_get_chk->dst);
        queue_checker(free_http_get_check, dump_http_get_check,
                      http_connect_thread, http_get_chk);
 }
@@ -120,14 +118,14 @@ void
 connect_p_handler(vector strvec)
 {
        http_get_checker *http_get_chk = CHECKER_GET();
-       http_get_chk->connection_port = htons(CHECKER_VALUE_INT(strvec));
+       checker_set_dst_port(&http_get_chk->dst, htons(CHECKER_VALUE_INT(strvec)));
 }
 
 void
 bindto_handler(vector strvec)
 {
        http_get_checker *http_get_chk = CHECKER_GET();
-       inet_ston(VECTOR_SLOT(strvec, 1), &http_get_chk->bindto);
+       inet_stosockaddr(VECTOR_SLOT(strvec, 1), 0, &http_get_chk->bindto);
 }
 
 void
@@ -254,28 +252,6 @@ install_ssl_check_keyword(void)
  *     http_handle_response (next checker thread registration)
  */
 
-uint16_t
-get_service_port(checker * checker_obj)
-{
-       http_get_checker *http_get_check = CHECKER_ARG(checker_obj);
-       uint16_t addr_port;
-
-       /*
-        *  Set the remote connection port.
-        *  If a specific checker port is specified, we used this.
-        *  If we are balancing all services (host rather than service),
-        *  then assume we want to use default ports for HTTP or HTTPS.
-        *  Known as 'Layer3 stickyness'.
-        */
-       addr_port = CHECKER_RPORT(checker_obj);
-       if (!addr_port)
-               addr_port =
-                   htons((http_get_check->proto == PROTO_SSL) ? 443 : 80);
-       if (http_get_check->connection_port)
-               addr_port = http_get_check->connection_port;
-       return addr_port;
-}
-
 /*
  * Simple epilog functions. Handling event timeout.
  * Finish the checker with memory managment or url rety check.
@@ -292,7 +268,6 @@ epilog(thread * thread_obj, int method, int t, int c)
        http_get_checker *http_get_check = CHECKER_ARG(checker_obj);
        http_arg *http_arg_obj = HTTP_ARG(http_get_check);
        REQ *req = HTTP_REQ(http_arg_obj);
-       uint16_t addr_port = get_service_port(checker_obj);
        long delay = 0;
 
        if (method) {
@@ -309,8 +284,8 @@ epilog(thread * thread_obj, int method, int t, int c)
        if (http_arg_obj->retry_it > http_get_check->nb_get_retry-1) {
                if (svr_checker_up(checker_obj->id, checker_obj->rs)) {
                        log_message(LOG_INFO, "Check on service [%s:%d] failed after %d retry."
-                              , inet_ntop2(CHECKER_RIP(checker_obj))
-                              , ntohs(addr_port), http_arg_obj->retry_it);
+                              , inet_sockaddrtos(&http_get_check->dst)
+                              , ntohs(inet_sockaddrport(&http_get_check->dst)), http_arg_obj->retry_it);
                        smtp_alert(checker_obj->rs, NULL, NULL,
                                   "DOWN",
                                   "=> CHECK failed on service"
@@ -362,12 +337,12 @@ int
 timeout_epilog(thread * thread_obj, char *smtp_msg, char *debug_msg)
 {
        checker *checker_obj = THREAD_ARG(thread_obj);
-       uint16_t addr_port = get_service_port(checker_obj);
+       http_get_checker *http_get_check = CHECKER_ARG(checker_obj);
 
-       log_message(LOG_INFO, "Timeout %s server [%s:%d].",
-              debug_msg
-              , inet_ntop2(CHECKER_RIP(checker_obj))
-              , ntohs(addr_port));
+       log_message(LOG_INFO, "Timeout %s server [%s:%d]."
+                           , debug_msg
+                           , inet_sockaddrtos(&http_get_check->dst)
+                           , ntohs(inet_sockaddrport(&http_get_check->dst)));
 
        /* check if server is currently alive */
        if (svr_checker_up(checker_obj->id, checker_obj->rs)) {
@@ -399,7 +374,6 @@ http_handle_response(thread * thread_obj, unsigned char digest[16]
        http_get_checker *http_get_check = CHECKER_ARG(checker_obj);
        http_arg *http_arg_obj = HTTP_ARG(http_get_check);
        REQ *req = HTTP_REQ(http_arg_obj);
-       uint16_t addr_port = get_service_port(checker_obj);
        int r, di = 0;
        char *digest_tmp;
        url *fetched_url = fetch_next_url(http_get_check);
@@ -418,8 +392,9 @@ http_handle_response(thread * thread_obj, unsigned char digest[16]
                                log_message(LOG_INFO,
                                       "HTTP status code error to [%s:%d] url(%s)"
                                       ", status_code [%d].",
-                                      inet_ntop2(CHECKER_RIP(checker_obj)),
-                                      ntohs(addr_port), fetched_url->path,
+                                      inet_sockaddrtos(&http_get_check->dst),
+                                      ntohs(inet_sockaddrport(&http_get_check->dst)),
+                                      fetched_url->path,
                                       req->status_code);
                                smtp_alert(checker_obj->rs, NULL, NULL,
                                           "DOWN",
@@ -429,9 +404,9 @@ http_handle_response(thread * thread_obj, unsigned char digest[16]
                                                             , checker_obj->vs
                                                             , checker_obj->rs);
                        } else {
-                               DBG("HTTP Status_code to [%s:%d] url(%d) = [%d].",
-                                   inet_ntop2(CHECKER_RIP(checker_obj))
-                                   , ntohs(addr_port)
+                               DBG("HTTP Status_code to [%s:%d] url(%d) = [%d]."
+                                   , inet_sockaddrtos(&http_get_check->dst)
+                                   , ntohs(inet_sockaddrport(&http_get_check->dst))
                                    , http_arg_obj->url_it + 1
                                    , req->status_code);
                                /*
@@ -444,9 +419,9 @@ http_handle_response(thread * thread_obj, unsigned char digest[16]
                } else {
                        if (!svr_checker_up(checker_obj->id, checker_obj->rs))
                                log_message(LOG_INFO,
-                                      "HTTP status code success to [%s:%d] url(%d).",
-                                      inet_ntop2(CHECKER_RIP(checker_obj))
-                                      , ntohs(addr_port)
+                                      "HTTP status code success to [%s:%d] url(%d)."
+                                      , inet_sockaddrtos(&http_get_check->dst)
+                                      , ntohs(inet_sockaddrport(&http_get_check->dst))
                                       , http_arg_obj->url_it + 1);
                        return epilog(thread_obj, 1, 1, 0) + 1;
                }
@@ -467,8 +442,9 @@ http_handle_response(thread * thread_obj, unsigned char digest[16]
                                log_message(LOG_INFO,
                                       "MD5 digest error to [%s:%d] url[%s]"
                                       ", MD5SUM [%s].",
-                                      inet_ntop2(CHECKER_RIP(checker_obj)),
-                                      ntohs(addr_port), fetched_url->path,
+                                      inet_sockaddrtos(&http_get_check->dst),
+                                      ntohs(inet_sockaddrport(&http_get_check->dst)),
+                                      fetched_url->path,
                                       digest_tmp);
                                smtp_alert(checker_obj->rs, NULL, NULL,
                                           "DOWN",
@@ -478,9 +454,9 @@ http_handle_response(thread * thread_obj, unsigned char digest[16]
                                                             , checker_obj->vs
                                                             , checker_obj->rs);
                        } else {
-                               DBG("MD5SUM to [%s:%d] url(%d) = [%s].",
-                                   inet_ntop2(CHECKER_RIP(checker_obj))
-                                   , ntohs(addr_port)
+                               DBG("MD5SUM to [%s:%d] url(%d) = [%s]."
+                                   , inet_sockaddrtos(&http_get_check->dst)
+                                   , ntohs(inet_sockaddrport(&http_get_check->dst))
                                    , http_arg_obj->url_it + 1
                                    , digest_tmp);
                                /*
@@ -493,9 +469,9 @@ http_handle_response(thread * thread_obj, unsigned char digest[16]
                        return epilog(thread_obj, 2, 0, 1);
                } else {
                        if (!svr_checker_up(checker_obj->id, checker_obj->rs))
-                               log_message(LOG_INFO, "MD5 digest success to [%s:%d] url(%d).",
-                                      inet_ntop2(CHECKER_RIP(checker_obj))
-                                      , ntohs(addr_port)
+                               log_message(LOG_INFO, "MD5 digest success to [%s:%d] url(%d)."
+                                      , inet_sockaddrtos(&http_get_check->dst)
+                                      , ntohs(inet_sockaddrport(&http_get_check->dst))
                                       , http_arg_obj->url_it + 1);
                        FREE(digest_tmp);
                        return epilog(thread_obj, 1, 1, 0) + 1;
@@ -539,7 +515,6 @@ http_read_thread(thread * thread_obj)
        http_get_checker *http_get_check = CHECKER_ARG(checker_obj);
        http_arg *http_arg_obj = HTTP_ARG(http_get_check);
        REQ *req = HTTP_REQ(http_arg_obj);
-       uint16_t addr_port = get_service_port(checker_obj);
        unsigned char digest[16];
        int r = 0;
        int val;
@@ -562,10 +537,10 @@ http_read_thread(thread * thread_obj)
 
        /* Test if data are ready */
        if (r == -1 && (errno == EAGAIN || errno == EINTR)) {
-               log_message(LOG_INFO, "Read error with server [%s:%d]: %s",
-                      inet_ntop2(CHECKER_RIP(checker_obj))
-                      , ntohs(addr_port)
-                      , strerror(errno));
+               log_message(LOG_INFO, "Read error with server [%s:%d]: %s"
+                                   , inet_sockaddrtos(&http_get_check->dst)
+                                   , ntohs(inet_sockaddrport(&http_get_check->dst))
+                                   , strerror(errno));
                thread_add_read(thread_obj->master, http_read_thread, checker_obj,
                                thread_obj->u.fd, http_get_check->connection_to);
                return 0;
@@ -579,9 +554,9 @@ http_read_thread(thread * thread_obj)
                if (r == -1) {
                        /* We have encourred a real read error */
                        if (svr_checker_up(checker_obj->id, checker_obj->rs)) {
-                               log_message(LOG_INFO, "Read error with server [%s:%d]: %s",
-                                      inet_ntop2(CHECKER_RIP(checker_obj))
-                                      , ntohs(addr_port)
+                               log_message(LOG_INFO, "Read error with server [%s:%d]: %s"
+                                      , inet_sockaddrtos(&http_get_check->dst)
+                                      , ntohs(inet_sockaddrport(&http_get_check->dst))
                                       , strerror(errno));
                                smtp_alert(checker_obj->rs, NULL, NULL,
                                           "DOWN",
@@ -655,7 +630,6 @@ http_request_thread(thread * thread_obj)
        http_get_checker *http_get_check = CHECKER_ARG(checker_obj);
        http_arg *http_arg_obj = HTTP_ARG(http_get_check);
        REQ *req = HTTP_REQ(http_arg_obj);
-       uint16_t addr_port = get_service_port(checker_obj);
        char *vhost = CHECKER_VHOST(checker_obj);
        char *str_request;
        url *fetched_url;
@@ -674,12 +648,12 @@ http_request_thread(thread * thread_obj)
        fetched_url = fetch_next_url(http_get_check);
        snprintf(str_request, GET_BUFFER_LENGTH, REQUEST_TEMPLATE,
                 fetched_url->path,
-                (vhost) ? vhost : inet_ntop2(CHECKER_RIP(checker_obj))
-                , ntohs(addr_port));
+                (vhost) ? vhost : inet_sockaddrtos(&http_get_check->dst)
+                , ntohs(inet_sockaddrport(&http_get_check->dst)));
        DBG("Processing url(%d) of [%s:%d].",
            http_arg_obj->url_it + 1
-           , inet_ntop2(CHECKER_RIP(checker_obj))
-           , ntohs(addr_port));
+           , inet_sockaddrtos(&http_get_check->dst)
+           , ntohs(inet_sockaddrport(&http_get_check->dst)));
 
        /* Set descriptor non blocking */
        val = fcntl(thread_obj->u.fd, F_GETFL, 0);
@@ -700,9 +674,9 @@ http_request_thread(thread * thread_obj)
        FREE(str_request);
 
        if (!ret) {
-               log_message(LOG_INFO, "Cannot send get request to [%s:%d].",
-                      inet_ntop2(CHECKER_RIP(checker_obj))
-                      , ntohs(addr_port));
+               log_message(LOG_INFO, "Cannot send get request to [%s:%d]."
+                                   , inet_sockaddrtos(&http_get_check->dst)
+                                   , ntohs(inet_sockaddrport(&http_get_check->dst)));
 
                /* check if server is currently alive */
                if (svr_checker_up(checker_obj->id, checker_obj->rs)) {
@@ -729,7 +703,6 @@ http_check_thread(thread * thread_obj)
 {
        checker *checker_obj = THREAD_ARG(thread_obj);
        http_get_checker *http_get_check = CHECKER_ARG(checker_obj);
-       uint16_t addr_port = get_service_port(checker_obj);
        http_arg *http_arg_obj = HTTP_ARG(http_get_check);
 #ifdef _DEBUG_
        REQ *req = HTTP_REQ(http_arg_obj);
@@ -740,15 +713,14 @@ http_check_thread(thread * thread_obj)
        int ssl_err = 0;
        int new_req = 0;
 
-       status = tcp_socket_state(thread_obj->u.fd, thread_obj, CHECKER_RIP(checker_obj)
-                                 , addr_port, http_check_thread);
+       status = tcp_socket_state(thread_obj->u.fd, thread_obj, http_check_thread);
        switch (status) {
        case connect_error:
                /* check if server is currently alive */
                if (svr_checker_up(checker_obj->id, checker_obj->rs)) {
-                       log_message(LOG_INFO, "Error connecting server [%s:%d].",
-                              inet_ntop2(CHECKER_RIP(checker_obj))
-                              , ntohs(addr_port));
+                       log_message(LOG_INFO, "Error connecting server [%s:%d]."
+                                           , inet_sockaddrtos(&http_get_check->dst)
+                                           , ntohs(inet_sockaddrport(&http_get_check->dst)));
                        smtp_alert(checker_obj->rs, NULL, NULL,
                                   "DOWN",
                                   "=> CHECK failed on service"
@@ -813,17 +785,17 @@ http_check_thread(thread * thread_obj)
                                /* Remote WEB server is connected.
                                 * Register the next step thread ssl_request_thread.
                                 */
-                               DBG("Remote Web server [%s:%d] connected.",
-                                   inet_ntop2(CHECKER_RIP(checker_obj)),
-                                   ntohs(addr_port));
+                               DBG("Remote Web server [%s:%d] connected."
+                                   , inet_sockaddrtos(&http_get_check->dst)
+                                   , ntohs(inet_sockaddrport(&http_get_check->dst)));
                                thread_add_write(thread_obj->master,
                                                 http_request_thread, checker_obj,
                                                 thread_obj->u.fd,
                                                 http_get_check->connection_to);
                        } else {
                                DBG(LOG_INFO, "Connection trouble to: [%s:%d]."
-                                   , inet_ntop2(CHECKER_RIP(checker_obj))
-                                   , ntohs(addr_port));
+                                           , inet_sockaddrtos(&http_get_check->dst)
+                                           , ntohs(inet_sockaddrport(&http_get_check->dst)));
 #ifdef _DEBUG_
                                if (http_get_check->proto == PROTO_SSL)
                                        ssl_printerr(SSL_get_error
@@ -835,8 +807,8 @@ http_check_thread(thread * thread_obj)
                                                         " connecting to server"
                                                         " (openssl errno: %d) [%s:%d]."
                                                       , SSL_get_error (http_arg_obj->req->ssl, ret)
-                                                      , inet_ntop2(CHECKER_RIP(checker_obj))
-                                                      , ntohs(addr_port));
+                                                      , inet_sockaddrtos(&http_get_check->dst)
+                                                      , ntohs(inet_sockaddrport(&http_get_check->dst)));
                                        smtp_alert(checker_obj->rs, NULL, NULL,
                                                   "DOWN",
                                                   "=> CHECK failed on service"
@@ -861,7 +833,6 @@ http_connect_thread(thread * thread_obj)
        checker *checker_obj = THREAD_ARG(thread_obj);
        http_get_checker *http_get_check = CHECKER_ARG(checker_obj);
        http_arg *http_arg_obj = HTTP_ARG(http_get_check);
-       uint16_t addr_port = get_service_port(checker_obj);
        url *fetched_url;
        enum connect_result status;
        int fd;
@@ -885,9 +856,9 @@ http_connect_thread(thread * thread_obj)
                 * check if server is currently alive.
                 */
                if (!svr_checker_up(checker_obj->id, checker_obj->rs)) {
-                       log_message(LOG_INFO, "Remote Web server [%s:%d] succeed on service.",
-                              inet_ntop2(CHECKER_RIP(checker_obj))
-                              , ntohs(addr_port));
+                       log_message(LOG_INFO, "Remote Web server [%s:%d] succeed on service."
+                                           , inet_sockaddrtos(&http_get_check->dst)
+                                           , ntohs(inet_sockaddrport(&http_get_check->dst)));
                        smtp_alert(checker_obj->rs, NULL, NULL, "UP",
                                   "=> CHECK succeed on service <=");
                        update_svr_checker_state(UP, checker_obj->id
@@ -899,13 +870,17 @@ http_connect_thread(thread * thread_obj)
        }
 
        /* Create the socket */
-       if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+       if ((fd = socket(http_get_check->dst.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
                DBG("WEB connection fail to create socket.");
                return 0;
        }
 
-       status = tcp_bind_connect(fd, CHECKER_RIP(checker_obj), addr_port
-                                 , http_get_check->bindto);
+       status = tcp_bind_connect(fd, &http_get_check->dst, &http_get_check->bindto);
+       if (status == connect_error) {
+               thread_add_timer(thread_obj->master, http_connect_thread, checker_obj,
+                                checker_obj->vs->delay_loop);
+               return 0;
+       }
 
        /* handle tcp connection status & register check worker thread */
        tcp_connection_state(fd, status, thread_obj, http_check_thread,
index 66631fe..ec684d9 100644 (file)
@@ -182,9 +182,9 @@ misc_check_child_thread(thread * thread_obj)
 
                /* The child hasn't responded. Kill it off. */
                if (svr_checker_up(checker_obj->id, checker_obj->rs)) {
-                       log_message(LOG_INFO, "Misc check to [%s] for [%s] timed out",
-                              inet_ntop2(CHECKER_RIP(checker_obj)),
-                              misc_chk->path);
+                       log_message(LOG_INFO, "Misc check to [%s] for [%s] timed out"
+                                           , inet_sockaddrtos(&checker_obj->rs->addr)
+                                           , misc_chk->path);
                        smtp_alert(checker_obj->rs, NULL, NULL,
                                   "DOWN",
                                   "=> MISC CHECK script timeout on service <=");
@@ -216,9 +216,9 @@ misc_check_child_thread(thread * thread_obj)
 
                        /* everything is good */
                        if (!svr_checker_up(checker_obj->id, checker_obj->rs)) {
-                               log_message(LOG_INFO, "Misc check to [%s] for [%s] success.",
-                                      inet_ntop2(CHECKER_RIP(checker_obj)),
-                                      misc_chk->path);
+                               log_message(LOG_INFO, "Misc check to [%s] for [%s] success."
+                                                   , inet_sockaddrtos(&checker_obj->rs->addr)
+                                                   , misc_chk->path);
                                smtp_alert(checker_obj->rs, NULL, NULL,
                                           "UP",
                                           "=> MISC CHECK succeed on service <=");
@@ -228,9 +228,9 @@ misc_check_child_thread(thread * thread_obj)
                        }
                } else {
                        if (svr_checker_up(checker_obj->id, checker_obj->rs)) {
-                               log_message(LOG_INFO, "Misc check to [%s] for [%s] failed.",
-                                      inet_ntop2(CHECKER_RIP(checker_obj)),
-                                      misc_chk->path);
+                               log_message(LOG_INFO, "Misc check to [%s] for [%s] failed."
+                                                   , inet_sockaddrtos(&checker_obj->rs->addr)
+                                                   , misc_chk->path);
                                smtp_alert(checker_obj->rs, NULL, NULL,
                                           "DOWN",
                                           "=> MISC CHECK failed on service <=");
index a7c97f6..2962b99 100644 (file)
@@ -130,7 +130,10 @@ static void
 pgr_handler(vector strvec)
 {
        virtual_server *vs = LIST_TAIL_DATA(check_data->vs);
-       inet_ston(VECTOR_SLOT(strvec, 1), &vs->granularity_persistence);
+       if (vs->addr.ss_family == AF_INET6)
+               vs->granularity_persistence = atoi(VECTOR_SLOT(strvec, 1));
+       else
+               inet_ston(VECTOR_SLOT(strvec, 1), &vs->granularity_persistence);
 }
 static void
 proto_handler(vector strvec)
index a72e983..e6fa251 100644 (file)
@@ -69,10 +69,10 @@ void
 smtp_dump_host(void *data)
 {
         smtp_host *smtp_hst = data;
-        log_message(LOG_INFO, "   Checked ip = %s", inet_ntop2(smtp_hst->ip));
-        log_message(LOG_INFO, "           port = %d", ntohs(smtp_hst->port));
-       if (smtp_hst->bindto)
-               log_message(LOG_INFO, "           bindto = %s", inet_ntop2(smtp_hst->bindto));
+        log_message(LOG_INFO, "   Checked ip = %s", inet_sockaddrtos(&smtp_hst->dst));
+        log_message(LOG_INFO, "           port = %d", ntohs(ntohs(inet_sockaddrport(&smtp_hst->dst))));
+       if (smtp_hst->bindto.ss_family)
+               log_message(LOG_INFO, "           bindto = %s", inet_sockaddrtos(&smtp_hst->bindto));
 }
 
 /* 
@@ -95,7 +95,6 @@ dump_smtp_check(void *data)
 smtp_host *
 smtp_alloc_host(void)
 {
-       checker *chk = LIST_TAIL_DATA(checkers_queue);
        smtp_host *new;
 
        /* Allocate the new host data structure */
@@ -105,8 +104,8 @@ smtp_alloc_host(void)
         * By default we set the ip to connect to as the same ip as the current real server
         * in the rs config. This might be overridden later on by a "connect_ip" keyword.
         */
-       new->ip = CHECKER_RIP(chk);
-       new->port = htons(SMTP_DEFAULT_PORT);
+       checker_set_dst(&new->dst);
+       checker_set_dst_port(&new->dst, htons(SMTP_DEFAULT_PORT));
        return new;
 }
 
@@ -189,7 +188,7 @@ smtp_ip_handler(vector strvec)
 {
        smtp_checker *smtp_chk = CHECKER_GET();
        smtp_host *smtp_hst = LIST_TAIL_DATA(smtp_chk->host);
-       inet_ston(VECTOR_SLOT(strvec, 1), &smtp_hst->ip);
+       inet_stosockaddr(VECTOR_SLOT(strvec, 1), NULL, &smtp_hst->dst);
 }
 
 /* "connect_port" keyword */
@@ -198,7 +197,7 @@ smtp_port_handler(vector strvec)
 {
        smtp_checker *smtp_chk = CHECKER_GET();
        smtp_host *smtp_hst = LIST_TAIL_DATA(smtp_chk->host);
-       smtp_hst->port = htons(CHECKER_VALUE_INT(strvec)); 
+       checker_set_dst_port(&smtp_hst->dst, htons(CHECKER_VALUE_INT(strvec)));
 }
 
 /* "helo_name" keyword */
@@ -239,7 +238,7 @@ smtp_bindto_handler(vector strvec)
 {
         smtp_checker *smtp_chk = CHECKER_GET();
        smtp_host *smtp_hst = LIST_TAIL_DATA(smtp_chk->host);
-        inet_ston(VECTOR_SLOT(strvec, 1), &smtp_hst->bindto);
+       inet_stosockaddr(VECTOR_SLOT(strvec, 1), 0, &smtp_hst->bindto);
 }
 
 /* Config callback installer */
@@ -383,26 +382,28 @@ smtp_get_line_cb(thread *thread_obj)
 
         /* Handle read timeout */
         if (thread_obj->type == THREAD_READ_TIMEOUT) {
-               smtp_final(thread_obj, 1, "Read timeout from server [%s:%d]",
-                          inet_ntop2(smtp_hst->ip), ntohs(smtp_hst->port));
+               smtp_final(thread_obj, 1, "Read timeout from server [%s:%d]"
+                                   , inet_sockaddrtos(&smtp_hst->dst)
+                                   , ntohs(inet_sockaddrport(&smtp_hst->dst)));
                return 0;
        }
 
        /* wrap the buffer, if full, by clearing it */
        if (SMTP_BUFF_MAX - smtp_chk->buff_ctr <= 0) {
                log_message(LOG_INFO, "SMTP_CHECK Buffer overflow reading from server [%s:%d]. "
-                      "Increase SMTP_BUFF_MAX in smtp_check.h",
-                      inet_ntop2(smtp_hst->ip), ntohs(smtp_hst->port));
+                                     "Increase SMTP_BUFF_MAX in smtp_check.h"
+                                   , inet_sockaddrtos(&smtp_hst->dst)
+                                   , ntohs(inet_sockaddrport(&smtp_hst->dst)));
                smtp_clear_buff(thread_obj);
        }
 
        /* Set descriptor non blocking */
-        f = fcntl(thread_obj->u.fd, F_GETFL, 0);
-        fcntl(thread_obj->u.fd, F_SETFL, f | O_NONBLOCK);
+       f = fcntl(thread_obj->u.fd, F_GETFL, 0);
+       fcntl(thread_obj->u.fd, F_SETFL, f | O_NONBLOCK);
 
-        /* read the data */
-        r = read(thread_obj->u.fd, smtp_chk->buff + smtp_chk->buff_ctr,
-                 SMTP_BUFF_MAX - smtp_chk->buff_ctr);
+       /* read the data */
+       r = read(thread_obj->u.fd, smtp_chk->buff + smtp_chk->buff_ctr,
+                SMTP_BUFF_MAX - smtp_chk->buff_ctr);
 
        if (r == -1 && (errno == EAGAIN || errno == EINTR)) {
                thread_add_read(thread_obj->master, smtp_get_line_cb, chk,
@@ -420,8 +421,10 @@ smtp_get_line_cb(thread *thread_obj)
                if (smtp_chk->buff[x] == '\n') {
                        smtp_chk->buff[SMTP_BUFF_MAX - 1] = '\0';
                        
-                       DBG("SMTP_CHECK [%s:%d] < %s", inet_ntop2(smtp_hst->ip),
-                           ntohs(smtp_hst->port), smtp_chk->buff);
+                       DBG("SMTP_CHECK [%s:%d] < %s"
+                           , inet_sockaddrtos(&smtp_hst->dst)
+                           , ntohs(inet_sockaddrport(&smtp_hst->dst))
+                           , smtp_chk->buff);
 
                        (smtp_chk->buff_cb)(thread_obj);
 
@@ -434,8 +437,9 @@ smtp_get_line_cb(thread *thread_obj)
         * some sort of error, notify smtp_final()
         */
        if (r <= 0) {
-               smtp_final(thread_obj, 1, "Read failure from server [%s:%d]",
-                          inet_ntop2(smtp_hst->ip), ntohs(smtp_hst->port));
+               smtp_final(thread_obj, 1, "Read failure from server [%s:%d]"
+                                    , inet_sockaddrtos(&smtp_hst->dst)
+                                    , ntohs(inet_sockaddrport(&smtp_hst->dst)));
                return 0;
        }
 
@@ -493,8 +497,9 @@ smtp_put_line_cb(thread *thread_obj)
 
         /* Handle read timeout */
         if (thread_obj->type == THREAD_WRITE_TIMEOUT) {
-               smtp_final(thread_obj, 1, "Write timeout to server [%s:%d]",
-                          inet_ntop2(smtp_hst->ip), ntohs(smtp_hst->port));
+               smtp_final(thread_obj, 1, "Write timeout to server [%s:%d]"
+                                    , inet_sockaddrtos(&smtp_hst->dst)
+                                    , ntohs(inet_sockaddrport(&smtp_hst->dst)));
                return 0;
        }
 
@@ -515,16 +520,19 @@ smtp_put_line_cb(thread *thread_obj)
         /* restore descriptor flags */
         fcntl(thread_obj->u.fd, F_SETFL, f);
 
-       DBG("SMTP_CHECK [%s:%d] > %s", inet_ntop2(smtp_hst->ip),
-           ntohs(smtp_hst->port), smtp_chk->buff);
+       DBG("SMTP_CHECK [%s:%d] > %s"
+           , inet_sockaddrtos(&smtp_hst->dst)
+           , ntohs(inet_sockaddrport(&smtp_hst->dst))
+           , smtp_chk->buff);
 
        /*
         * If the connection was closed or there was
         * some sort of error, notify smtp_final()
         */
        if (w <= 0) {
-               smtp_final(thread_obj, 1, "Write failure to server [%s:%d]",
-                          inet_ntop2(smtp_hst->ip), ntohs(smtp_hst->port));
+               smtp_final(thread_obj, 1, "Write failure to server [%s:%d]"
+                                    , inet_sockaddrtos(&smtp_hst->dst)
+                                    , ntohs(inet_sockaddrport(&smtp_hst->dst)));
                return 0;
        }
 
@@ -610,8 +618,9 @@ smtp_engine_thread(thread *thread_obj)
                case SMTP_HAVE_BANNER:
                        /* Check for "220 some.mailserver.com" in the greeting */
                        if (smtp_get_status(thread_obj) != 220) {
-                               smtp_final(thread_obj, 1, "Bad greeting banner from server [%s:%d]",
-                                       inet_ntop2(smtp_hst->ip), ntohs(smtp_hst->port));
+                               smtp_final(thread_obj, 1, "Bad greeting banner from server [%s:%d]"
+                                                    , inet_sockaddrtos(&smtp_hst->dst)
+                                                    , ntohs(inet_sockaddrport(&smtp_hst->dst)));
 
                                return 0;
                        }
@@ -638,8 +647,9 @@ smtp_engine_thread(thread *thread_obj)
                case SMTP_RECV_HELO:
                        /* Check for "250 Please to meet you..." */
                        if (smtp_get_status(thread_obj) != 250) {
-                               smtp_final(thread_obj, 1, "Bad HELO response from server [%s:%d]",
-                                       inet_ntop2(smtp_hst->ip), ntohs(smtp_hst->port));
+                               smtp_final(thread_obj, 1, "Bad HELO response from server [%s:%d]"
+                                                    , inet_sockaddrtos(&smtp_hst->dst)
+                                                    , ntohs(inet_sockaddrport(&smtp_hst->dst)));
 
                                return 0;
                        }
@@ -681,24 +691,26 @@ smtp_check_thread(thread *thread_obj)
        smtp_host *smtp_hst = smtp_chk->host_ptr;
        int status;
 
-       status = tcp_socket_state(thread_obj->u.fd, thread_obj, smtp_hst->ip,
-                                 smtp_hst->port, smtp_check_thread);
+       status = tcp_socket_state(thread_obj->u.fd, thread_obj, smtp_check_thread);
        switch (status) {
                case connect_error:
-                       smtp_final(thread_obj, 1, "Error connecting to server [%s:%d]",
-                                  inet_ntop2(smtp_hst->ip), ntohs(smtp_hst->port));
+                       smtp_final(thread_obj, 1, "Error connecting to server [%s:%d]"
+                                            , inet_sockaddrtos(&smtp_hst->dst)
+                                            , ntohs(inet_sockaddrport(&smtp_hst->dst)));
                        return 0;
                        break;
 
                case connect_timeout:
-                       smtp_final(thread_obj, 1, "Connection timeout to server [%s:%d]",
-                                  inet_ntop2(smtp_hst->ip), ntohs(smtp_hst->port));
+                       smtp_final(thread_obj, 1, "Connection timeout to server [%s:%d]"
+                                            , inet_sockaddrtos(&smtp_hst->dst)
+                                            , ntohs(inet_sockaddrport(&smtp_hst->dst)));
                        return 0;
                        break;
 
                case connect_success:
-                       DBG("SMTP_CHECK Remote SMTP server [%s:%d] connected",
-                           inet_ntop2(smtp_hst->ip), ntohs(smtp_hst->port));
+                       DBG("SMTP_CHECK Remote SMTP server [%s:%d] connected"
+                           , inet_sockaddrtos(&smtp_hst->dst)
+                           , ntohs(inet_sockaddrport(&smtp_hst->dst)));
 
                        /* Enter the engine at SMTP_START */
                        smtp_chk->state = SMTP_START;
@@ -708,8 +720,9 @@ smtp_check_thread(thread *thread_obj)
        }
 
        /* we shouldn't be here */              
-       smtp_final(thread_obj, 1, "Unknown connection error to server [%s:%d]",
-                  inet_ntop2(smtp_hst->ip), ntohs(smtp_hst->port));
+       smtp_final(thread_obj, 1, "Unknown connection error to server [%s:%d]"
+                            , inet_sockaddrtos(&smtp_hst->dst)
+                            , ntohs(inet_sockaddrport(&smtp_hst->dst)));
        return 0;
 }
 
@@ -777,8 +790,9 @@ smtp_connect_thread(thread *thread_obj)
         */
        if ((smtp_chk->host_ptr = list_element(smtp_chk->host, smtp_chk->host_ctr)) == NULL) {
                if (!svr_checker_up(chk->id, chk->rs)) {
-                       log_message(LOG_INFO, "Remote SMTP server [%s:%d] succeed on service.",
-                              inet_ntop2(CHECKER_RIP(chk)), ntohs(CHECKER_RPORT(chk)));
+                       log_message(LOG_INFO, "Remote SMTP server [%s:%d] succeed on service."
+                                           , inet_sockaddrtos(&chk->rs->addr)
+                                           , ntohs(inet_sockaddrport(&chk->rs->addr)));
 
                        smtp_alert(chk->rs, NULL, NULL, "UP",
                                   "=> CHECK succeed on service <=");
@@ -796,14 +810,19 @@ smtp_connect_thread(thread *thread_obj)
        smtp_hst = smtp_chk->host_ptr;
 
        /* Create the socket, failling here should be an oddity */
-       if ((sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+       if ((sd = socket(smtp_hst->dst.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
                DBG("SMTP_CHECK connection failed to create socket.");
                thread_add_timer(thread_obj->master, smtp_connect_thread, chk,
                                 chk->vs->delay_loop);
                return 0;
        }
 
-       status = tcp_bind_connect(sd, smtp_hst->ip, smtp_hst->port, smtp_hst->bindto);
+       status = tcp_bind_connect(sd, &smtp_hst->dst, &smtp_hst->bindto);
+       if (status == connect_error) {
+               thread_add_timer(thread_obj->master, smtp_connect_thread, chk,
+                                chk->vs->delay_loop);
+               return 0;
+       }
 
        /* handle tcp connection status & register callback the next setp in the process */
        tcp_connection_state(sd, status, thread_obj, smtp_check_thread, smtp_chk->timeout);
index ec56b89..00b185b 100644 (file)
@@ -286,8 +286,7 @@ ssl_read_thread(thread * thread_obj)
                MD5_Final(digest, &req->context);
                SSL_set_quiet_shutdown(req->ssl, 1);
 
-               r = (req->error ==
-                    SSL_ERROR_ZERO_RETURN) ? SSL_shutdown(req->ssl) : 0;
+               r = (req->error == SSL_ERROR_ZERO_RETURN) ? SSL_shutdown(req->ssl) : 0;
 
                if (r && !req->extracted) {
                        /* check if server is currently alive */
index cf6c7cc..9d8415a 100644 (file)
@@ -48,11 +48,9 @@ dump_tcp_check(void *data)
        tcp_checker *tcp_chk = CHECKER_DATA(data);
 
        log_message(LOG_INFO, "   Keepalive method = TCP_CHECK");
-       if (tcp_chk->connection_port)
-               log_message(LOG_INFO, "   Connection port = %d",
-                      ntohs(tcp_chk->connection_port));
-       if (tcp_chk->bindto)
-               log_message(LOG_INFO, "   Bind to = %s", inet_ntop2(tcp_chk->bindto));
+       log_message(LOG_INFO, "   Connection port = %d", ntohs(inet_sockaddrport(&tcp_chk->dst)));
+       if (tcp_chk->bindto.ss_family)
+               log_message(LOG_INFO, "   Bind to = %s", inet_sockaddrtos(&tcp_chk->bindto));
        log_message(LOG_INFO, "   Connection timeout = %d", tcp_chk->connection_to/TIMER_HZ);
 }
 
@@ -62,22 +60,23 @@ tcp_check_handler(vector strvec)
        tcp_checker *tcp_chk = (tcp_checker *) MALLOC(sizeof (tcp_checker));
 
        /* queue new checker */
-       queue_checker(free_tcp_check, dump_tcp_check, tcp_connect_thread,
-                     tcp_chk);
+       checker_set_dst(&tcp_chk->dst);
+       queue_checker(free_tcp_check, dump_tcp_check, tcp_connect_thread, tcp_chk);
 }
 
 void
 connect_port_handler(vector strvec)
 {
        tcp_checker *tcp_chk = CHECKER_GET();
-       tcp_chk->connection_port = htons(CHECKER_VALUE_INT(strvec));
+
+       checker_set_dst_port(&tcp_chk->dst, htons(CHECKER_VALUE_INT(strvec)));
 }
 
 void
 bind_handler(vector strvec)
 {
        tcp_checker *tcp_chk = CHECKER_GET();
-       inet_ston(VECTOR_SLOT(strvec, 1), &tcp_chk->bindto);
+       inet_stosockaddr(VECTOR_SLOT(strvec, 1), 0, &tcp_chk->bindto);
 }
 
 void
@@ -103,17 +102,12 @@ tcp_check_thread(thread * thread_obj)
 {
        checker *checker_obj;
        tcp_checker *tcp_check;
-       uint16_t addr_port;
        int status;
 
        checker_obj = THREAD_ARG(thread_obj);
        tcp_check = CHECKER_ARG(checker_obj);
 
-       addr_port = CHECKER_RPORT(checker_obj);
-       if (tcp_check->connection_port)
-               addr_port = tcp_check->connection_port;
-       status = tcp_socket_state(thread_obj->u.fd, thread_obj, CHECKER_RIP(checker_obj)
-                                 , addr_port, tcp_check_thread);
+       status = tcp_socket_state(thread_obj->u.fd, thread_obj, tcp_check_thread);
 
        /* If status = connect_success, TCP connection to remote host is established.
         * Otherwise we have a real connection error or connection timeout.
@@ -122,9 +116,9 @@ tcp_check_thread(thread * thread_obj)
                close(thread_obj->u.fd);
 
                if (!svr_checker_up(checker_obj->id, checker_obj->rs)) {
-                       log_message(LOG_INFO, "TCP connection to [%s:%d] success.",
-                              inet_ntop2(CHECKER_RIP(checker_obj))
-                              , ntohs(addr_port));
+                       log_message(LOG_INFO, "TCP connection to [%s:%d] success."
+                                           , inet_sockaddrtos(&tcp_check->dst)
+                                           , ntohs(inet_sockaddrport(&tcp_check->dst)));
                        smtp_alert(checker_obj->rs, NULL, NULL,
                                   "UP",
                                   "=> TCP CHECK succeed on service <=");
@@ -136,9 +130,9 @@ tcp_check_thread(thread * thread_obj)
        } else {
 
                if (svr_checker_up(checker_obj->id, checker_obj->rs)) {
-                       log_message(LOG_INFO, "TCP connection to [%s:%d] failed !!!",
-                              inet_ntop2(CHECKER_RIP(checker_obj))
-                              , ntohs(addr_port));
+                       log_message(LOG_INFO, "TCP connection to [%s:%d] failed !!!"
+                                           , inet_sockaddrtos(&tcp_check->dst)
+                                           , ntohs(inet_sockaddrport(&tcp_check->dst)));
                        smtp_alert(checker_obj->rs, NULL, NULL,
                                   "DOWN",
                                   "=> TCP CHECK failed on service <=");
@@ -162,7 +156,6 @@ tcp_connect_thread(thread * thread_obj)
        checker *checker_obj = THREAD_ARG(thread_obj);
        tcp_checker *tcp_check = CHECKER_ARG(checker_obj);
        int fd;
-       uint16_t addr_port;
        int status;
 
        /*
@@ -175,16 +168,17 @@ tcp_connect_thread(thread * thread_obj)
                return 0;
        }
 
-       if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+       if ((fd = socket(tcp_check->dst.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
                DBG("TCP connect fail to create socket.");
                return 0;
        }
 
-       addr_port = CHECKER_RPORT(checker_obj);
-       if (tcp_check->connection_port)
-               addr_port = tcp_check->connection_port;
-       status = tcp_bind_connect(fd, CHECKER_RIP(checker_obj), addr_port
-                                 , tcp_check->bindto);
+       status = tcp_bind_connect(fd, &tcp_check->dst, &tcp_check->bindto);
+       if (status == connect_error) {
+               thread_add_timer(thread_obj->master, tcp_connect_thread, checker_obj,
+                                checker_obj->vs->delay_loop);
+               return 0;
+       }
 
        /* handle tcp connection status & register check worker thread */
        tcp_connection_state(fd, status, thread_obj, tcp_check_thread,
index ad79f20..8f5b93e 100644 (file)
@@ -125,11 +125,11 @@ ipvs_group_range_cmd(int cmd, virtual_server_group_entry *vsg_entry)
        int err = 0;
 
        /* Parse the whole range */
-       for (addr_ip = SVR_IP(vsg_entry);
+       for (addr_ip = inet_sockaddrip4(&vsg_entry->addr);
             ((addr_ip >> 24) & 0xFF) <= vsg_entry->range;
             addr_ip += 0x01000000) {
                urule->vaddr = addr_ip;
-               urule->vport = SVR_PORT(vsg_entry);
+               urule->vport = inet_sockaddrport(&vsg_entry->addr);
 
                /* Talk to the IPVS channel */
                err = ipvs_talk(cmd);
@@ -155,8 +155,8 @@ ipvs_group_cmd(int cmd, list vs_group, real_server * rs, char * vsgname)
        l = vsg->addr_ip;
        for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
                vsg_entry = ELEMENT_DATA(e);
-               urule->vaddr = SVR_IP(vsg_entry);
-               urule->vport = SVR_PORT(vsg_entry);
+               urule->vaddr = inet_sockaddrip4(&vsg_entry->addr);
+               urule->vport = inet_sockaddrport(&vsg_entry->addr);
 
                /* Talk to the IPVS channel */
                if (IPVS_ALIVE(cmd, vsg_entry, rs)) {
@@ -210,9 +210,9 @@ ipvs_set_rule(int cmd, virtual_server * vs, real_server * rs)
        urule->protocol = vs->service_type;
 
        if (!parse_timeout(vs->timeout_persistence, &urule->timeout))
-               log_message(LOG_INFO,
-                      "IPVS : Virtual service [%s:%d] illegal timeout.",
-                      inet_ntop2(SVR_IP(vs)), ntohs(SVR_PORT(vs)));
+               log_message(LOG_INFO, "IPVS : Virtual service [%s:%d] illegal timeout."
+                                   , inet_ntop2(inet_sockaddrip4(&vs->addr))
+                                   , ntohs(inet_sockaddrport(&vs->addr)));
 
        if (urule->timeout != 0 || vs->granularity_persistence)
                urule->vs_flags = IP_VS_SVC_F_PERSISTENT;
@@ -227,8 +227,8 @@ ipvs_set_rule(int cmd, virtual_server * vs, real_server * rs)
                    || cmd == IP_VS_SO_SET_DELDEST
                    || cmd == IP_VS_SO_SET_EDITDEST) {
                        urule->weight = rs->weight;
-                       urule->daddr = SVR_IP(rs);
-                       urule->dport = SVR_PORT(rs);
+                       urule->daddr = inet_sockaddrip4(&rs->addr);
+                       urule->dport = inet_sockaddrport(&rs->addr);
                }
        }
 }
@@ -263,8 +263,8 @@ ipvs_cmd(int cmd, list vs_group, virtual_server * vs, real_server * rs)
                if (vs->vfwmark) {
                        urule->vfwmark = vs->vfwmark;
                } else {
-                       urule->vaddr = SVR_IP(vs);
-                       urule->vport = SVR_PORT(vs);
+                       urule->vaddr = inet_sockaddrip4(&vs->addr);
+                       urule->vport = inet_sockaddrport(&vs->addr);
                }
 
                /* Talk to the IPVS channel */
@@ -297,8 +297,8 @@ ipvs_group_remove_entry(virtual_server *vs, virtual_server_group_entry *vsge)
                                ipvs_set_rule(IP_VS_SO_SET_DELDEST, vs, rs);
                        } else {
                                urule->weight = rs->weight;
-                               urule->daddr = SVR_IP(rs);
-                               urule->dport = SVR_PORT(rs);
+                               urule->daddr = inet_sockaddrip4(&rs->addr);
+                               urule->dport = inet_sockaddrport(&rs->addr);
                        }
 
                        /* Set vs rule */
@@ -306,8 +306,8 @@ ipvs_group_remove_entry(virtual_server *vs, virtual_server_group_entry *vsge)
                                ipvs_group_range_cmd(IP_VS_SO_SET_DELDEST, vsge);
                        } else {
                                urule->vfwmark = vsge->vfwmark;
-                               urule->vaddr = SVR_IP(vsge);
-                               urule->vport = SVR_PORT(vsge);
+                               urule->vaddr = inet_sockaddrip4(&vsge->addr);
+                               urule->vport = inet_sockaddrport(&vsge->addr);
 
                                /* Talk to the IPVS channel */
                                err = ipvs_talk(IP_VS_SO_SET_DELDEST);
@@ -326,9 +326,9 @@ ipvs_group_remove_entry(virtual_server *vs, virtual_server_group_entry *vsge)
 #else                                  /* KERNEL 2.6 IPVS handling */
 
 /* Global module def IPVS rules */
-static struct ip_vs_service_user *srule;
-static struct ip_vs_dest_user *drule;
-static struct ip_vs_daemon_user *daemonrule;
+static ipvs_service_t *srule;
+static ipvs_dest_t *drule;
+static ipvs_daemon_t *daemonrule;
 
 /* Initialization helpers */
 int
@@ -345,9 +345,9 @@ ipvs_start(void)
        }
 
        /* Allocate global user rules */
-       srule = (struct ip_vs_service_user *) MALLOC(sizeof (struct ip_vs_service_user));
-       drule = (struct ip_vs_dest_user *) MALLOC(sizeof (struct ip_vs_dest_user));
-       daemonrule = (struct ip_vs_daemon_user *) MALLOC(sizeof (struct ip_vs_daemon_user));
+       srule = (ipvs_service_t *) MALLOC(sizeof(ipvs_service_t));
+       drule = (ipvs_dest_t *) MALLOC(sizeof(ipvs_dest_t));
+       daemonrule = (ipvs_daemon_t *) MALLOC(sizeof(ipvs_daemon_t));
        return IPVS_SUCCESS;
 }
 
@@ -406,7 +406,7 @@ ipvs_talk(int cmd)
 int
 ipvs_syncd_cmd(int cmd, char *ifname, int state, int syncid)
 {
-       memset(daemonrule, 0, sizeof (struct ip_vs_daemon_user));
+       memset(daemonrule, 0, sizeof(ipvs_daemon_t));
 
        /* prepare user rule */
        daemonrule->state = state;
@@ -423,14 +423,30 @@ ipvs_syncd_cmd(int cmd, char *ifname, int state, int syncid)
 static void
 ipvs_group_range_cmd(int cmd, virtual_server_group_entry *vsg_entry)
 {
-       uint32_t addr_ip;
+       uint32_t addr_ip, ip;
+
+       if (vsg_entry->addr.ss_family == AF_INET6) {
+               inet_sockaddrip6(&vsg_entry->addr, &srule->addr.in6);
+               ip = srule->addr.in6.s6_addr32[3];
+       } else {
+               ip = inet_sockaddrip4(&vsg_entry->addr);
+       }
+
+       /* Set Address Family */
+       srule->af = vsg_entry->addr.ss_family;
 
        /* Parse the whole range */
-       for (addr_ip = SVR_IP(vsg_entry);
+       for (addr_ip = ip;
             ((addr_ip >> 24) & 0xFF) <= vsg_entry->range;
             addr_ip += 0x01000000) {
-               srule->addr = addr_ip;
-               srule->port = SVR_PORT(vsg_entry);
+               if (srule->af == AF_INET6) {
+                       if (srule->netmask == 0xffffffff)
+                               srule->netmask = 128;
+                       srule->addr.in6.s6_addr32[3] = addr_ip;
+               } else {
+                       srule->addr.ip = addr_ip;
+               }
+               srule->port = inet_sockaddrport(&vsg_entry->addr);
 
                /* Talk to the IPVS channel */
                ipvs_talk(cmd);
@@ -453,8 +469,14 @@ ipvs_group_cmd(int cmd, list vs_group, real_server * rs, char * vsgname)
        l = vsg->addr_ip;
        for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
                vsg_entry = ELEMENT_DATA(e);
-               srule->addr = SVR_IP(vsg_entry);
-               srule->port = SVR_PORT(vsg_entry);
+               srule->af = vsg_entry->addr.ss_family;
+               if (vsg_entry->addr.ss_family == AF_INET6) {
+                       if (srule->netmask == 0xffffffff)
+                               srule->netmask = 128;
+                       inet_sockaddrip6(&vsg_entry->addr, &srule->addr.in6);
+               } else
+                       srule->addr.ip = inet_sockaddrip4(&vsg_entry->addr);
+               srule->port = inet_sockaddrport(&vsg_entry->addr);
 
                /* Talk to the IPVS channel */
                if (IPVS_ALIVE(cmd, vsg_entry, rs)) {
@@ -465,10 +487,12 @@ ipvs_group_cmd(int cmd, list vs_group, real_server * rs, char * vsgname)
 
        /* visit vfwmark list */
        l = vsg->vfwmark;
-       srule->addr = 0;
+       srule->addr.ip = 0;
+       srule->af = 0;
        srule->port = 0;
        for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
                vsg_entry = ELEMENT_DATA(e);
+               srule->af = AF_INET;
                srule->fwmark = vsg_entry->vfwmark;
 
                /* Talk to the IPVS channel */
@@ -497,20 +521,20 @@ void
 ipvs_set_rule(int cmd, virtual_server * vs, real_server * rs)
 {
        /* Clean target rule */
-       memset(drule, 0, sizeof (struct ip_vs_dest_user));
+       memset(drule, 0, sizeof(ipvs_dest_t));
 
        drule->weight = 1;
        drule->u_threshold = 0;
        drule->l_threshold = 0;
        drule->conn_flags = vs->loadbalancing_kind;
        strncpy(srule->sched_name, vs->sched, IP_VS_SCHEDNAME_MAXLEN);
-       srule->netmask = ((u_int32_t) 0xffffffff);
+       srule->netmask = (vs->addr.ss_family == AF_INET6) ? 128 : ((u_int32_t) 0xffffffff);
        srule->protocol = vs->service_type;
 
        if (!parse_timeout(vs->timeout_persistence, &srule->timeout))
-               log_message(LOG_INFO,
-                      "IPVS : Virtual service [%s:%d] illegal timeout.",
-                      inet_ntop2(SVR_IP(vs)), ntohs(SVR_PORT(vs)));
+               log_message(LOG_INFO, "IPVS : Virtual service [%s:%d] illegal timeout."
+                                   , inet_ntop2(inet_sockaddrip4(&vs->addr))
+                                   , ntohs(inet_sockaddrport(&vs->addr)));
 
        if (srule->timeout != 0 || vs->granularity_persistence)
                srule->flags = IP_VS_SVC_F_PERSISTENT;
@@ -521,12 +545,15 @@ ipvs_set_rule(int cmd, virtual_server * vs, real_server * rs)
 
        /* SVR specific */
        if (rs) {
-               if (cmd == IP_VS_SO_SET_ADDDEST
-                   || cmd == IP_VS_SO_SET_DELDEST
-                   || cmd == IP_VS_SO_SET_EDITDEST) {
-                       drule->weight = rs->weight;
-                       drule->addr = SVR_IP(rs);
-                       drule->port = SVR_PORT(rs);
+               if (cmd == IP_VS_SO_SET_ADDDEST || cmd == IP_VS_SO_SET_DELDEST ||
+                   cmd == IP_VS_SO_SET_EDITDEST) {
+                       drule->af = rs->addr.ss_family;
+                       if (rs->addr.ss_family == AF_INET6)
+                               inet_sockaddrip6(&rs->addr, &drule->addr.in6);
+                       else
+                               drule->addr.ip = inet_sockaddrip4(&rs->addr);
+                       drule->port = inet_sockaddrport(&rs->addr);
+                       drule->weight = rs->weight;     
                        drule->u_threshold = rs->u_threshold;
                        drule->l_threshold = rs->l_threshold;
                }
@@ -538,7 +565,7 @@ int
 ipvs_cmd(int cmd, list vs_group, virtual_server * vs, real_server * rs)
 {
        /* Allocate the room */
-       memset(srule, 0, sizeof (struct ip_vs_service_user));
+       memset(srule, 0, sizeof(ipvs_service_t));
        ipvs_set_rule(cmd, vs, rs);
 
        /* Does the service use inhibit flag ? */
@@ -560,10 +587,15 @@ ipvs_cmd(int cmd, list vs_group, virtual_server * vs, real_server * rs)
                ipvs_group_cmd(cmd, vs_group, rs, vs->vsgname);
        } else {
                if (vs->vfwmark) {
+                       srule->af = AF_INET;
                        srule->fwmark = vs->vfwmark;
                } else {
-                       srule->addr = SVR_IP(vs);
-                       srule->port = SVR_PORT(vs);
+                       srule->af = vs->addr.ss_family;
+                       if (vs->addr.ss_family == AF_INET6)
+                               inet_sockaddrip6(&vs->addr, &srule->addr.in6);
+                       else
+                               srule->addr.ip = inet_sockaddrip4(&vs->addr);
+                       srule->port = inet_sockaddrport(&vs->addr);
                }
 
                /* Talk to the IPVS channel */
@@ -582,8 +614,8 @@ ipvs_group_remove_entry(virtual_server *vs, virtual_server_group_entry *vsge)
        list l = vs->rs;
 
        /* Clean target rules */
-       memset(srule, 0, sizeof (struct ip_vs_service_user));
-       memset(drule, 0, sizeof (struct ip_vs_dest_user));
+       memset(srule, 0, sizeof(ipvs_service_t));
+       memset(drule, 0, sizeof(ipvs_dest_t));
 
        /* Process realserver queue */
        for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
@@ -591,22 +623,30 @@ ipvs_group_remove_entry(virtual_server *vs, virtual_server_group_entry *vsge)
 
                if (rs->alive) {
                        /* Prepare the IPVS rule */
-                       if (!drule->addr) {
+                       if (!drule->addr.ip) {
                                /* Setting IPVS rule with vs root rs */
                                ipvs_set_rule(IP_VS_SO_SET_DELDEST, vs, rs);
                        } else {
+                               drule->af = rs->addr.ss_family;
+                               if (rs->addr.ss_family == AF_INET6)
+                                       inet_sockaddrip6(&rs->addr, &drule->addr.in6);
+                               else
+                                       drule->addr.ip = inet_sockaddrip4(&rs->addr);
+                               drule->port = inet_sockaddrport(&rs->addr);
                                drule->weight = rs->weight;
-                               drule->addr = SVR_IP(rs);
-                               drule->port = SVR_PORT(rs);
                        }
 
                        /* Set vs rule */
                        if (vsge->range) {
                                ipvs_group_range_cmd(IP_VS_SO_SET_DELDEST, vsge);
                        } else {
+                               srule->af = vsge->addr.ss_family;
+                               if (vsge->addr.ss_family == AF_INET6)
+                                       inet_sockaddrip6(&vsge->addr, &srule->addr.in6);
+                               else
+                                       srule->addr.ip = inet_sockaddrip4(&vsge->addr);
+                               srule->port = inet_sockaddrport(&vsge->addr);
                                srule->fwmark = vsge->vfwmark;
-                               srule->addr = SVR_IP(vsge);
-                               srule->port = SVR_PORT(vsge);
                                drule->u_threshold = rs->u_threshold;
                                drule->l_threshold = rs->l_threshold;
 
@@ -621,6 +661,7 @@ ipvs_group_remove_entry(virtual_server *vs, virtual_server_group_entry *vsge)
                ipvs_group_range_cmd(IP_VS_SO_SET_DEL, vsge);
        else
                ipvs_talk(IP_VS_SO_SET_DEL);
+
        return IPVS_SUCCESS;
 }
 
index 15093fe..b3906f7 100644 (file)
@@ -50,15 +50,12 @@ clear_service_rs(list vs_group, virtual_server * vs, list l)
 {
        element e;
        real_server *rs;
-       char rsip[16], vsip[16];
+       char rsip[INET6_ADDRSTRLEN];
 
        for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
                rs = ELEMENT_DATA(e);
                if (ISALIVE(rs)) {
-                       if (!ipvs_cmd(LVS_CMD_DEL_DEST
-                                     , vs_group
-                                     , vs
-                                     , rs))
+                       if (!ipvs_cmd(LVS_CMD_DEL_DEST, vs_group, vs, rs))
                                return 0;
                        UNSET_ALIVE(rs);
                        if (!vs->omega)
@@ -68,13 +65,12 @@ clear_service_rs(list vs_group, virtual_server * vs, list l)
                         * all the way down the exit, as necessary.
                         */
                        if (rs->notify_down) {
-                               log_message(LOG_INFO, "Executing [%s] for service [%s:%d]"
-                                           " in VS [%s:%d]"
-                                           , rs->notify_down
-                                           , inet_ntoa2(SVR_IP(rs), rsip)
-                                           , ntohs(SVR_PORT(rs))
-                                           , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip)
-                                           , ntohs(SVR_PORT(vs)));
+                               log_message(LOG_INFO, "Executing [%s] for service [%s:%d] in VS [%s:%d]"
+                                                   , rs->notify_down
+                                                   , inet_sockaddrtos2(&rs->addr, rsip)
+                                                   , ntohs(inet_sockaddrport(&rs->addr))
+                                                   , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
+                                                   , ntohs(inet_sockaddrport(&vs->addr)));
                                notify_exec(rs->notify_down);
                        }
 
@@ -82,17 +78,18 @@ clear_service_rs(list vs_group, virtual_server * vs, list l)
                         * we don't push in a sorry server then, hence the regression
                         * is intended.
                         */
-                       if (vs->quorum_state == UP && vs->quorum_down
-                         && weigh_live_realservers(vs) < vs->quorum - vs->hysteresis) {
+                       if (vs->quorum_state == UP && vs->quorum_down &&
+                           weigh_live_realservers(vs) < vs->quorum - vs->hysteresis) {
                                vs->quorum_state = DOWN;
                                log_message(LOG_INFO, "Executing [%s] for VS [%s:%d]"
-                                           , vs->quorum_down
-                                           , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip)
-                                           , ntohs(SVR_PORT(vs)));
+                                                   , vs->quorum_down
+                                                   , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
+                                                   , ntohs(inet_sockaddrport(&vs->addr)));
                                notify_exec(vs->quorum_down);
                        }
                }
        }
+
        return 1;
 }
 
@@ -104,10 +101,7 @@ clear_service_vs(list vs_group, virtual_server * vs)
        if (!LIST_ISEMPTY(vs->rs)) {
                if (vs->s_svr) {
                        if (ISALIVE(vs->s_svr))
-                               if (!ipvs_cmd(LVS_CMD_DEL_DEST
-                                             , vs_group
-                                             , vs
-                                             , vs->s_svr))
+                               if (!ipvs_cmd(LVS_CMD_DEL_DEST, vs_group, vs, vs->s_svr))
                                        return 0;
                } else if (!clear_service_rs(vs_group, vs, vs->rs))
                        return 0;
@@ -216,21 +210,21 @@ perform_quorum_state(virtual_server *vs, int add)
 {
        element e;
        real_server *rs;
-       char vsip[16];
+
        if (LIST_ISEMPTY(vs->rs))
                return;
-       log_message(LOG_INFO,
-              "%s the pool for VS [%s:%d]"
-              , add?"Adding alive servers to":"Removing alive servers from"
-              , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip)
-              , ntohs(SVR_PORT(vs)));
+
+       log_message(LOG_INFO, "%s the pool for VS [%s:%d]"
+                           , add?"Adding alive servers to":"Removing alive servers from"
+                           , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
+                           , ntohs(inet_sockaddrport(&vs->addr)));
        for (e = LIST_HEAD(vs->rs); e; ELEMENT_NEXT(e)) {
                rs = ELEMENT_DATA(e);
                if (!ISALIVE(rs)) /* We only handle alive servers */
                        continue;
-               if (add) rs->alive = 0;
-               ipvs_cmd(add?LVS_CMD_ADD_DEST:LVS_CMD_DEL_DEST,
-                        check_data->vs_group, vs, rs);
+               if (add)
+                       rs->alive = 0;
+               ipvs_cmd(add?LVS_CMD_ADD_DEST:LVS_CMD_DEL_DEST, check_data->vs_group, vs, rs);
                rs->alive = 1;
        }
 }
@@ -239,31 +233,27 @@ perform_quorum_state(virtual_server *vs, int add)
 void
 update_quorum_state(virtual_server * vs)
 {
-       char rsip[16], vsip[16];
+       char rsip[INET6_ADDRSTRLEN];
 
        /* If we have just gained quorum, it's time to consider notify_up. */
-       if (vs->quorum_state == DOWN
-           && weigh_live_realservers(vs) >= vs->quorum + vs->hysteresis) {
+       if (vs->quorum_state == DOWN &&
+           weigh_live_realservers(vs) >= vs->quorum + vs->hysteresis) {
                vs->quorum_state = UP;
                log_message(LOG_INFO, "Gained quorum %lu+%lu=%lu <= %u for VS [%s:%d]"
-                           , vs->quorum
-                           , vs->hysteresis
-                           , vs->quorum + vs->hysteresis
-                           , weigh_live_realservers(vs)
-                           , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip)
-                           , ntohs(SVR_PORT(vs)));
+                                   , vs->quorum
+                                   , vs->hysteresis
+                                   , vs->quorum + vs->hysteresis
+                                   , weigh_live_realservers(vs)
+                                   , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
+                                   , ntohs(inet_sockaddrport(&vs->addr)));
                if (vs->s_svr && ISALIVE(vs->s_svr)) {
-                       log_message(LOG_INFO,
-                                   "Removing sorry server [%s:%d] from VS [%s:%d]",
-                                   inet_ntoa2(SVR_IP(vs->s_svr), rsip)
-                                   , ntohs(SVR_PORT(vs->s_svr))
-                                   , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip)
-                                   , ntohs(SVR_PORT(vs)));
-
-                       ipvs_cmd(LVS_CMD_DEL_DEST
-                                , check_data->vs_group
-                                , vs
-                                , vs->s_svr);
+                       log_message(LOG_INFO, "Removing sorry server [%s:%d] from VS [%s:%d]"
+                                           , inet_sockaddrtos2(&vs->s_svr->addr, rsip)
+                                           , ntohs(inet_sockaddrport(&vs->s_svr->addr))
+                                           , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
+                                           , ntohs(inet_sockaddrport(&vs->addr)));
+
+                       ipvs_cmd(LVS_CMD_DEL_DEST, check_data->vs_group, vs, vs->s_svr);
                        vs->s_svr->alive = 0;
 
                        /* Adding back alive real servers */
@@ -271,9 +261,9 @@ update_quorum_state(virtual_server * vs)
                }
                if (vs->quorum_up) {
                        log_message(LOG_INFO, "Executing [%s] for VS [%s:%d]"
-                                   , vs->quorum_up
-                                   , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip)
-                                   , ntohs(SVR_PORT(vs)));
+                                           , vs->quorum_up
+                                           , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
+                                           , ntohs(inet_sockaddrport(&vs->addr)));
                        notify_exec(vs->quorum_up);
                }
                return;
@@ -282,30 +272,29 @@ update_quorum_state(virtual_server * vs)
        /* If we have just lost quorum for the VS, we need to consider
         * VS notify_down and sorry_server cases
         */
-       if (vs->quorum_state == UP
-           && weigh_live_realservers(vs) < vs->quorum - vs->hysteresis) {
+       if (vs->quorum_state == UP &&
+           weigh_live_realservers(vs) < vs->quorum - vs->hysteresis) {
                vs->quorum_state = DOWN;
                log_message(LOG_INFO, "Lost quorum %lu-%lu=%lu > %u for VS [%s:%d]"
-                           , vs->quorum
-                           , vs->hysteresis
-                           , vs->quorum - vs->hysteresis
-                           , weigh_live_realservers(vs)
-                           , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip)
-                           , ntohs(SVR_PORT(vs)));
+                                   , vs->quorum
+                                   , vs->hysteresis
+                                   , vs->quorum - vs->hysteresis
+                                   , weigh_live_realservers(vs)
+                                   , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
+                                   , ntohs(inet_sockaddrport(&vs->addr)));
                if (vs->quorum_down) {
                        log_message(LOG_INFO, "Executing [%s] for VS [%s:%d]"
-                                   , vs->quorum_down
-                                   , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip)
-                                   , ntohs(SVR_PORT(vs)));
+                                           , vs->quorum_down
+                                           , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
+                                           , ntohs(inet_sockaddrport(&vs->addr)));
                        notify_exec(vs->quorum_down);
                }
                if (vs->s_svr) {
-                       log_message(LOG_INFO,
-                                   "Adding sorry server [%s:%d] to VS [%s:%d]",
-                                   inet_ntoa2(SVR_IP(vs->s_svr), rsip)
-                                   , ntohs(SVR_PORT(vs->s_svr))
-                                   , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip)
-                                   , ntohs(SVR_PORT(vs)));
+                       log_message(LOG_INFO, "Adding sorry server [%s:%d] to VS [%s:%d]"
+                                           , inet_sockaddrtos2(&vs->s_svr->addr, rsip)
+                                           , ntohs(inet_sockaddrport(&vs->s_svr->addr))
+                                           , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
+                                           , ntohs(inet_sockaddrport(&vs->addr)));
 
                        /* the sorry server is now up in the pool, we flag it alive */
                        ipvs_cmd(LVS_CMD_ADD_DEST, check_data->vs_group, vs, vs->s_svr);
@@ -322,36 +311,34 @@ update_quorum_state(virtual_server * vs)
 void
 perform_svr_state(int alive, virtual_server * vs, real_server * rs)
 {
-       char rsip[16], vsip[16];
-/*
- * | ISALIVE(rs) | alive | context
- * | 0           | 0     | first check failed under alpha mode, unreachable here
- * | 0           | 1     | RS went up, add it to the pool
- * | 1           | 0     | RS went down, remove it from the pool
- * | 1           | 1     | first check succeeded w/o alpha mode, unreachable here
- */
+       char rsip[INET6_ADDRSTRLEN];
 
+       /*
+        * | ISALIVE(rs) | alive | context
+        * | 0           | 0     | first check failed under alpha mode, unreachable here
+        * | 0           | 1     | RS went up, add it to the pool
+        * | 1           | 0     | RS went down, remove it from the pool
+        * | 1           | 1     | first check succeeded w/o alpha mode, unreachable here
+        */
        if (!ISALIVE(rs) && alive) {
-
-               log_message(LOG_INFO, "%s service [%s:%d] to VS [%s:%d]",
-                      (rs->inhibit) ? "Enabling" : "Adding"
-                      , inet_ntoa2(SVR_IP(rs), rsip)
-                      , ntohs(SVR_PORT(rs))
-                      , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip)
-                      , ntohs(SVR_PORT(vs)));
+               log_message(LOG_INFO, "%s service [%s:%d] to VS [%s:%d]"
+                                   , (rs->inhibit) ? "Enabling" : "Adding"
+                                   , inet_sockaddrtos2(&rs->addr, rsip)
+                                   , ntohs(inet_sockaddrport(&rs->addr))
+                                   , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
+                                   , ntohs(inet_sockaddrport(&vs->addr)));
                /* Add only if we have quorum or no sorry server */
                if (vs->quorum_state == UP || !vs->s_svr || !ISALIVE(vs->s_svr)) {
                        ipvs_cmd(LVS_CMD_ADD_DEST, check_data->vs_group, vs, rs);
                }
                rs->alive = alive;
                if (rs->notify_up) {
-                       log_message(LOG_INFO, "Executing [%s] for service [%s:%d]"
-                              " in VS [%s:%d]"
-                              , rs->notify_up
-                              , inet_ntoa2(SVR_IP(rs), rsip)
-                              , ntohs(SVR_PORT(rs))
-                              , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip)
-                              , ntohs(SVR_PORT(vs)));
+                       log_message(LOG_INFO, "Executing [%s] for service [%s:%d] in VS [%s:%d]"
+                                           , rs->notify_up
+                                           , inet_sockaddrtos2(&rs->addr, rsip)
+                                           , ntohs(inet_sockaddrport(&rs->addr))
+                                           , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
+                                           , ntohs(inet_sockaddrport(&vs->addr)));
                        notify_exec(rs->notify_up);
                }
 
@@ -360,28 +347,27 @@ perform_svr_state(int alive, virtual_server * vs, real_server * rs)
        }
 
        if (ISALIVE(rs) && !alive) {
-
-               log_message(LOG_INFO, "%s service [%s:%d] from VS [%s:%d]",
-                      (rs->inhibit) ? "Disabling" : "Removing"
-                      , inet_ntoa2(SVR_IP(rs), rsip)
-                      , ntohs(SVR_PORT(rs))
-                      , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip)
-                      , ntohs(SVR_PORT(vs)));
-
-               /* server is down, it is removed from the LVS realserver pool */
-               /* Remove only if we have quorum or no sorry server */
+               log_message(LOG_INFO, "%s service [%s:%d] from VS [%s:%d]"
+                                   , (rs->inhibit) ? "Disabling" : "Removing"
+                                   , inet_sockaddrtos2(&rs->addr, rsip)
+                                   , ntohs(inet_sockaddrport(&rs->addr))
+                                   , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
+                                   , ntohs(inet_sockaddrport(&vs->addr)));
+
+               /* server is down, it is removed from the LVS realserver pool
+                * Remove only if we have quorum or no sorry server
+                */
                if (vs->quorum_state == UP || !vs->s_svr || !ISALIVE(vs->s_svr)) {
                        ipvs_cmd(LVS_CMD_DEL_DEST, check_data->vs_group, vs, rs);
                }
                rs->alive = alive;
                if (rs->notify_down) {
-                       log_message(LOG_INFO, "Executing [%s] for service [%s:%d]"
-                              " in VS [%s:%d]"
-                              , rs->notify_down
-                              , inet_ntoa2(SVR_IP(rs), rsip)
-                              , ntohs(SVR_PORT(rs))
-                              , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip)
-                              , ntohs(SVR_PORT(vs)));
+                       log_message(LOG_INFO, "Executing [%s] for service [%s:%d] in VS [%s:%d]"
+                                           , rs->notify_down
+                                           , inet_sockaddrtos2(&rs->addr, rsip)
+                                           , ntohs(inet_sockaddrport(&rs->addr))
+                                           , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
+                                           , ntohs(inet_sockaddrport(&vs->addr)));
                        notify_exec(rs->notify_down);
                }
 
@@ -394,18 +380,17 @@ perform_svr_state(int alive, virtual_server * vs, real_server * rs)
 void
 update_svr_wgt(int weight, virtual_server * vs, real_server * rs)
 {
-       char rsip[16], vsip[16];
+       char rsip[INET6_ADDRSTRLEN];
 
        if (weight != rs->weight) {
-               log_message(LOG_INFO, "Changing weight from %d to %d for %s service [%s:%d]"
-                                " of VS [%s:%d]"
-                                , rs->weight
-                                , weight
-                                , ISALIVE(rs) ? "active" : "inactive"
-                                , inet_ntoa2(SVR_IP(rs), rsip)
-                                , ntohs(SVR_PORT(rs))
-                                , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip)
-                                , ntohs(SVR_PORT(vs)));
+               log_message(LOG_INFO, "Changing weight from %d to %d for %s service [%s:%d] of VS [%s:%d]"
+                                   , rs->weight
+                                   , weight
+                                   , ISALIVE(rs) ? "active" : "inactive"
+                                   , inet_sockaddrtos2(&rs->addr, rsip)
+                                   , ntohs(inet_sockaddrport(&rs->addr))
+                                   , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
+                                   , ntohs(inet_sockaddrport(&vs->addr)));
                rs->weight = weight;
                /*
                 * Have weight change take effect now only if rs is in
@@ -506,19 +491,18 @@ vsge_exist(virtual_server_group_entry *vsg_entry, list l)
 static int
 clear_diff_vsge(list old, list new, virtual_server * old_vs)
 {
-       element e;
        virtual_server_group_entry *vsge;
+       element e;
 
        for (e = LIST_HEAD(old); e; ELEMENT_NEXT(e)) {
                vsge = ELEMENT_DATA(e);
                if (!vsge_exist(vsge, new)) {
-                       log_message(LOG_INFO, "VS [%s:%d:%d:%d] in group %s"
-                              " no longer exist\n" 
-                              , inet_ntop2(vsge->addr_ip)
-                              , ntohs(vsge->addr_port)
-                              , vsge->range
-                              , vsge->vfwmark
-                              , old_vs->vsgname);
+                       log_message(LOG_INFO, "VS [%s:%d:%d:%d] in group %s no longer exist\n" 
+                                           , inet_sockaddrtos(&vsge->addr)
+                                           , ntohs(inet_sockaddrport(&vsge->addr))
+                                           , vsge->range
+                                           , vsge->vfwmark
+                                           , old_vs->vsgname);
 
                        if (!ipvs_group_remove_entry(old_vs, vsge))
                                return 0;
@@ -644,7 +628,7 @@ clear_diff_rs(virtual_server * old_vs)
        list l = old_vs->rs;
        list new = get_rs_list(old_vs);
        real_server *rs;
-       char rsip[16], vsip[16];
+       char rsip[INET6_ADDRSTRLEN];
 
        /* If old vs didn't own rs then nothing return */
        if (LIST_ISEMPTY(l))
@@ -655,13 +639,13 @@ clear_diff_rs(virtual_server * old_vs)
                if (!rs_exist(rs, new)) {
                        /* Reset inhibit flag to delete inhibit entries */
                        log_message(LOG_INFO, "service [%s:%d] no longer exist"
-                              , inet_ntoa2(SVR_IP(rs), rsip)
-                              , ntohs(SVR_PORT(rs)));
+                                           , inet_sockaddrtos(&rs->addr)
+                                           , ntohs(inet_sockaddrport(&rs->addr)));
                        log_message(LOG_INFO, "Removing service [%s:%d] from VS [%s:%d]"
-                              , inet_ntoa2(SVR_IP(rs), rsip)
-                              , ntohs(SVR_PORT(rs))
-                              , (old_vs->vsgname) ? old_vs->vsgname : inet_ntoa2(SVR_IP(old_vs), vsip)
-                              , ntohs(SVR_PORT(old_vs)));
+                                           , inet_sockaddrtos2(&rs->addr, rsip)
+                                           , ntohs(inet_sockaddrport(&rs->addr))
+                                           , (old_vs->vsgname) ? old_vs->vsgname : inet_sockaddrtos(&old_vs->addr)
+                                           , ntohs(inet_sockaddrport(&old_vs->addr)));
                        rs->inhibit = 0;
                        if (!ipvs_cmd(LVS_CMD_DEL_DEST, check_data->vs_group, old_vs, rs))
                                return 0;
@@ -694,11 +678,11 @@ clear_diff_services(void)
                if (!vs_exist(vs)) {
                        if (vs->vsgname)
                                log_message(LOG_INFO, "Removing Virtual Server Group [%s]"
-                                      , vs->vsgname);
+                                                   , vs->vsgname);
                        else
                                log_message(LOG_INFO, "Removing Virtual Server [%s:%d]"
-                                      , inet_ntop2(vs->addr_ip)
-                                      , ntohs(vs->addr_port));
+                                                   , inet_sockaddrtos(&vs->addr)
+                                                   , ntohs(inet_sockaddrport(&vs->addr)));
 
                        /* Clear VS entry */
                        if (!clear_service_vs(old_check_data->vs_group, vs))
index 3ba7855..ec97248 100644 (file)
@@ -23,6 +23,7 @@
 #include <syslog.h>
 #include <unistd.h>
 #include <pwd.h>
+#include <netdb.h>
 #include "global_data.h"
 #include "memory.h"
 #include "list.h"
@@ -75,12 +76,6 @@ set_default_email_from(conf_data * conf_data_obj)
 }
 
 static void
-set_default_smtp_server(conf_data * conf_data_obj)
-{
-       conf_data_obj->smtp_server = htonl(DEFAULT_SMTP_SERVER);
-}
-
-static void
 set_default_smtp_connection_timeout(conf_data * conf_data_obj)
 {
        conf_data_obj->smtp_connection_to = DEFAULT_SMTP_CONNECTION_TIMEOUT;
@@ -93,7 +88,6 @@ set_default_values(conf_data * conf_data_obj)
        if (!conf_data_obj)
                return;
        set_default_router_id(conf_data_obj);
-       set_default_smtp_server(conf_data_obj);
        set_default_smtp_connection_timeout(conf_data_obj);
        set_default_email_from(conf_data_obj);
 }
@@ -153,16 +147,15 @@ dump_global_data(conf_data * global_data)
                return;
 
        if (data->router_id ||
-           data->smtp_server || data->smtp_connection_to || data->email_from) {
+           data->smtp_server.ss_family || data->smtp_connection_to || data->email_from) {
                log_message(LOG_INFO, "------< Global definitions >------");
        }
        if (data->router_id)
                log_message(LOG_INFO, " Router ID = %s", data->router_id);
        if (data->plugin_dir)
                log_message(LOG_INFO, " Plugin dir = %s", data->plugin_dir);
-       if (data->smtp_server)
-               log_message(LOG_INFO, " Smtp server = %s",
-                      inet_ntop2(data->smtp_server));
+       if (data->smtp_server.ss_family)
+               log_message(LOG_INFO, " Smtp server = %s", inet_sockaddrtos(&data->smtp_server));
        if (data->smtp_connection_to)
                log_message(LOG_INFO, " Smtp server connection timeout = %lu",
                       data->smtp_connection_to / TIMER_HZ);
index 24b4b26..26fc847 100644 (file)
  * Copyright (C) 2001-2010 Alexandre Cassen, <acassen@freebox.fr>
  */
 
+#include <netdb.h>
 #include "global_parser.h"
 #include "global_data.h"
 #include "check_data.h"
 #include "parser.h"
 #include "memory.h"
+#include "smtp.h"
 #include "utils.h"
 
 /* data handlers */
@@ -61,7 +63,7 @@ smtpto_handler(vector strvec)
 static void
 smtpip_handler(vector strvec)
 {
-       inet_ston(VECTOR_SLOT(strvec, 1), &data->smtp_server);
+       inet_stosockaddr(VECTOR_SLOT(strvec, 1), SMTP_PORT_STR, &data->smtp_server);
 }
 static void
 email_handler(vector strvec)
index 9fbd481..28077dc 100644 (file)
 #include "utils.h"
 
 enum connect_result
-tcp_bind_connect(int fd, uint32_t addr_ip, uint16_t addr_port, uint32_t bind_ip)
+tcp_bind_connect(int fd, struct sockaddr_storage *addr, struct sockaddr_storage *bind_addr)
 {
        struct linger li = { 0 };
-       int long_inet;
-       struct sockaddr_in sa_in;
+       socklen_t addrlen;
        int ret;
        int val;
 
        /* free the tcp port after closing the socket descriptor */
        li.l_onoff = 1;
        li.l_linger = 0;
-       setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &li,
-                  sizeof (struct linger));
+       setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof (struct linger));
 
        /* Make socket non-block. */
        val = fcntl(fd, F_GETFL, 0);
        fcntl(fd, F_SETFL, val | O_NONBLOCK);
 
        /* Bind socket */
-       long_inet = sizeof (struct sockaddr_in);
-       memset(&sa_in, 0, long_inet);
-
-       if (bind_ip) {
-               sa_in.sin_family = AF_INET;
-               sa_in.sin_addr.s_addr = bind_ip;
-               if (bind(fd, (struct sockaddr *) &sa_in, sizeof (sa_in)) != 0)
+       if (bind_addr) {
+               addrlen = sizeof(*bind_addr);
+               if (bind(fd, (struct sockaddr *) bind_addr, addrlen) != 0)
                        return connect_error;
        }
 
        /* Set remote IP and connect */
-       memset(&sa_in, 0, long_inet);
-       sa_in.sin_family = AF_INET;
-       sa_in.sin_port = addr_port;
-       sa_in.sin_addr.s_addr = addr_ip;
-
-       ret = connect(fd, (struct sockaddr *) &sa_in, long_inet);
+       addrlen = sizeof(*addr);
+       ret = connect(fd, (struct sockaddr *) addr, addrlen);
 
        /* Immediate success */
        if (ret == 0) {
@@ -81,38 +71,32 @@ tcp_bind_connect(int fd, uint32_t addr_ip, uint16_t addr_port, uint32_t bind_ip)
 }
 
 enum connect_result
-tcp_connect(int fd, uint32_t addr_ip, uint16_t addr_port)
+tcp_connect(int fd, struct sockaddr_storage *addr)
 {
-       return tcp_bind_connect(fd, addr_ip, addr_port, 0);
+       return tcp_bind_connect(fd, addr, NULL);
 }
 
 enum connect_result
-tcp_socket_state(int fd, thread * thread_obj, uint32_t addr_ip, uint16_t addr_port,
-                int (*func) (struct _thread *))
+tcp_socket_state(int fd, thread * thread_obj, int (*func) (struct _thread *))
 {
        int status;
-       socklen_t slen;
+       socklen_t addrlen;
        int ret = 0;
        TIMEVAL timer_min;
 
        /* Handle connection timeout */
        if (thread_obj->type == THREAD_WRITE_TIMEOUT) {
-               DBG("TCP connection timeout to [%s:%d].",
-                   inet_ntop2(addr_ip), ntohs(addr_port));
                close(thread_obj->u.fd);
                return connect_timeout;
        }
 
        /* Check file descriptor */
-       slen = sizeof (status);
-       if (getsockopt
-           (thread_obj->u.fd, SOL_SOCKET, SO_ERROR, (void *) &status, &slen) < 0)
+       addrlen = sizeof(status);
+       if (getsockopt(thread_obj->u.fd, SOL_SOCKET, SO_ERROR, (void *) &status, &addrlen) < 0)
                ret = errno;
 
        /* Connection failed !!! */
        if (ret) {
-               DBG("TCP connection failed to [%s:%d].",
-                   inet_ntop2(addr_ip), ntohs(addr_port));
                close(thread_obj->u.fd);
                return connect_error;
        }
@@ -123,12 +107,9 @@ tcp_socket_state(int fd, thread * thread_obj, uint32_t addr_ip, uint16_t addr_po
         * Recompute the write timeout (or pending connection).
         */
        if (status == EINPROGRESS) {
-               DBG("TCP connection to [%s:%d] still IN_PROGRESS.",
-                   inet_ntop2(addr_ip), ntohs(addr_port));
-
                timer_min = timer_sub_now(thread_obj->sands);
-               thread_add_write(thread_obj->master, func, THREAD_ARG(thread_obj)
-                                , thread_obj->u.fd, TIMER_LONG(timer_min));
+               thread_add_write(thread_obj->master, func, THREAD_ARG(thread_obj),
+                                thread_obj->u.fd, TIMER_LONG(timer_min));
                return connect_in_progress;
        } else if (status != 0) {
                close(thread_obj->u.fd);
@@ -140,8 +121,7 @@ tcp_socket_state(int fd, thread * thread_obj, uint32_t addr_ip, uint16_t addr_po
 
 void
 tcp_connection_state(int fd, enum connect_result status, thread * thread_obj,
-                    int (*func) (struct _thread *)
-                    , long timeout)
+                    int (*func) (struct _thread *), long timeout)
 {
        checker *checker_obj;
 
@@ -149,24 +129,15 @@ tcp_connection_state(int fd, enum connect_result status, thread * thread_obj,
 
        switch (status) {
        case connect_error:
-               DBG("TCP connection ERROR to [%s:%d].",
-                   inet_ntop2(SVR_IP(checker_obj->rs)),
-                   ntohs(SVR_PORT(checker_obj->rs)));
                close(fd);
                break;
 
        case connect_success:
-               DBG("TCP connection SUCCESS to [%s:%d].",
-                   inet_ntop2(SVR_IP(checker_obj->rs)),
-                   ntohs(SVR_PORT(checker_obj->rs)));
                thread_add_write(thread_obj->master, func, checker_obj, fd, timeout);
                break;
 
                /* Checking non-blocking connect, we wait until socket is writable */
        case connect_in_progress:
-               DBG("TCP connection to [%s:%d] now IN_PROGRESS.",
-                   inet_ntop2(SVR_IP(checker_obj->rs)),
-                   ntohs(SVR_PORT(checker_obj->rs)));
                thread_add_write(thread_obj->master, func, checker_obj, fd, timeout);
                break;
 
index 4dfaa13..41d73d1 100644 (file)
@@ -95,8 +95,8 @@ connection_error(thread * thread_obj)
 {
        smtp_thread_arg *smtp_arg = THREAD_ARG(thread_obj);
 
-       log_message(LOG_INFO, "SMTP connection ERROR to [%s:%d].",
-              inet_ntop2(data->smtp_server), SMTP_PORT);
+       log_message(LOG_INFO, "SMTP connection ERROR to [%s:%d]."
+                           , inet_sockaddrtos(&data->smtp_server), SMTP_PORT);
        free_smtp_all(smtp_arg);
        return 0;
 }
@@ -105,8 +105,8 @@ connection_timeout(thread * thread_obj)
 {
        smtp_thread_arg *smtp_arg = THREAD_ARG(thread_obj);
 
-       log_message(LOG_INFO, "Timeout connecting SMTP server [%s:%d].",
-              inet_ntop2(data->smtp_server), SMTP_PORT);
+       log_message(LOG_INFO, "Timeout connecting SMTP server [%s:%d]."
+                           , inet_sockaddrtos(&data->smtp_server), SMTP_PORT);
        free_smtp_all(smtp_arg);
        return 0;
 }
@@ -116,15 +116,13 @@ connection_in_progress(thread * thread_obj)
        int status;
 
        DBG("SMTP connection to [%s:%d] now IN_PROGRESS.",
-           inet_ntop2(data->smtp_server), SMTP_PORT);
+           inet_sockaddrtos(&data->smtp_server), SMTP_PORT);
 
        /*
         * Here we use the propriety of a union structure,
         * each element of the structure have the same value.
         */
-       status =
-           tcp_socket_state(thread_obj->u.fd, thread_obj, data->smtp_server,
-                            htons(SMTP_PORT), connection_in_progress);
+       status = tcp_socket_state(thread_obj->u.fd, thread_obj, connection_in_progress);
 
        if (status != connect_in_progress)
                SMTP_FSM_SEND(status, thread_obj);
@@ -136,8 +134,8 @@ connection_success(thread * thread_obj)
 {
        smtp_thread_arg *smtp_arg = THREAD_ARG(thread_obj);
 
-       log_message(LOG_INFO, "Remote SMTP server [%s:%d] connected.",
-              inet_ntop2(data->smtp_server), SMTP_PORT);
+       log_message(LOG_INFO, "Remote SMTP server [%s:%d] connected."
+                           , inet_sockaddrtos(&data->smtp_server), SMTP_PORT);
 
        smtp_arg->stage = connect_success;
        thread_add_read(thread_obj->master, smtp_read_thread, smtp_arg,
@@ -158,9 +156,8 @@ smtp_read_thread(thread * thread_obj)
        smtp_arg = THREAD_ARG(thread_obj);
 
        if (thread_obj->type == THREAD_READ_TIMEOUT) {
-               log_message(LOG_INFO,
-                      "Timeout reading data to remote SMTP server [%s:%d].",
-                      inet_ntop2(data->smtp_server), SMTP_PORT);
+               log_message(LOG_INFO, "Timeout reading data to remote SMTP server [%s:%d]."
+                                   , inet_sockaddrtos(&data->smtp_server), SMTP_PORT);
                SMTP_FSM_READ(QUIT, thread_obj, 0);
                return -1;
        }
@@ -173,19 +170,17 @@ smtp_read_thread(thread * thread_obj)
        if (rcv_buffer_size == -1) {
                if (errno == EAGAIN)
                        goto end;
-               log_message(LOG_INFO,
-                      "Error reading data from remote SMTP server [%s:%d].",
-                      inet_ntop2(data->smtp_server), SMTP_PORT);
+               log_message(LOG_INFO, "Error reading data from remote SMTP server [%s:%d]."
+                                   , inet_sockaddrtos(&data->smtp_server), SMTP_PORT);
                SMTP_FSM_READ(QUIT, thread_obj, 0);
                return 0;
        }
 
        /* received data overflow buffer size ? */
        if (smtp_arg->buflen >= SMTP_BUFFER_MAX) {
-               log_message(LOG_INFO,
-                      "Received buffer from remote SMTP server [%s:%d]"
-                      " overflow our get read buffer length.",
-                      inet_ntop2(data->smtp_server), SMTP_PORT);
+               log_message(LOG_INFO, "Received buffer from remote SMTP server [%s:%d]"
+                                     " overflow our get read buffer length."
+                                   , inet_sockaddrtos(&data->smtp_server), SMTP_PORT);
                SMTP_FSM_READ(QUIT, thread_obj, 0);
                return 0;
        } else {
@@ -219,9 +214,7 @@ smtp_read_thread(thread * thread_obj)
                        continue;
                }
 
-               status =
-                   ((reply[0] - '0') * 100) + ((reply[1] - '0') * 10) +
-                   (reply[2] - '0');
+               status = ((reply[0] - '0') * 100) + ((reply[1] - '0') * 10) + (reply[2] - '0');
 
                reply = p + 2;
                break;
@@ -244,9 +237,8 @@ smtp_read_thread(thread * thread_obj)
                thread_add_write(thread_obj->master, smtp_send_thread, smtp_arg,
                                 smtp_arg->fd, data->smtp_connection_to);
        } else {
-               log_message(LOG_INFO,
-                      "Can not read data from remote SMTP server [%s:%d].",
-                      inet_ntop2(data->smtp_server), SMTP_PORT);
+               log_message(LOG_INFO, "Can not read data from remote SMTP server [%s:%d]."
+                                   , inet_sockaddrtos(&data->smtp_server), SMTP_PORT);
                SMTP_FSM_READ(QUIT, thread_obj, 0);
        }
 
@@ -259,9 +251,8 @@ smtp_send_thread(thread * thread_obj)
        smtp_thread_arg *smtp_arg = THREAD_ARG(thread_obj);
 
        if (thread_obj->type == THREAD_WRITE_TIMEOUT) {
-               log_message(LOG_INFO,
-                      "Timeout sending data to remote SMTP server [%s:%d].",
-                      inet_ntop2(data->smtp_server), SMTP_PORT);
+               log_message(LOG_INFO, "Timeout sending data to remote SMTP server [%s:%d]."
+                                   , inet_sockaddrtos(&data->smtp_server), SMTP_PORT);
                SMTP_FSM_READ(QUIT, thread_obj, 0);
                return 0;
        }
@@ -281,7 +272,7 @@ smtp_send_thread(thread * thread_obj)
        } else {
                log_message(LOG_INFO,
                       "Can not send data to remote SMTP server [%s:%d].",
-                      inet_ntop2(data->smtp_server), SMTP_PORT);
+                      inet_sockaddrtos(&data->smtp_server), SMTP_PORT);
                SMTP_FSM_READ(QUIT, thread_obj, 0);
        }
 
@@ -297,7 +288,7 @@ connection_code(thread * thread_obj, int status)
                smtp_arg->stage++;
        } else {
                log_message(LOG_INFO, "Error connecting SMTP server[%s:%d]."
-                      " SMTP status code = %d", inet_ntop2(data->smtp_server),
+                      " SMTP status code = %d", inet_sockaddrtos(&data->smtp_server),
                       SMTP_PORT, status);
                smtp_arg->stage = ERROR;
        }
@@ -330,7 +321,7 @@ helo_code(thread * thread_obj, int status)
        } else {
                log_message(LOG_INFO,
                       "Error processing HELO cmd on SMTP server [%s:%d]."
-                      " SMTP status code = %d", inet_ntop2(data->smtp_server),
+                      " SMTP status code = %d", inet_sockaddrtos(&data->smtp_server),
                       SMTP_PORT, status);
                smtp_arg->stage = ERROR;
        }
@@ -363,7 +354,7 @@ mail_code(thread * thread_obj, int status)
        } else {
                log_message(LOG_INFO,
                       "Error processing MAIL cmd on SMTP server [%s:%d]."
-                      " SMTP status code = %d", inet_ntop2(data->smtp_server),
+                      " SMTP status code = %d", inet_sockaddrtos(&data->smtp_server),
                       SMTP_PORT, status);
                smtp_arg->stage = ERROR;
        }
@@ -408,7 +399,7 @@ rcpt_code(thread * thread_obj, int status)
        } else {
                log_message(LOG_INFO,
                       "Error processing RCPT cmd on SMTP server [%s:%d]."
-                      " SMTP status code = %d", inet_ntop2(data->smtp_server),
+                      " SMTP status code = %d", inet_sockaddrtos(&data->smtp_server),
                       SMTP_PORT, status);
                smtp_arg->stage = ERROR;
        }
@@ -422,8 +413,7 @@ data_cmd(thread * thread_obj)
 {
        smtp_thread_arg *smtp_arg = THREAD_ARG(thread_obj);
 
-       if (send(thread_obj->u.fd, SMTP_DATA_CMD, strlen(SMTP_DATA_CMD), 0)
-           == -1)
+       if (send(thread_obj->u.fd, SMTP_DATA_CMD, strlen(SMTP_DATA_CMD), 0) == -1)
                smtp_arg->stage = ERROR;
        return 0;
 }
@@ -437,7 +427,7 @@ data_code(thread * thread_obj, int status)
        } else {
                log_message(LOG_INFO,
                       "Error processing DATA cmd on SMTP server [%s:%d]."
-                      " SMTP status code = %d", inet_ntop2(data->smtp_server),
+                      " SMTP status code = %d", inet_sockaddrtos(&data->smtp_server),
                       SMTP_PORT, status);
                smtp_arg->stage = ERROR;
        }
@@ -495,7 +485,7 @@ body_code(thread * thread_obj, int status)
        } else {
                log_message(LOG_INFO,
                       "Error processing DOT cmd on SMTP server [%s:%d]."
-                      " SMTP status code = %d", inet_ntop2(data->smtp_server),
+                      " SMTP status code = %d", inet_sockaddrtos(&data->smtp_server),
                       SMTP_PORT, status);
                smtp_arg->stage = ERROR;
        }
@@ -509,8 +499,7 @@ quit_cmd(thread * thread_obj)
 {
        smtp_thread_arg *smtp_arg = THREAD_ARG(thread_obj);
 
-       if (send(thread_obj->u.fd, SMTP_QUIT_CMD, strlen(SMTP_QUIT_CMD), 0)
-           == -1)
+       if (send(thread_obj->u.fd, SMTP_QUIT_CMD, strlen(SMTP_QUIT_CMD), 0) == -1)
                smtp_arg->stage = ERROR;
        else
                smtp_arg->stage++;
@@ -533,14 +522,13 @@ smtp_connect(smtp_thread_arg * smtp_arg)
 {
        enum connect_result status;
 
-       if ((smtp_arg->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))
-           == -1) {
+       if ((smtp_arg->fd = socket(data->smtp_server.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
                DBG("SMTP connect fail to create socket.");
                free_smtp_all(smtp_arg);
                return;
        }
 
-       status = tcp_connect(smtp_arg->fd, data->smtp_server, htons(SMTP_PORT));
+       status = tcp_connect(smtp_arg->fd, &data->smtp_server);
 
        /* Handle connection status code */
        thread_add_event(master, SMTP_FSM[status].send, smtp_arg, smtp_arg->fd);
@@ -554,7 +542,7 @@ smtp_alert(real_server * rs, vrrp_rt * vrrp,
        smtp_thread_arg *smtp_arg;
 
        /* Only send mail if email specified */
-       if (!LIST_ISEMPTY(data->email) && data->smtp_server != 0) {
+       if (!LIST_ISEMPTY(data->email) && data->smtp_server.ss_family != 0) {
                /* allocate & initialize smtp argument data structure */
                smtp_arg = (smtp_thread_arg *) MALLOC(sizeof (smtp_thread_arg));
                smtp_arg->subject = (char *) MALLOC(MAX_HEADERS_LENGTH);
@@ -562,13 +550,12 @@ smtp_alert(real_server * rs, vrrp_rt * vrrp,
                smtp_arg->buffer = (char *) MALLOC(SMTP_BUFFER_MAX);
 
                /* format subject if rserver is specified */
-               if (rs)
-                       snprintf(smtp_arg->subject, MAX_HEADERS_LENGTH,
-                                "[%s] Realserver %s:%d - %s",
-                                data->router_id, inet_ntop2(SVR_IP(rs))
-                                , ntohs(SVR_PORT(rs))
+               if (rs) {
+                       snprintf(smtp_arg->subject, MAX_HEADERS_LENGTH, "[%s] Realserver %s:%d - %s"
+                                , data->router_id, inet_sockaddrtos(&rs->addr)
+                                , ntohs(inet_sockaddrport(&rs->addr))
                                 , subject);
-               else if (vrrp)
+               } else if (vrrp)
                        snprintf(smtp_arg->subject, MAX_HEADERS_LENGTH,
                                 "[%s] VRRP Instance %s - %s",
                                 data->router_id, vrrp->iname, subject);
index aea1ee4..a5802be 100644 (file)
@@ -49,10 +49,6 @@ extern list checkers_queue;
 #define CHECKER_GET() (CHECKER_DATA(LIST_TAIL_DATA(checkers_queue)))
 #define CHECKER_VALUE_INT(X) (atoi(VECTOR_SLOT(X,1)))
 #define CHECKER_VALUE_STRING(X) (set_value(X))
-#define CHECKER_VIP(C)   (SVR_IP((C)->vs))
-#define CHECKER_VPORT(C) (SVR_PORT((C)->vs))
-#define CHECKER_RIP(C)   (SVR_IP((C)->rs))
-#define CHECKER_RPORT(C) (SVR_PORT((C)->rs))
 #define CHECKER_VHOST(C) (VHOST((C)->vs))
 #define CHECKER_ENABLED(C) ((C)->enabled)
 #define CHECKER_ENABLE(C)  ((C)->enabled = 1)
@@ -63,11 +59,13 @@ extern list checkers_queue;
 extern void init_checkers_queue(void);
 extern void queue_checker(void (*free_func) (void *), void (*dump_func) (void *)
                          , int (*launch) (struct _thread *)
-                         , void *data);
+                         , void *);
 extern void dump_checkers_queue(void);
 extern void free_checkers_queue(void);
 extern void register_checkers_thread(void);
 extern void install_checkers_keyword(void);
-extern void update_checker_activity(uint32_t address, int enable);
+extern void update_checker_activity(sa_family_t, void *, int);
+extern void checker_set_dst(struct sockaddr_storage *);
+extern void checker_set_dst_port(struct sockaddr_storage *, uint16_t);
 
 #endif
index 7a3ef47..f6f2b79 100644 (file)
 #include <openssl/ssl.h>
 
 #ifdef _WITH_LVS_
+  #ifdef _KRNL_2_4_
+    #include <net/ip_vs.h>
+  #elif _KRNL_2_6_
+    #include "../libipvs-2.6/ip_vs.h"
+  #endif
   #define SCHED_MAX_LENGTH IP_VS_SCHEDNAME_MAXLEN
-  #include <net/ip_vs.h>
 #else
   #define SCHED_MAX_LENGTH   1
 #endif
@@ -65,8 +69,7 @@ typedef struct _ssl_data {
 
 /* Real Server definition */
 typedef struct _real_server {
-       uint32_t addr_ip;
-       uint16_t addr_port;
+       struct sockaddr_storage addr;
        int weight;
        int iweight;            /* Initial weight */
 #ifdef _KRNL_2_6_
@@ -85,10 +88,9 @@ typedef struct _real_server {
 
 /* Virtual Server group definition */
 typedef struct _virtual_server_group_entry {
-       uint32_t addr_ip;
+       struct sockaddr_storage addr;
        uint8_t range;
        uint32_t vfwmark;
-       uint16_t addr_port;
        int alive;
 } virtual_server_group_entry;
 
@@ -102,8 +104,8 @@ typedef struct _virtual_server_group {
 /* Virtual Server definition */
 typedef struct _virtual_server {
        char *vsgname;
-       uint32_t addr_ip;
-       uint16_t addr_port;
+       struct sockaddr_storage addr;
+       real_server *s_svr;
        uint32_t vfwmark;
        uint16_t service_type;
        long delay_loop;
@@ -114,14 +116,14 @@ typedef struct _virtual_server {
        uint32_t nat_mask;
        uint32_t granularity_persistence;
        char *virtualhost;
-       real_server *s_svr;
        list rs;
        int alive;
        unsigned alpha;                 /* Alpha mode enabled. */
        unsigned omega;                 /* Omega mode enabled. */
-       char * quorum_up;               /* A hook to call when the VS gains quorum. */
+       char *quorum_up;                /* A hook to call when the VS gains quorum. */
        char * quorum_down;             /* A hook to call when the VS loses quorum. */
        long unsigned quorum;           /* Minimum live RSs to consider VS up. */
+
        long unsigned hysteresis;       /* up/down events "lag" WRT quorum. */
        unsigned quorum_state;          /* Reflects result of the last transition done. */
 } virtual_server;
@@ -133,34 +135,84 @@ typedef struct _check_conf_data {
        list vs;
 } check_conf_data;
 
+/* inline stuff */
+static inline int __ip6_addr_equal(const struct in6_addr *a1,
+                                  const struct in6_addr *a2)
+{
+       return (((a1->s6_addr32[0] ^ a2->s6_addr32[0]) |
+                (a1->s6_addr32[1] ^ a2->s6_addr32[1]) |
+                (a1->s6_addr32[2] ^ a2->s6_addr32[2]) |
+                (a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0);
+}
+
+static inline int sockstorage_equal(const struct sockaddr_storage *s1,
+                                   const struct sockaddr_storage *s2)
+{
+       if (s1->ss_family != s2->ss_family)
+               return 0;
+
+       if (s1->ss_family == AF_INET6) {
+               struct sockaddr_in6 *a1 = (struct sockaddr_in6 *) s1;
+               struct sockaddr_in6 *a2 = (struct sockaddr_in6 *) s2;
+
+//             if (IN6_ARE_ADDR_EQUAL(a1, a2) && (a1->sin6_port == a2->sin6_port))
+               if (__ip6_addr_equal(&a1->sin6_addr, &a2->sin6_addr) &&
+                   (a1->sin6_port == a2->sin6_port))
+                       return 1;
+       } else if (s1->ss_family == AF_INET) {
+               struct sockaddr_in *a1 = (struct sockaddr_in *) s1;
+               struct sockaddr_in *a2 = (struct sockaddr_in *) s2;
+
+               if ((a1->sin_addr.s_addr == a1->sin_addr.s_addr) &&
+                   (a1->sin_port == a2->sin_port))
+                       return 1;
+       }
+
+       return 0;
+}
+
+static inline int inaddr_equal(sa_family_t family, void *addr1, void *addr2)
+{
+       if (family == AF_INET6) {
+               struct in6_addr *a1 = (struct in6_addr *) addr1;
+               struct in6_addr *a2 = (struct in6_addr *) addr2;
+
+               if (__ip6_addr_equal(a1, a2))
+                       return 1;
+       } else if (family == AF_INET) {
+               struct in_addr *a1 = (struct in_addr *) addr1;
+               struct in_addr *a2 = (struct in_addr *) addr2;
+
+               if (a1->s_addr == a2->s_addr)
+                       return 1;
+       }
+
+       return 0;
+}
+
 /* macro utility */
 #define ISALIVE(S)     ((S)->alive)
 #define SET_ALIVE(S)   ((S)->alive = 1)
 #define UNSET_ALIVE(S) ((S)->alive = 0)
-#define SVR_IP(H)      ((H)->addr_ip)
-#define SVR_PORT(H)    ((H)->addr_port)
 #define VHOST(V)       ((V)->virtualhost)
 
-#define VS_ISEQ(X,Y)   ((X)->addr_ip                 == (Y)->addr_ip &&                \
-                        (X)->addr_port               == (Y)->addr_port &&              \
-                        (X)->vfwmark                 == (Y)->vfwmark &&                \
-                        (X)->service_type            == (Y)->service_type &&           \
-                        (X)->loadbalancing_kind      == (Y)->loadbalancing_kind &&     \
-                        (X)->nat_mask                == (Y)->nat_mask &&               \
-                        (X)->granularity_persistence == (Y)->granularity_persistence &&\
-                        !strcmp((X)->sched, (Y)->sched) &&                             \
-                        !strcmp((X)->timeout_persistence, (Y)->timeout_persistence) && \
+#define VS_ISEQ(X,Y)   (sockstorage_equal(&(X)->addr,&(Y)->addr)                       &&\
+                        (X)->vfwmark                 == (Y)->vfwmark                   &&\
+                        (X)->service_type            == (Y)->service_type              &&\
+                        (X)->loadbalancing_kind      == (Y)->loadbalancing_kind        &&\
+                        (X)->nat_mask                == (Y)->nat_mask                  &&\
+                        (X)->granularity_persistence == (Y)->granularity_persistence   &&\
+                        !strcmp((X)->sched, (Y)->sched)                                &&\
+                        !strcmp((X)->timeout_persistence, (Y)->timeout_persistence)    &&\
                         (((X)->vsgname && (Y)->vsgname &&                              \
                           !strcmp((X)->vsgname, (Y)->vsgname)) ||                      \
                          (!(X)->vsgname && !(Y)->vsgname)))
 
-#define VSGE_ISEQ(X,Y) ((X)->addr_ip   == (Y)->addr_ip &&      \
-                        (X)->range     == (Y)->range &&        \
-                        (X)->vfwmark   == (Y)->vfwmark &&      \
-                        (X)->addr_port == (Y)->addr_port)
+#define VSGE_ISEQ(X,Y) (sockstorage_equal(&(X)->addr,&(Y)->addr) &&    \
+                        (X)->range     == (Y)->range &&                \
+                        (X)->vfwmark   == (Y)->vfwmark)
 
-#define RS_ISEQ(X,Y)   ((X)->addr_ip   == (Y)->addr_ip &&      \
-                        (X)->addr_port == (Y)->addr_port &&    \
+#define RS_ISEQ(X,Y)   (sockstorage_equal(&(X)->addr,&(Y)->addr) &&    \
                         (X)->iweight   == (Y)->iweight)
 
 /* Global vars exported */
index 9d1786b..4e2969d 100644 (file)
@@ -63,8 +63,8 @@ typedef struct _url {
 } url;
 typedef struct _http_get_checker {
        int proto;
-       uint16_t connection_port;
-       uint32_t bindto;
+       struct sockaddr_storage dst;
+       struct sockaddr_storage bindto;
        long connection_to;
        int nb_get_retry;
        long delay_before_retry;
index 06f0b5d..4fd2652 100644 (file)
@@ -46,9 +46,8 @@
 
 /* Per host configuration structure  */
 typedef struct _smtp_host {
-       uint16_t port;
-       uint32_t ip;
-       uint32_t bindto;
+       struct sockaddr_storage dst;
+       struct sockaddr_storage bindto;
 } smtp_host;
 
 /* Checker argument structure  */
index ee4a535..c007599 100644 (file)
@@ -33,8 +33,8 @@
 
 /* Checker argument structure  */
 typedef struct _tcp_checker {
-       uint16_t connection_port;
-       uint32_t bindto;
+       struct sockaddr_storage dst;
+       struct sockaddr_storage bindto;
        int connection_to;
 } tcp_checker;
 
index 9e2aedc..d11f334 100644 (file)
@@ -48,7 +48,7 @@ typedef struct _conf_data {
        char *router_id;
        char *plugin_dir;
        char *email_from;
-       uint32_t smtp_server;
+       struct sockaddr_storage smtp_server;
        long smtp_connection_to;
        list email;
 } conf_data;
index 4f21413..7215619 100644 (file)
 #ifdef _WITH_LVS_
 #ifdef _KRNL_2_4_
   #include "../libipvs-2.4/libipvs.h"
+  #include <net/ip_vs.h>
 #elif _KRNL_2_6_
+  #include "../libipvs-2.6/ip_vs.h"
   #include "../libipvs-2.6/libipvs.h"
 #endif
-  #include <net/ip_vs.h>
+//  #include <net/ip_vs.h>
 #endif
 
 #ifndef IP_VS_TEMPLATE_TIMEOUT
index 9705ba4..39af630 100644 (file)
@@ -44,14 +44,13 @@ enum connect_result {
 
 /* Prototypes defs */
 extern enum connect_result
- tcp_bind_connect(int, uint32_t, uint16_t, uint32_t);
+ tcp_bind_connect(int, struct sockaddr_storage *, struct sockaddr_storage *);
 
 extern enum connect_result
- tcp_connect(int, uint32_t, uint16_t);
+ tcp_connect(int, struct sockaddr_storage *);
 
 extern enum connect_result
- tcp_socket_state(int, thread *, uint32_t, uint16_t,
-                 int (*func) (struct _thread *));
+ tcp_socket_state(int, thread *, int (*func) (struct _thread *));
 
 extern void
  tcp_connection_state(int, enum connect_result
index aab0cb3..a811b30 100644 (file)
@@ -34,6 +34,7 @@
 #include "vrrp.h"
 
 /* global defs */
+#define SMTP_PORT_STR          "25"
 #define SMTP_PORT              25
 #define SMTP_BUFFER_LENGTH     512
 #define SMTP_BUFFER_MAX                1024
index 79ef8ce..690f6b5 100644 (file)
@@ -1,18 +1,22 @@
-# Makefile to make libipvsc.
+# Makefile for libipvs
 
-CC     = @CC@
-CFLAGS = @CFLAGS@ @CPPFLAGS@ -Wall -Wunused
+CC             = @CC@
+CFLAGS         = @CFLAGS@ @CPPFLAGS@ -D@USE_NL@ -Wall -Wunused
 
 export OBJS += libipvs.a
 
-all: libipvs.a
+STATIC_LIB     = libipvs.a
 
-libipvs.a: libipvs.a(libipvs.o)
+all:           $(STATIC_LIB)
 
-libipvsc.o: libipvs.h
+$(STATIC_LIB): libipvs.o ip_vs_nl_policy.o
+               ar rv $@ $^
+               rm $^
+
+%.o:           %.c
+               $(CC) $(CFLAGS) -c -o $@ $<
 
 clean:
-       rm -f *.a *.o *~
+               rm -f *.[ao] *~ *.orig *.rej core
 
-distclean: clean
-       rm -f Makefile
+distclean:     clean
index c94fd79..2c75118 100644 (file)
 #include <netinet/in.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <arpa/inet.h>
 
+#include "ip_vs.h"
 #include "libipvs.h"
 
-
 typedef struct ipvs_servicedest_s {
-       ipvs_service_t          svc;
-       ipvs_dest_t             dest;
+       struct ip_vs_service_kern       svc;
+       struct ip_vs_dest_kern          dest;
 } ipvs_servicedest_t;
 
 static int sockfd = -1;
 static void* ipvs_func = NULL;
 struct ip_vs_getinfo ipvs_info;
 
+#ifdef LIBIPVS_USE_NL
+struct nl_handle *sock = NULL;
+int family, try_nl = 1;
+#endif
+
+#define CHECK_IPV4(s, ret) if (s->af && s->af != AF_INET)      \
+       { errno = EAFNOSUPPORT; return ret; }                   \
+       s->__addr_v4 = s->addr.ip;                              \
+
+#ifdef LIBIPVS_USE_NL
+struct nl_msg *ipvs_nl_message(int cmd, int flags) {
+       struct nl_msg *msg;
+
+       msg = nlmsg_alloc();
+       if (!msg)
+               return NULL;
+
+       genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, flags,
+                   cmd, IPVS_GENL_VERSION);
+
+       return msg;
+}
+
+static int ipvs_nl_noop_cb(struct nl_msg *msg, void *arg) {
+       return NL_OK;
+}
+
+int ipvs_nl_send_message(struct nl_msg *msg, nl_recvmsg_msg_cb_t func, void *arg) {
+       int err = EINVAL;
+
+       sock = nl_handle_alloc();
+       if (!sock) {
+               nlmsg_free(msg);
+               return -1;
+       }
+       
+       if (genl_connect(sock) < 0)
+               goto fail_genl;
+       
+       family = genl_ctrl_resolve(sock, IPVS_GENL_NAME);
+       if (family < 0)
+               goto fail_genl;
+
+       /* To test connections and set the family */
+       if (msg == NULL) {
+               nl_handle_destroy(sock);
+               sock = NULL;
+               return 0;
+       }
+
+       if (nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, func, arg) != 0)
+               goto fail_genl;
+
+       if (nl_send_auto_complete(sock, msg) < 0)
+               goto fail_genl;
+
+       if ((err = -nl_recvmsgs_default(sock)) > 0)
+               goto fail_genl;
+
+       nlmsg_free(msg);
+
+       nl_handle_destroy(sock);
+
+       return 0;
+
+fail_genl:
+       nl_handle_destroy(sock);
+       sock = NULL;
+       nlmsg_free(msg);
+       errno = err;
+       return -1;
+}
+#endif
+
 int ipvs_init(void)
 {
        socklen_t len;
 
+       ipvs_func = ipvs_init;
+
+#ifdef LIBIPVS_USE_NL
+       if (ipvs_nl_send_message(NULL, NULL, NULL) == 0) {
+               return ipvs_getinfo();
+       }
+
+       try_nl = 0;
+#endif
+
        len = sizeof(ipvs_info);
        if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1)
                return -1;
@@ -47,11 +132,42 @@ int ipvs_init(void)
        return 0;
 }
 
+#ifdef LIBIPVS_USE_NL
+static int ipvs_getinfo_parse_cb(struct nl_msg *msg, void *arg)
+{
+       struct nlmsghdr *nlh = nlmsg_hdr(msg);
+       struct nlattr *attrs[IPVS_INFO_ATTR_MAX + 1];
+
+       if (genlmsg_parse(nlh, 0, attrs, IPVS_INFO_ATTR_MAX, ipvs_info_policy) != 0)
+               return -1;
+       
+       if (!(attrs[IPVS_INFO_ATTR_VERSION] &&
+             attrs[IPVS_INFO_ATTR_CONN_TAB_SIZE]))
+               return -1;
+
+       ipvs_info.version = nla_get_u32(attrs[IPVS_INFO_ATTR_VERSION]);
+       ipvs_info.size = nla_get_u32(attrs[IPVS_INFO_ATTR_CONN_TAB_SIZE]);
+       
+       return NL_OK;
+}
+#endif
 
 int ipvs_getinfo(void)
 {
        socklen_t len;
 
+#ifdef LIBIPVS_USE_NL
+       if (try_nl) {
+               struct nl_msg *msg;
+               msg = ipvs_nl_message(IPVS_CMD_GET_INFO, 0);
+               if (msg)
+                       return ipvs_nl_send_message(msg, ipvs_getinfo_parse_cb,
+                                                   NULL);
+               return -1;
+       }
+#endif
+
+       ipvs_func = ipvs_getinfo;
        len = sizeof(ipvs_info);
        return getsockopt(sockfd, IPPROTO_IP, IP_VS_SO_GET_INFO,
                          (char *)&ipvs_info, &len);
@@ -66,48 +182,184 @@ unsigned int ipvs_version(void)
 
 int ipvs_flush(void)
 {
-       return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_FLUSH,
-                         NULL, 0);
+#ifdef LIBIPVS_USE_NL
+       if (try_nl) {
+               struct nl_msg *msg = ipvs_nl_message(IPVS_CMD_FLUSH, 0);
+               if (msg && (ipvs_nl_send_message(msg, ipvs_nl_noop_cb, NULL) == 0))
+                       return 0;
+
+               return -1;
+       }
+#endif
+       return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_FLUSH, NULL, 0);
 }
 
+#ifdef LIBIPVS_USE_NL
+static int ipvs_nl_fill_service_attr(struct nl_msg *msg, ipvs_service_t *svc) {
+       struct nlattr *nl_service;
+       struct ip_vs_flags flags = { .flags = svc->flags,
+                                    .mask = ~0 };
+       
+       nl_service = nla_nest_start(msg, IPVS_CMD_ATTR_SERVICE);
+       if (!nl_service)
+               return -1;
+       
+       NLA_PUT_U16(msg, IPVS_SVC_ATTR_AF, svc->af);
+
+       if (svc->fwmark) {
+               NLA_PUT_U32(msg, IPVS_SVC_ATTR_FWMARK, svc->fwmark);
+       } else {
+               NLA_PUT_U16(msg, IPVS_SVC_ATTR_PROTOCOL, svc->protocol);
+               NLA_PUT(msg, IPVS_SVC_ATTR_ADDR, sizeof(svc->addr), &(svc->addr));
+               NLA_PUT_U16(msg, IPVS_SVC_ATTR_PORT, svc->port);
+       }
+
+       NLA_PUT_STRING(msg, IPVS_SVC_ATTR_SCHED_NAME, svc->sched_name);
+       NLA_PUT(msg, IPVS_SVC_ATTR_FLAGS, sizeof(flags), &flags);
+       NLA_PUT_U32(msg, IPVS_SVC_ATTR_TIMEOUT, svc->timeout);
+       NLA_PUT_U32(msg, IPVS_SVC_ATTR_NETMASK, svc->netmask);
+       
+       nla_nest_end(msg, nl_service);
+       return 0;
+
+nla_put_failure:
+       return -1;
+}
+#endif
 
 int ipvs_add_service(ipvs_service_t *svc)
 {
        ipvs_func = ipvs_add_service;
-       return setsockopt(sockfd, IPPROTO_IP,
-                         IP_VS_SO_SET_ADD, (char *)svc, sizeof(*svc));
+#ifdef LIBIPVS_USE_NL
+       if (try_nl) {
+               struct nl_msg *msg = ipvs_nl_message(IPVS_CMD_NEW_SERVICE, 0);
+               if (!msg) return -1;
+               if (ipvs_nl_fill_service_attr(msg, svc)) {
+                       nlmsg_free(msg);
+                       return -1;
+               }
+               return ipvs_nl_send_message(msg, ipvs_nl_noop_cb, NULL);
+       }
+#endif
+
+       CHECK_IPV4(svc, -1);
+       return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_ADD, (char *)svc,
+                         sizeof(struct ip_vs_service_kern));
 }
 
 
 int ipvs_update_service(ipvs_service_t *svc)
 {
        ipvs_func = ipvs_update_service;
-       return setsockopt(sockfd, IPPROTO_IP,
-                         IP_VS_SO_SET_EDIT, (char *)svc, sizeof(*svc));
+#ifdef LIBIPVS_USE_NL
+       if (try_nl) {
+               struct nl_msg *msg = ipvs_nl_message(IPVS_CMD_SET_SERVICE, 0);
+               if (!msg) return -1;
+               if (ipvs_nl_fill_service_attr(msg, svc)) {
+                       nlmsg_free(msg);
+                       return -1;
+               }
+               return ipvs_nl_send_message(msg, ipvs_nl_noop_cb, NULL);
+       }
+#endif
+       CHECK_IPV4(svc, -1);
+       return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_EDIT, (char *)svc,
+                         sizeof(struct ip_vs_service_kern));
 }
 
 
 int ipvs_del_service(ipvs_service_t *svc)
 {
        ipvs_func = ipvs_del_service;
-       return setsockopt(sockfd, IPPROTO_IP,
-                         IP_VS_SO_SET_DEL, (char *)svc, sizeof(*svc));
+#ifdef LIBIPVS_USE_NL
+       if (try_nl) {
+               struct nl_msg *msg = ipvs_nl_message(IPVS_CMD_DEL_SERVICE, 0);
+               if (!msg) return -1;
+               if (ipvs_nl_fill_service_attr(msg, svc)) {
+                       nlmsg_free(msg);
+                       return -1;
+               }
+               return ipvs_nl_send_message(msg, ipvs_nl_noop_cb, NULL);
+       }
+#endif
+       CHECK_IPV4(svc, -1);
+       return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_DEL, (char *)svc,
+                         sizeof(struct ip_vs_service_kern));
 }
 
 
 int ipvs_zero_service(ipvs_service_t *svc)
 {
        ipvs_func = ipvs_zero_service;
-       return setsockopt(sockfd, IPPROTO_IP,
-                         IP_VS_SO_SET_ZERO, (char *)svc, sizeof(*svc));
+#ifdef LIBIPVS_USE_NL
+       if (try_nl) {
+               struct nl_msg *msg = ipvs_nl_message(IPVS_CMD_ZERO, 0);
+               if (!msg) return -1;
+
+               if (svc->fwmark
+                   || memcmp(&in6addr_any, &svc->addr.in6, sizeof(struct in6_addr))
+                   || svc->port) {
+                       if (ipvs_nl_fill_service_attr(msg, svc)) {
+                               nlmsg_free(msg);
+                               return -1;
+                       }
+               }
+               return ipvs_nl_send_message(msg, ipvs_nl_noop_cb, NULL);
+       }
+#endif
+       CHECK_IPV4(svc, -1);
+       return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_ZERO, (char *)svc,
+                         sizeof(struct ip_vs_service_kern));
 }
 
+#ifdef LIBIPVS_USE_NL
+static int ipvs_nl_fill_dest_attr(struct nl_msg *msg, ipvs_dest_t *dst) {
+       struct nlattr *nl_dest;
+       
+       nl_dest = nla_nest_start(msg, IPVS_CMD_ATTR_DEST);
+       if (!nl_dest)
+               return -1;
+       
+       NLA_PUT(msg, IPVS_DEST_ATTR_ADDR, sizeof(dst->addr), &(dst->addr));
+       NLA_PUT_U16(msg, IPVS_DEST_ATTR_PORT, dst->port);
+       NLA_PUT_U32(msg, IPVS_DEST_ATTR_FWD_METHOD, dst->conn_flags & IP_VS_CONN_F_FWD_MASK);
+       NLA_PUT_U32(msg, IPVS_DEST_ATTR_WEIGHT, dst->weight);
+       NLA_PUT_U32(msg, IPVS_DEST_ATTR_U_THRESH, dst->u_threshold);
+       NLA_PUT_U32(msg, IPVS_DEST_ATTR_L_THRESH, dst->l_threshold);
+       
+       nla_nest_end(msg, nl_dest);
+       return 0;
+
+nla_put_failure:
+       return -1;
+}
+#endif
 
 int ipvs_add_dest(ipvs_service_t *svc, ipvs_dest_t *dest)
 {
-       ipvs_servicedest_t svcdest = {*svc, *dest};
+       ipvs_servicedest_t svcdest;
 
+#ifdef LIBIPVS_USE_NL
        ipvs_func = ipvs_add_dest;
+       if (try_nl) {
+               struct nl_msg *msg = ipvs_nl_message(IPVS_CMD_NEW_DEST, 0);
+               if (!msg) return -1;
+               if (ipvs_nl_fill_service_attr(msg, svc))
+                       goto nla_put_failure;
+               if (ipvs_nl_fill_dest_attr(msg, dest))
+                       goto nla_put_failure;
+               return ipvs_nl_send_message(msg, ipvs_nl_noop_cb, NULL);
+
+nla_put_failure:
+               nlmsg_free(msg);
+               return -1;
+       }
+#endif
+
+       CHECK_IPV4(svc, -1);
+       CHECK_IPV4(dest, -1);
+       memcpy(&svcdest.svc, svc, sizeof(svcdest.svc));
+       memcpy(&svcdest.dest, dest, sizeof(svcdest.dest));
        return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_ADDDEST,
                          (char *)&svcdest, sizeof(svcdest));
 }
@@ -115,9 +367,28 @@ int ipvs_add_dest(ipvs_service_t *svc, ipvs_dest_t *dest)
 
 int ipvs_update_dest(ipvs_service_t *svc, ipvs_dest_t *dest)
 {
-       ipvs_servicedest_t svcdest = {*svc, *dest};
+       ipvs_servicedest_t svcdest;
 
        ipvs_func = ipvs_update_dest;
+#ifdef LIBIPVS_USE_NL
+       if (try_nl) {
+               struct nl_msg *msg = ipvs_nl_message(IPVS_CMD_SET_DEST, 0);
+               if (!msg) return -1;
+               if (ipvs_nl_fill_service_attr(msg, svc))
+                       goto nla_put_failure;
+               if (ipvs_nl_fill_dest_attr(msg, dest))
+                       goto nla_put_failure;
+               return ipvs_nl_send_message(msg, ipvs_nl_noop_cb, NULL);
+
+nla_put_failure:
+               nlmsg_free(msg);
+               return -1;
+       }
+#endif
+       CHECK_IPV4(svc, -1);
+       CHECK_IPV4(dest, -1);
+       memcpy(&svcdest.svc, svc, sizeof(svcdest.svc));
+       memcpy(&svcdest.dest, dest, sizeof(svcdest.dest));
        return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_EDITDEST,
                          (char *)&svcdest, sizeof(svcdest));
 }
@@ -125,9 +396,29 @@ int ipvs_update_dest(ipvs_service_t *svc, ipvs_dest_t *dest)
 
 int ipvs_del_dest(ipvs_service_t *svc, ipvs_dest_t *dest)
 {
-       ipvs_servicedest_t svcdest = {*svc, *dest};
+       ipvs_servicedest_t svcdest;
 
        ipvs_func = ipvs_del_dest;
+#ifdef LIBIPVS_USE_NL
+       if (try_nl) {
+               struct nl_msg *msg = ipvs_nl_message(IPVS_CMD_DEL_DEST, 0);
+               if (!msg) return -1;
+               if (ipvs_nl_fill_service_attr(msg, svc))
+                       goto nla_put_failure;
+               if (ipvs_nl_fill_dest_attr(msg, dest))
+                       goto nla_put_failure;
+               return ipvs_nl_send_message(msg, ipvs_nl_noop_cb, NULL);
+
+nla_put_failure:
+               nlmsg_free(msg);
+               return -1;
+       }
+#endif
+
+       CHECK_IPV4(svc, -1);
+       CHECK_IPV4(dest, -1);
+       memcpy(&svcdest.svc, svc, sizeof(svcdest.svc));
+       memcpy(&svcdest.dest, dest, sizeof(svcdest.dest));
        return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_DELDEST,
                          (char *)&svcdest, sizeof(svcdest));
 }
@@ -136,71 +427,238 @@ int ipvs_del_dest(ipvs_service_t *svc, ipvs_dest_t *dest)
 int ipvs_set_timeout(ipvs_timeout_t *to)
 {
        ipvs_func = ipvs_set_timeout;
-       return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_TIMEOUT,
-                         (char *)to, sizeof(*to));
+#ifdef LIBIPVS_USE_NL
+       if (try_nl) {
+               struct nl_msg *msg = ipvs_nl_message(IPVS_CMD_SET_TIMEOUT, 0);
+               if (!msg) return -1;
+               NLA_PUT_U32(msg, IPVS_CMD_ATTR_TIMEOUT_TCP, to->tcp_timeout);
+               NLA_PUT_U32(msg, IPVS_CMD_ATTR_TIMEOUT_TCP_FIN, to->tcp_fin_timeout);
+               NLA_PUT_U32(msg, IPVS_CMD_ATTR_TIMEOUT_UDP, to->udp_timeout);
+               return ipvs_nl_send_message(msg, ipvs_nl_noop_cb, NULL);
+
+nla_put_failure:
+               nlmsg_free(msg);
+               return -1;
+       }
+#endif
+       return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_TIMEOUT, (char *)to,
+                         sizeof(*to));
 }
 
 
-static int _ipvs_start_daemon(void *dm)
+int ipvs_start_daemon(ipvs_daemon_t *dm)
 {
        ipvs_func = ipvs_start_daemon;
-       setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_STARTDAEMON,
-                  (char *)dm, sizeof(struct ip_vs_daemon_user));
-       exit(0);
+#ifdef LIBIPVS_USE_NL
+       if (try_nl) {
+               struct nlattr *nl_daemon;
+               struct nl_msg *msg = ipvs_nl_message(IPVS_CMD_NEW_DAEMON, 0);
+               if (!msg) return -1;
+
+               nl_daemon = nla_nest_start(msg, IPVS_CMD_ATTR_DAEMON);
+               if (!nl_daemon)
+                       goto nla_put_failure;
+
+               NLA_PUT_U32(msg, IPVS_DAEMON_ATTR_STATE, dm->state);
+               NLA_PUT_STRING(msg, IPVS_DAEMON_ATTR_MCAST_IFN, dm->mcast_ifn);
+               NLA_PUT_U32(msg, IPVS_DAEMON_ATTR_SYNC_ID, dm->syncid);
+
+               nla_nest_end(msg, nl_daemon);
+
+               return ipvs_nl_send_message(msg, ipvs_nl_noop_cb, NULL);
+
+nla_put_failure:
+               nlmsg_free(msg);
+               return -1;
+       }
+#endif
+       return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_STARTDAEMON,
+                         (char *)dm, sizeof(*dm));
 }
 
 
-static int _ipvs_stop_daemon(void *dm)
+int ipvs_stop_daemon(ipvs_daemon_t *dm)
 {
        ipvs_func = ipvs_stop_daemon;
-       setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_STOPDAEMON,
-                  (char *)dm, sizeof(struct ip_vs_daemon_user));
-       exit(0);
+#ifdef LIBIPVS_USE_NL
+       if (try_nl) {
+               struct nlattr *nl_daemon;
+               struct nl_msg *msg = ipvs_nl_message(IPVS_CMD_DEL_DAEMON, 0);
+               if (!msg) return -1;
+
+               nl_daemon = nla_nest_start(msg, IPVS_CMD_ATTR_DAEMON);
+               if (!nl_daemon)
+                       goto nla_put_failure;
+
+               NLA_PUT_U32(msg, IPVS_DAEMON_ATTR_STATE, dm->state);
+               NLA_PUT_STRING(msg, IPVS_DAEMON_ATTR_MCAST_IFN, dm->mcast_ifn);
+               NLA_PUT_U32(msg, IPVS_DAEMON_ATTR_SYNC_ID, dm->syncid);
+
+               nla_nest_end(msg, nl_daemon);
+
+               return ipvs_nl_send_message(msg, ipvs_nl_noop_cb, NULL);
+
+nla_put_failure:
+               nlmsg_free(msg);
+               return -1;
+       }
+#endif
+       return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_STOPDAEMON,
+                         (char *)dm, sizeof(*dm));
 }
 
-int ipvs_start_daemon(ipvs_daemon_t *dm)
-{
-       pid_t pid;
+#ifdef LIBIPVS_USE_NL
+static int ipvs_parse_stats(struct ip_vs_stats_user *stats, struct nlattr *nla) {
+       struct nlattr *attrs[IPVS_STATS_ATTR_MAX + 1];
+
+       if (nla_parse_nested(attrs, IPVS_STATS_ATTR_MAX, nla, ipvs_stats_policy))
+               return -1;
+       
+       if (!(attrs[IPVS_STATS_ATTR_CONNS] &&
+             attrs[IPVS_STATS_ATTR_INPKTS] &&
+             attrs[IPVS_STATS_ATTR_OUTPKTS] &&
+             attrs[IPVS_STATS_ATTR_INBYTES] &&
+             attrs[IPVS_STATS_ATTR_OUTBYTES] &&
+             attrs[IPVS_STATS_ATTR_CPS] &&
+             attrs[IPVS_STATS_ATTR_INPPS] &&
+             attrs[IPVS_STATS_ATTR_OUTPPS] &&
+             attrs[IPVS_STATS_ATTR_INBPS] &&
+             attrs[IPVS_STATS_ATTR_OUTBPS]))
+               return -1;
+
+       stats->conns = nla_get_u32(attrs[IPVS_STATS_ATTR_CONNS]);
+       stats->inpkts = nla_get_u32(attrs[IPVS_STATS_ATTR_INPKTS]);
+       stats->outpkts = nla_get_u32(attrs[IPVS_STATS_ATTR_OUTPKTS]);
+       stats->inbytes = nla_get_u64(attrs[IPVS_STATS_ATTR_INBYTES]);
+       stats->outbytes = nla_get_u64(attrs[IPVS_STATS_ATTR_OUTBYTES]);
+       stats->cps = nla_get_u32(attrs[IPVS_STATS_ATTR_CPS]);
+       stats->inpps = nla_get_u32(attrs[IPVS_STATS_ATTR_INPPS]);
+       stats->outpps = nla_get_u32(attrs[IPVS_STATS_ATTR_OUTPPS]);
+       stats->inbps = nla_get_u32(attrs[IPVS_STATS_ATTR_INBPS]);
+       stats->outbps = nla_get_u32(attrs[IPVS_STATS_ATTR_OUTBPS]);
+
+       return 0;
 
-       pid = fork();
-       if (pid == 0) {
-               _ipvs_start_daemon(dm);
-               exit(0);
-       } else if (pid > 0)
-               return 0;
-       return 1;
 }
 
-int ipvs_stop_daemon(ipvs_daemon_t *dm)
+static int ipvs_services_parse_cb(struct nl_msg *msg, void *arg)
 {
-       pid_t pid;
+       struct nlmsghdr *nlh = nlmsg_hdr(msg);
+       struct nlattr *attrs[IPVS_CMD_ATTR_MAX + 1];
+       struct nlattr *svc_attrs[IPVS_SVC_ATTR_MAX + 1];
+       struct ip_vs_get_services **getp = (struct ip_vs_get_services **)arg;
+       struct ip_vs_get_services *get = (struct ip_vs_get_services *)*getp;
+       struct ip_vs_flags flags;
+       int i = get->num_services;
+
+       if (genlmsg_parse(nlh, 0, attrs, IPVS_CMD_ATTR_MAX, ipvs_cmd_policy) != 0)
+               return -1;
+       
+       if (!attrs[IPVS_CMD_ATTR_SERVICE])
+               return -1;
 
-       pid = fork();
-       if (pid == 0) {
-               _ipvs_stop_daemon(dm);
-               exit(0);
-       } else if (pid > 0)
-               return 0;
-       return 1;
+       if (nla_parse_nested(svc_attrs, IPVS_SVC_ATTR_MAX, attrs[IPVS_CMD_ATTR_SERVICE], ipvs_service_policy))
+               return -1;
+
+       memset(&(get->entrytable[i]), 0, sizeof(get->entrytable[i]));
+
+       if (!(svc_attrs[IPVS_SVC_ATTR_AF] &&
+             (svc_attrs[IPVS_SVC_ATTR_FWMARK] ||
+              (svc_attrs[IPVS_SVC_ATTR_PROTOCOL] &&
+               svc_attrs[IPVS_SVC_ATTR_ADDR] &&
+               svc_attrs[IPVS_SVC_ATTR_PORT])) &&
+             svc_attrs[IPVS_SVC_ATTR_SCHED_NAME] &&
+             svc_attrs[IPVS_SVC_ATTR_NETMASK] &&
+             svc_attrs[IPVS_SVC_ATTR_TIMEOUT] &&
+             svc_attrs[IPVS_SVC_ATTR_FLAGS]))
+               return -1;
+
+       get->entrytable[i].af = nla_get_u16(svc_attrs[IPVS_SVC_ATTR_AF]);
+
+       if (svc_attrs[IPVS_SVC_ATTR_FWMARK])
+               get->entrytable[i].fwmark = nla_get_u32(svc_attrs[IPVS_SVC_ATTR_FWMARK]);
+       else {
+               get->entrytable[i].protocol = nla_get_u16(svc_attrs[IPVS_SVC_ATTR_PROTOCOL]);
+               memcpy(&(get->entrytable[i].addr), nla_data(svc_attrs[IPVS_SVC_ATTR_ADDR]),
+                      sizeof(get->entrytable[i].addr));
+               get->entrytable[i].port = nla_get_u16(svc_attrs[IPVS_SVC_ATTR_PORT]);
+       }
+
+       strncpy(get->entrytable[i].sched_name,
+               nla_get_string(svc_attrs[IPVS_SVC_ATTR_SCHED_NAME]),
+               IP_VS_SCHEDNAME_MAXLEN);
+
+       get->entrytable[i].netmask = nla_get_u32(svc_attrs[IPVS_SVC_ATTR_NETMASK]);
+       get->entrytable[i].timeout = nla_get_u32(svc_attrs[IPVS_SVC_ATTR_TIMEOUT]);
+       nla_memcpy(&flags, svc_attrs[IPVS_SVC_ATTR_FLAGS], sizeof(flags));
+       get->entrytable[i].flags = flags.flags & flags.mask;
+
+       if (ipvs_parse_stats(&(get->entrytable[i].stats),
+                            svc_attrs[IPVS_SVC_ATTR_STATS]) != 0)
+               return -1;
+
+       get->entrytable[i].num_dests = 0;
+       
+       i++;
+
+       get->num_services = i;
+       get = realloc(get, sizeof(*get)
+             + sizeof(ipvs_service_entry_t) * (get->num_services + 1));
+       *getp = get;
+       return 0;
 }
+#endif
 
 struct ip_vs_get_services *ipvs_get_services(void)
 {
        struct ip_vs_get_services *get;
+       struct ip_vs_get_services_kern *getk;
        socklen_t len;
+       int i;
+
+#ifdef LIBIPVS_USE_NL
+       if (try_nl) {
+               struct nl_msg *msg;
+               len = sizeof(*get) +
+                       sizeof(ipvs_service_entry_t);
+               if (!(get = malloc(len)))
+                       return NULL;
+               get->num_services = 0;
+
+               msg = ipvs_nl_message(IPVS_CMD_GET_SERVICE, NLM_F_DUMP);
+               if (msg && (ipvs_nl_send_message(msg, ipvs_services_parse_cb, &get) == 0))
+                       return get;
+
+               free(get);
+               return NULL;
+       }
+#endif
 
        len = sizeof(*get) +
-               sizeof(ipvs_service_entry_t)*ipvs_info.num_services;
+               sizeof(ipvs_service_entry_t) * ipvs_info.num_services;
        if (!(get = malloc(len)))
                return NULL;
+       len = sizeof(*getk) +
+               sizeof(struct ip_vs_service_entry_kern) * ipvs_info.num_services;
+       if (!(getk = malloc(len)))
+               return NULL;
 
        ipvs_func = ipvs_get_services;
-       get->num_services = ipvs_info.num_services;
+       getk->num_services = ipvs_info.num_services;
        if (getsockopt(sockfd, IPPROTO_IP,
-                      IP_VS_SO_GET_SERVICES, get, &len) < 0) {
+                      IP_VS_SO_GET_SERVICES, getk, &len) < 0) {
                free(get);
+               free(getk);
                return NULL;
        }
+       memcpy(get, getk, sizeof(struct ip_vs_get_services));
+       for (i = 0; i < getk->num_services; i++) {
+               memcpy(&get->entrytable[i], &getk->entrytable[i],
+                      sizeof(struct ip_vs_service_entry_kern));
+               get->entrytable[i].af = AF_INET;
+               get->entrytable[i].addr.ip = get->entrytable[i].__addr_v4;
+       }
+       free(getk);
        return get;
 }
 
@@ -210,17 +668,25 @@ typedef int (*qsort_cmp_t)(const void *, const void *);
 int
 ipvs_cmp_services(ipvs_service_entry_t *s1, ipvs_service_entry_t *s2)
 {
-       int r;
+       int r, i;
 
        r = s1->fwmark - s2->fwmark;
        if (r != 0)
                return r;
 
+       r = s1->af - s2->af;
+       if (r != 0)
+               return r;
+
        r = s1->protocol - s2->protocol;
        if (r != 0)
                return r;
 
-       r = ntohl(s1->addr) - ntohl(s2->addr);
+       if (s1->af == AF_INET6)
+               for (i = 0; !r && (i < 4); i++)
+                       r = ntohl(s1->addr.in6.s6_addr32[i]) - ntohl(s2->addr.in6.s6_addr32[i]);
+       else
+               r = ntohl(s1->addr.ip) - ntohl(s2->addr.ip);
        if (r != 0)
                return r;
 
@@ -235,38 +701,169 @@ ipvs_sort_services(struct ip_vs_get_services *s, ipvs_service_cmp_t f)
              sizeof(ipvs_service_entry_t), (qsort_cmp_t)f);
 }
 
+#ifdef LIBIPVS_USE_NL
+static int ipvs_dests_parse_cb(struct nl_msg *msg, void *arg)
+{
+       struct nlmsghdr *nlh = nlmsg_hdr(msg);
+       struct nlattr *attrs[IPVS_DEST_ATTR_MAX + 1];
+       struct nlattr *dest_attrs[IPVS_SVC_ATTR_MAX + 1];
+       struct ip_vs_get_dests **dp = (struct ip_vs_get_dests **)arg;
+       struct ip_vs_get_dests *d = (struct ip_vs_get_dests *)*dp;
+       int i = d->num_dests;
+
+       if (genlmsg_parse(nlh, 0, attrs, IPVS_CMD_ATTR_MAX, ipvs_cmd_policy) != 0)
+               return -1;
+       
+       if (!attrs[IPVS_CMD_ATTR_DEST])
+               return -1;
+
+       if (nla_parse_nested(dest_attrs, IPVS_DEST_ATTR_MAX, attrs[IPVS_CMD_ATTR_DEST], ipvs_dest_policy))
+               return -1;
+
+       memset(&(d->entrytable[i]), 0, sizeof(d->entrytable[i]));
+
+       if (!(dest_attrs[IPVS_DEST_ATTR_ADDR] &&
+             dest_attrs[IPVS_DEST_ATTR_PORT] &&
+             dest_attrs[IPVS_DEST_ATTR_FWD_METHOD] &&
+             dest_attrs[IPVS_DEST_ATTR_WEIGHT] &&
+             dest_attrs[IPVS_DEST_ATTR_U_THRESH] &&
+             dest_attrs[IPVS_DEST_ATTR_L_THRESH] &&
+             dest_attrs[IPVS_DEST_ATTR_ACTIVE_CONNS] &&
+             dest_attrs[IPVS_DEST_ATTR_INACT_CONNS] &&
+             dest_attrs[IPVS_DEST_ATTR_PERSIST_CONNS]))
+               return -1;
+
+       memcpy(&(d->entrytable[i].addr),
+              nla_data(dest_attrs[IPVS_DEST_ATTR_ADDR]),
+              sizeof(d->entrytable[i].addr));
+       d->entrytable[i].port = nla_get_u16(dest_attrs[IPVS_DEST_ATTR_PORT]);
+       d->entrytable[i].conn_flags = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_FWD_METHOD]);
+       d->entrytable[i].weight = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_WEIGHT]);
+       d->entrytable[i].u_threshold = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_U_THRESH]);
+       d->entrytable[i].l_threshold = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_L_THRESH]);
+       d->entrytable[i].activeconns = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_ACTIVE_CONNS]);
+       d->entrytable[i].inactconns = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_INACT_CONNS]);
+       d->entrytable[i].activeconns = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_PERSIST_CONNS]);
+       d->entrytable[i].af = d->af;
+
+       if (ipvs_parse_stats(&(d->entrytable[i].stats),
+                            dest_attrs[IPVS_DEST_ATTR_STATS]) != 0)
+               return -1;
+
+       i++;
+
+       d->num_dests = i;
+       d = realloc(d, sizeof(*d) + sizeof(ipvs_dest_entry_t) * (d->num_dests + 1));
+       *dp = d;
+       return 0;
+}
+#endif
 
 struct ip_vs_get_dests *ipvs_get_dests(ipvs_service_entry_t *svc)
 {
        struct ip_vs_get_dests *d;
+       struct ip_vs_get_dests_kern *dk;
        socklen_t len;
+       int i;
 
-       len = sizeof(*d) + sizeof(ipvs_dest_entry_t)*svc->num_dests;
+       len = sizeof(*d) + sizeof(ipvs_dest_entry_t) * svc->num_dests;
        if (!(d = malloc(len)))
                return NULL;
 
        ipvs_func = ipvs_get_dests;
 
-       d->fwmark = svc->fwmark;
-       d->protocol = svc->protocol;
-       d->addr = svc->addr;
-       d->port = svc->port;
-       d->num_dests = svc->num_dests;
+#ifdef LIBIPVS_USE_NL
+       if (try_nl) {
+               struct nl_msg *msg;
+               struct nlattr *nl_service;
+               if (svc->num_dests == 0)
+                       d = realloc(d,sizeof(*d) + sizeof(ipvs_dest_entry_t));
+               d->fwmark = svc->fwmark;
+               d->protocol = svc->protocol;
+               d->addr = svc->addr;
+               d->port = svc->port;
+               d->num_dests = svc->num_dests;
+               d->af = svc->af;
+
+               msg = ipvs_nl_message(IPVS_CMD_GET_DEST, NLM_F_DUMP);
+               if (!msg)
+                       goto ipvs_nl_dest_failure;
+
+               nl_service = nla_nest_start(msg, IPVS_CMD_ATTR_SERVICE);
+               if (!nl_service)
+                       goto nla_put_failure;
+
+               NLA_PUT_U16(msg, IPVS_SVC_ATTR_AF, svc->af);
+
+               if (svc->fwmark) {
+                       NLA_PUT_U32(msg, IPVS_SVC_ATTR_FWMARK, svc->fwmark);
+               } else {
+                       NLA_PUT_U16(msg, IPVS_SVC_ATTR_PROTOCOL, svc->protocol);
+                       NLA_PUT(msg, IPVS_SVC_ATTR_ADDR, sizeof(svc->addr),
+                               &svc->addr);
+                       NLA_PUT_U16(msg, IPVS_SVC_ATTR_PORT, svc->port);
+               }
+
+               nla_nest_end(msg, nl_service);
+               if (ipvs_nl_send_message(msg, ipvs_dests_parse_cb, &d))
+                       goto ipvs_nl_dest_failure;
+
+               return d;
+
+nla_put_failure:
+               nlmsg_free(msg);
+ipvs_nl_dest_failure:
+               free(d);
+               return NULL;
+       }
+#endif
+
+       if (svc->af != AF_INET) {
+         errno = EAFNOSUPPORT;
+         free(d);
+         return NULL;
+       }
+
+       len = sizeof(*dk) + sizeof(struct ip_vs_dest_entry_kern) * svc->num_dests;
+       if (!(dk = malloc(len)))
+               return NULL;
+
+       dk->fwmark = svc->fwmark;
+       dk->protocol = svc->protocol;
+       dk->addr = svc->addr.ip;
+       dk->port = svc->port;
+       dk->num_dests = svc->num_dests;
 
        if (getsockopt(sockfd, IPPROTO_IP,
-                      IP_VS_SO_GET_DESTS, d, &len) < 0) {
+                      IP_VS_SO_GET_DESTS, dk, &len) < 0) {
                free(d);
+               free(dk);
                return NULL;
        }
+       memcpy(d, dk, sizeof(struct ip_vs_get_dests_kern));
+       d->af = AF_INET;
+       d->addr.ip = d->__addr_v4;
+       for (i = 0; i < dk->num_dests; i++) {
+               memcpy(&d->entrytable[i], &dk->entrytable[i],
+                      sizeof(struct ip_vs_dest_entry_kern));
+               d->entrytable[i].af = AF_INET;
+               d->entrytable[i].addr.ip = d->entrytable[i].__addr_v4;
+       }
+       free(dk);
        return d;
 }
 
 
 int ipvs_cmp_dests(ipvs_dest_entry_t *d1, ipvs_dest_entry_t *d2)
 {
-       int r;
-
-       r = ntohl(d1->addr) - ntohl(d2->addr);
+       int r = 0, i;
+
+       if (d1->af == AF_INET6)
+               for (i = 0; !r && (i < 4); i++)
+                       r = ntohl(d1->addr.in6.s6_addr32[i]) -
+                           ntohl(d2->addr.in6.s6_addr32[i]);
+       else
+               r = ntohl(d1->addr.ip) - ntohl(d2->addr.ip);
        if (r != 0)
                return r;
 
@@ -282,7 +879,7 @@ void ipvs_sort_dests(struct ip_vs_get_dests *d, ipvs_dest_cmp_t f)
 
 
 ipvs_service_entry_t *
-ipvs_get_service(__u32 fwmark, __u16 protocol, __u32 addr, __u16 port)
+ipvs_get_service(__u32 fwmark, __u16 af, __u16 protocol, union nf_inet_addr addr, __u16 port)
 {
        ipvs_service_entry_t *svc;
        socklen_t len;
@@ -294,17 +891,78 @@ ipvs_get_service(__u32 fwmark, __u16 protocol, __u32 addr, __u16 port)
        ipvs_func = ipvs_get_service;
 
        svc->fwmark = fwmark;
+       svc->af = af;
        svc->protocol = protocol;
        svc->addr = addr;
        svc->port = port;
+#ifdef LIBIPVS_USE_NL
+       if (try_nl) {
+               struct ip_vs_get_services *get;
+               struct nl_msg *msg;
+               ipvs_service_t tsvc;
+               tsvc.fwmark = fwmark;
+               tsvc.af = af;
+               tsvc.protocol= protocol;
+               tsvc.addr = addr;
+               tsvc.port = port;
+
+               if (!(get = malloc(sizeof(*get) + sizeof(ipvs_service_entry_t))))
+                       goto ipvs_get_service_err2;
+
+               get->num_services = 0;
+
+               msg = ipvs_nl_message(IPVS_CMD_GET_SERVICE, 0);
+               if (!msg) goto ipvs_get_service_err;
+               if (ipvs_nl_fill_service_attr(msg, &tsvc))
+                       goto nla_put_failure;
+               if (ipvs_nl_send_message(msg, ipvs_services_parse_cb, &get))
+                       goto ipvs_get_service_err;
+
+               memcpy(svc, &(get->entrytable[0]), sizeof(*svc));
+               free(get);
+               return svc;
+
+nla_put_failure:
+               nlmsg_free(msg);
+ipvs_get_service_err:
+               free(get);
+ipvs_get_service_err2:
+               free(svc);
+               return NULL;
+       }
+#endif
+
+       CHECK_IPV4(svc, NULL);
        if (getsockopt(sockfd, IPPROTO_IP, IP_VS_SO_GET_SERVICE,
                       (char *)svc, &len)) {
                free(svc);
                return NULL;
        }
+       svc->af = AF_INET;
+       svc->addr.ip = svc->__addr_v4;
        return svc;
 }
 
+#ifdef LIBIPVS_USE_NL
+static int ipvs_timeout_parse_cb(struct nl_msg *msg, void *arg)
+{
+       struct nlmsghdr *nlh = nlmsg_hdr(msg);
+       struct nlattr *attrs[IPVS_CMD_ATTR_MAX + 1];
+       ipvs_timeout_t *u = (ipvs_timeout_t *)arg;
+
+       if (genlmsg_parse(nlh, 0, attrs, IPVS_CMD_ATTR_MAX, ipvs_cmd_policy) != 0)
+               return -1;
+       
+       if (attrs[IPVS_CMD_ATTR_TIMEOUT_TCP])
+               u->tcp_timeout = nla_get_u32(attrs[IPVS_CMD_ATTR_TIMEOUT_TCP]);
+       if (attrs[IPVS_CMD_ATTR_TIMEOUT_TCP_FIN])
+               u->tcp_fin_timeout = nla_get_u32(attrs[IPVS_CMD_ATTR_TIMEOUT_TCP_FIN]);
+       if (attrs[IPVS_CMD_ATTR_TIMEOUT_UDP])
+               u->udp_timeout = nla_get_u32(attrs[IPVS_CMD_ATTR_TIMEOUT_UDP]);
+       
+       return NL_OK;
+}
+#endif
 
 ipvs_timeout_t *ipvs_get_timeout(void)
 {
@@ -316,6 +974,18 @@ ipvs_timeout_t *ipvs_get_timeout(void)
                return NULL;
 
        ipvs_func = ipvs_get_timeout;
+#ifdef LIBIPVS_USE_NL
+       if (try_nl) {
+               struct nl_msg *msg;
+               memset(u, 0, sizeof(*u));
+               msg = ipvs_nl_message(IPVS_CMD_GET_TIMEOUT, 0);
+               if (msg && (ipvs_nl_send_message(msg, ipvs_timeout_parse_cb, u) == 0))
+                       return u;
+
+               free(u);
+               return NULL;
+       }
+#endif
        if (getsockopt(sockfd, IPPROTO_IP, IP_VS_SO_GET_TIMEOUT,
                       (char *)u, &len)) {
                free(u);
@@ -324,6 +994,40 @@ ipvs_timeout_t *ipvs_get_timeout(void)
        return u;
 }
 
+#ifdef LIBIPVS_USE_NL
+static int ipvs_daemon_parse_cb(struct nl_msg *msg, void *arg)
+{
+       struct nlmsghdr *nlh = nlmsg_hdr(msg);
+       struct nlattr *attrs[IPVS_CMD_ATTR_MAX + 1];
+       struct nlattr *daemon_attrs[IPVS_DAEMON_ATTR_MAX + 1];
+       ipvs_daemon_t *u = (ipvs_daemon_t *)arg;
+       int i = 0;
+
+       /* We may get two daemons.  If we've already got one, this is the second */
+       if (u[0].state)
+               i = 1;
+
+       if (genlmsg_parse(nlh, 0, attrs, IPVS_CMD_ATTR_MAX, ipvs_cmd_policy) != 0)
+               return -1;
+       
+       if (nla_parse_nested(daemon_attrs, IPVS_DAEMON_ATTR_MAX,
+                            attrs[IPVS_CMD_ATTR_DAEMON], ipvs_daemon_policy))
+               return -1;
+       
+       if (!(daemon_attrs[IPVS_DAEMON_ATTR_STATE] &&
+             daemon_attrs[IPVS_DAEMON_ATTR_MCAST_IFN] &&
+             daemon_attrs[IPVS_DAEMON_ATTR_SYNC_ID]))
+               return -1;
+
+       u[i].state = nla_get_u32(daemon_attrs[IPVS_DAEMON_ATTR_STATE]);
+       strncpy(u[i].mcast_ifn,
+               nla_get_string(daemon_attrs[IPVS_DAEMON_ATTR_MCAST_IFN]),
+               IP_VS_IFNAME_MAXLEN);
+       u[i].syncid = nla_get_u32(daemon_attrs[IPVS_DAEMON_ATTR_SYNC_ID]);
+       
+       return NL_OK;
+}
+#endif
 
 ipvs_daemon_t *ipvs_get_daemon(void)
 {
@@ -337,8 +1041,19 @@ ipvs_daemon_t *ipvs_get_daemon(void)
                return NULL;
 
        ipvs_func = ipvs_get_daemon;
-       if (getsockopt(sockfd, IPPROTO_IP,
-                      IP_VS_SO_GET_DAEMON, (char *)u, &len)) {
+#ifdef LIBIPVS_USE_NL
+       if (try_nl) {
+               struct nl_msg *msg;
+               memset(u, 0, len);
+               msg = ipvs_nl_message(IPVS_CMD_GET_DAEMON, NLM_F_DUMP);
+               if (msg && (ipvs_nl_send_message(msg, ipvs_daemon_parse_cb, u) == 0))
+                       return u;
+
+               free(u);
+               return NULL;
+       }
+#endif
+       if (getsockopt(sockfd, IPPROTO_IP, IP_VS_SO_GET_DAEMON, (char *)u, &len)) {
                free(u);
                return NULL;
        }
@@ -348,6 +1063,11 @@ ipvs_daemon_t *ipvs_get_daemon(void)
 
 void ipvs_close(void)
 {
+#ifdef LIBIPVS_USE_NL
+       if (try_nl) {
+               return;
+       }
+#endif
        close(sockfd);
 }
 
@@ -360,10 +1080,6 @@ const char *ipvs_strerror(int err)
                int err;
                const char *message;
        } table [] = {
-               { 0, EPERM, "Permission denied (you must be root)" },
-               { 0, EINVAL, "Module is wrong version" },
-               { 0, ENOPROTOOPT, "Protocol not available" },
-               { 0, ENOMEM, "Memory allocation problem" },
                { ipvs_add_service, EEXIST, "Service already exists" },
                { ipvs_add_service, ENOENT, "Scheduler not found" },
                { ipvs_update_service, ESRCH, "No such service" },
@@ -381,6 +1097,13 @@ const char *ipvs_strerror(int err)
                { ipvs_get_services, ESRCH, "No such service" },
                { ipvs_get_dests, ESRCH, "No such service" },
                { ipvs_get_service, ESRCH, "No such service" },
+               { 0, EPERM, "Permission denied (you must be root)" },
+               { 0, EINVAL, "Invalid operation.  Possibly wrong module version, address not unicast, ..." },
+               { 0, ENOPROTOOPT, "Protocol not available" },
+               { 0, ENOMEM, "Memory allocation problem" },
+               { 0, EOPNOTSUPP, "Operation not supported with IPv6" },
+               { 0, EAFNOSUPPORT, "Operation not supported with specified address family" },
+               { 0, EMSGSIZE, "Module is wrong version" },
        };
 
        for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) {
index 47182da..bd5852e 100644 (file)
@@ -10,8 +10,6 @@
 #ifndef _LIBIPVS_H
 #define _LIBIPVS_H
 
-#include <net/ip_vs.h>
-
 #define MINIMUM_IPVS_VERSION_MAJOR      1
 #define MINIMUM_IPVS_VERSION_MINOR      1
 #define MINIMUM_IPVS_VERSION_PATCH      4
@@ -40,7 +38,6 @@ typedef struct ip_vs_daemon_user      ipvs_daemon_t;
 typedef struct ip_vs_service_entry     ipvs_service_entry_t;
 typedef struct ip_vs_dest_entry                ipvs_dest_entry_t;
 
-
 /* ipvs info variable */
 extern struct ip_vs_getinfo ipvs_info;
 
@@ -86,6 +83,7 @@ extern int ipvs_start_daemon(ipvs_daemon_t *dm);
 /* stop a connection synchronizaiton daemon (master/backup) */
 extern int ipvs_stop_daemon(ipvs_daemon_t *dm);
 
+
 /* get all the ipvs services */
 extern struct ip_vs_get_services *ipvs_get_services(void);
 
@@ -108,10 +106,6 @@ extern int ipvs_cmp_dests(ipvs_dest_entry_t *d1,
 extern void ipvs_sort_dests(struct ip_vs_get_dests *d,
                            ipvs_dest_cmp_t f);
 
-/* get an ipvs service entry */
-extern ipvs_service_entry_t *
-ipvs_get_service(__u32 fwmark, __u16 protocol, __u32 addr, __u16 port);
-
 /* get ipvs timeout */
 extern ipvs_timeout_t *ipvs_get_timeout(void);
 
index 7f7a529..04b7c40 100644 (file)
@@ -536,17 +536,16 @@ netlink_if_address_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
        if (ifa->ifa_family == AF_INET) {
                if (!ifp->sin_addr.s_addr)
                        ifp->sin_addr = *(struct in_addr *) addr;
-#ifdef _WITH_LVS_
-               /* Refresh checkers state */
-               update_checker_activity(ifp->sin_addr.s_addr,
-                                       (h->nlmsg_type == RTM_NEWADDR) ? 1 : 0);
-#endif
-
        } else {
                if (!ifp->sin6_addr.s6_addr16[0] && ifa->ifa_scope == RT_SCOPE_LINK)
                        ifp->sin6_addr = *(struct in6_addr *) addr;
        }
 
+#ifdef _WITH_LVS_
+       /* Refresh checkers state */
+       update_checker_activity(ifa->ifa_family, addr,
+                               (h->nlmsg_type == RTM_NEWADDR) ? 1 : 0);
+#endif
        return 0;
 }
 
index ecfaffb..0ffcae5 100644 (file)
@@ -159,6 +159,110 @@ inet_stor(char *addr)
        return range;
 }
 
+/* IP string to sockaddr_storage */
+int
+inet_stosockaddr(char *ip, char *port, struct sockaddr_storage *addr)
+{
+       void *addr_ip;
+       char *cp = ip;
+
+       addr->ss_family = (strchr(ip, ':')) ? AF_INET6 : AF_INET;
+
+       /* remove range and mask stuff */
+       if (strstr(ip, "-")) {
+               while (*cp != '-' && *cp != '\0')
+                       cp++;
+               if (*cp == '-')
+                       *cp = 0;
+       } else if (strstr(ip, "/")) {
+               while (*cp != '/' && *cp != '\0')
+                       cp++;
+               if (*cp == '/')
+                       *cp = 0;
+       }
+
+       if (addr->ss_family == AF_INET6) {
+               struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr;
+               if (port)
+                       addr6->sin6_port = htons(atoi(port));
+               addr_ip = &addr6->sin6_addr;
+       } else {
+               struct sockaddr_in *addr4 = (struct sockaddr_in *) addr;
+               if (port)
+                       addr4->sin_port = htons(atoi(port));
+               addr_ip = &addr4->sin_addr;
+       }
+
+       if (!inet_pton(addr->ss_family, ip, addr_ip))
+               return -1;
+
+       return 0;
+}
+
+/* IP network to string representation */
+char *
+inet_sockaddrtos2(struct sockaddr_storage *addr, char *addr_str)
+{
+       void *addr_ip;
+
+       if (addr->ss_family == AF_INET6) {
+               struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr;
+               addr_ip = &addr6->sin6_addr;
+       } else {
+               struct sockaddr_in *addr4 = (struct sockaddr_in *) addr;
+               addr_ip = &addr4->sin_addr;
+       }
+
+       if (!inet_ntop(addr->ss_family, addr_ip, addr_str, INET6_ADDRSTRLEN))
+               return NULL;
+
+       return addr_str;
+}
+
+char *
+inet_sockaddrtos(struct sockaddr_storage *addr)
+{
+       static char addr_str[INET6_ADDRSTRLEN];
+       inet_sockaddrtos2(addr, addr_str);
+       return addr_str;
+}
+
+uint16_t
+inet_sockaddrport(struct sockaddr_storage *addr)
+{
+       uint16_t port;
+
+       if (addr->ss_family == AF_INET6) {
+               struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr;
+               port = addr6->sin6_port;
+       } else {
+               struct sockaddr_in *addr4 = (struct sockaddr_in *) addr;
+               port = addr4->sin_port;
+       }
+       
+       return port;
+}
+
+uint32_t
+inet_sockaddrip4(struct sockaddr_storage *addr)
+{
+       if (addr->ss_family != AF_INET)
+               return -1;
+       
+       return ((struct sockaddr_in *) addr)->sin_addr.s_addr;
+}
+
+int
+inet_sockaddrip6(struct sockaddr_storage *addr, struct in6_addr *ip6)
+{
+       if (addr->ss_family != AF_INET6)
+               return -1;
+       
+       *ip6 = ((struct sockaddr_in6 *) addr)->sin6_addr;
+       return 0;
+}
+
+
 /*
  * IP string to network representation
  * Highly inspired from Paul Vixie code.
index f173273..66d3a31 100644 (file)
 extern int debug;
 
 /* Prototypes defs */
-extern void dump_buffer(char *buff, int count);
-extern u_short in_csum(u_short * addr, int len, u_short csum);
-extern char *inet_ntop2(uint32_t ip);
-extern char *inet_ntoa2(uint32_t ip, char *buf);
-extern uint8_t inet_stom(char *addr);
-extern uint8_t inet_stor(char *addr);
-extern int inet_ston(const char *addr, uint32_t *dst);
-uint32_t inet_broadcast(uint32_t network, uint32_t netmask);
-uint32_t inet_cidrtomask(uint8_t cidr);
+extern void dump_buffer(char *, int);
+extern u_short in_csum(u_short *, int, u_short);
+extern char *inet_ntop2(uint32_t);
+extern char *inet_ntoa2(uint32_t, char *);
+extern uint8_t inet_stom(char *);
+extern uint8_t inet_stor(char *);
+extern int inet_stosockaddr(char *, char *, struct sockaddr_storage *);
+extern char *inet_sockaddrtos(struct sockaddr_storage *);
+extern char *inet_sockaddrtos2(struct sockaddr_storage *, char *);
+extern uint16_t inet_sockaddrport(struct sockaddr_storage *);
+extern uint32_t inet_sockaddrip4(struct sockaddr_storage *);
+extern int inet_sockaddrip6(struct sockaddr_storage *, struct in6_addr *);
+extern int inet_ston(const char *, uint32_t *);
+uint32_t inet_broadcast(uint32_t, uint32_t);
+uint32_t inet_cidrtomask(uint8_t);
 extern char *get_local_name(void);
 
 #endif