+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>:
ac_subst_vars='LTLIBOBJS
LIBOBJS
VRRP_SUPPORT
+USE_NL
IPVS_SUPPORT
VERSION_DATE
VERSION
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
+
{ $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 :
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"
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"
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"
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 ]----
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)
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"
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
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);
}
}
}
+/* 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)
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,
/* 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 */
#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"
* Copyright (C) 2001-2010 Alexandre Cassen, <acassen@freebox.fr>
*/
+#include <netdb.h>
#include "check_data.h"
#include "check_api.h"
#include "logger.h"
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)
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
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",
}
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);
} 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;
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 */
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)
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);
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);
/* 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);
}
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
* 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.
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) {
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"
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)) {
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);
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",
, 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);
/*
} 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;
}
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",
, 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);
/*
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;
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;
/* 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;
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",
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;
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);
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)) {
{
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);
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"
/* 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
" 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"
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;
* 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
}
/* 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,
/* 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 <=");
/* 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 <=");
}
} 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 <=");
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)
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));
}
/*
smtp_host *
smtp_alloc_host(void)
{
- checker *chk = LIST_TAIL_DATA(checkers_queue);
smtp_host *new;
/* Allocate the new host data structure */
* 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;
}
{
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 */
{
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 */
{
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 */
/* 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,
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);
* 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;
}
/* 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;
}
/* 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;
}
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;
}
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;
}
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;
}
/* 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;
}
*/
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 <=");
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);
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 */
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);
}
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
{
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.
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 <=");
} 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 <=");
checker *checker_obj = THREAD_ARG(thread_obj);
tcp_checker *tcp_check = CHECKER_ARG(checker_obj);
int fd;
- uint16_t addr_port;
int status;
/*
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,
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);
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)) {
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;
|| 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);
}
}
}
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 */
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 */
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);
#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
}
/* 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;
}
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;
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);
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)) {
/* 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 */
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;
/* 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;
}
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 ? */
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 */
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)) {
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;
ipvs_group_range_cmd(IP_VS_SO_SET_DEL, vsge);
else
ipvs_talk(IP_VS_SO_SET_DEL);
+
return IPVS_SUCCESS;
}
{
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)
* 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);
}
* 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;
}
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;
{
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;
}
}
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 */
}
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;
/* 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);
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);
}
}
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);
}
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
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;
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))
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;
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))
#include <syslog.h>
#include <unistd.h>
#include <pwd.h>
+#include <netdb.h>
#include "global_data.h"
#include "memory.h"
#include "list.h"
}
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;
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);
}
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);
* 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 */
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)
#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) {
}
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;
}
* 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);
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;
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;
{
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;
}
{
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;
}
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);
{
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,
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;
}
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 {
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;
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);
}
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;
}
} 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);
}
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;
}
} 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;
}
} 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;
}
} 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;
}
{
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;
}
} 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;
}
} 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;
}
{
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++;
{
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);
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);
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);
#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)
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
#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
/* 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_
/* 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;
/* 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;
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;
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 */
} 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;
/* 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 */
/* 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;
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;
#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
/* 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
#include "vrrp.h"
/* global defs */
+#define SMTP_PORT_STR "25"
#define SMTP_PORT 25
#define SMTP_BUFFER_LENGTH 512
#define SMTP_BUFFER_MAX 1024
-# 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
#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;
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);
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));
}
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));
}
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));
}
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;
}
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;
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;
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;
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)
{
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);
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)
{
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;
}
void ipvs_close(void)
{
+#ifdef LIBIPVS_USE_NL
+ if (try_nl) {
+ return;
+ }
+#endif
close(sockfd);
}
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" },
{ 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++) {
#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
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;
/* 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);
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);
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;
}
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.
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