]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] implement SMTP health checks
authorWilly Tarreau <w@1wt.eu>
Tue, 8 May 2007 21:50:35 +0000 (23:50 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 May 2007 21:50:35 +0000 (23:50 +0200)
Peter van Dijk contributed this patch which implements the "smtpchk"
option, which is to SMTP what "httpchk" is to HTTP. By default, it sends
"HELO localhost" to the servers, and waits for the 250 message, but it
can also send a specific request.

doc/haproxy-en.txt
doc/haproxy-fr.txt
include/common/defaults.h
include/types/backend.h
src/cfgparse.c
src/checks.c

index 76d54c463bb0fc43d80aa1dd4c49ec9efe18dfe9..1341aea53951811937bd8dccd8b4134f3935c196 100644 (file)
@@ -1034,6 +1034,13 @@ the response is considered as valid. Note that Apache does not generate a log
 when it receives only an HELLO message, which makes this type of message
 perfectly suit this need.
 
+Version 1.3.10 introduced the SMTP health check. By default, it sends
+"HELO localhost" to the servers, and waits for the 250 message. Note that it
+can also send a specific request :
+
+  - option smtpchk                         -> sends "HELO localhost"
+  - option smtpchk EHLO mail.mydomain.com  -> sends this ESMTP greeting
+
 See examples below.
 
 Since version 1.1.17, it is possible to specify backup servers. These servers
index 8e83eab093fb7cd07db7d04f101237ef9b639d67..795b67b3c89e8d2f24a5f849d571ac7a325bade2 100644 (file)
@@ -1044,6 +1044,14 @@ r
 lorsqu'il reçoit des messages HELLO, ce qui en fait un type de message
 parfaitement adapté à ce besoin.
 
+La version 1.3.10 est accompagnée d'un nouveau test d'état pour le SMTP. Par
+défaut, il consiste à envoyer "HELO localhost" aux serveurs, et à attendre le
+message "250" en retour. Notez qu'il peut aussi envoyer une requête plus
+spécifique :
+
+  - option smtpchk                         -> envoie "HELO localhost"
+  - option smtpchk EHLO mail.mydomain.com  -> envoie ce message ESMTP
+
 Voir les exemples ci-après.        
 
 Depuis la version 1.1.17, il est possible de définir des serveurs de secours,
index c99aafe4feb65e4278585d270af81624b18f00be..cfe60e8f9cc24794aa4f284bcac299c489cf8c16 100644 (file)
@@ -92,6 +92,7 @@
 #define DEF_FALLTIME    3
 #define DEF_RISETIME    2
 #define DEF_CHECK_REQ   "OPTIONS / HTTP/1.0\r\n\r\n"
+#define DEF_SMTP_CHECK_REQ   "HELO localhost\r\n"
 
 /* Default connections limit.
  *
index e2d4efc6f2ec44f3374b3d2159c1c3b11dd38ea6..57a8cb053ab0787a993dd7b1a86de290e8ea126f 100644 (file)
@@ -59,6 +59,7 @@
 #define        PR_O_TCPSPLICE  0x08000000      /* delegate data transfer to linux kernel's tcp_splice */
 #define PR_O_BALANCE_UH 0x10000000      /* balance on URI hash */
 #define PR_O_BALANCE    (PR_O_BALANCE_RR | PR_O_BALANCE_SH | PR_O_BALANCE_UH)
+#define PR_O_SMTP_CHK   0x20000000      /* use SMTP EHLO check for server health - pvandijk@vision6.com.au */
 
 
 #endif /* _TYPES_BACKEND_H */
index 41d706611865085e51d6dbf6eb66c5958d6b036a..b2e76b310f783e4582687083aa1021428c3b47e5 100644 (file)
@@ -1029,13 +1029,14 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
                        if (curproxy->check_req != NULL) {
                                free(curproxy->check_req);
                        }
-                       curproxy->options |= PR_O_HTTP_CHK;
                        curproxy->options &= ~PR_O_SSL3_CHK;
+                       curproxy->options &= ~PR_O_SMTP_CHK;
+                       curproxy->options |= PR_O_HTTP_CHK;
                        if (!*args[2]) { /* no argument */
                                curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
                                curproxy->check_len = strlen(DEF_CHECK_REQ);
                        } else if (!*args[3]) { /* one argument : URI */
-                               int reqlen = strlen(args[2]) + strlen("OPTIONS / HTTP/1.0\r\n\r\n");
+                               int reqlen = strlen(args[2]) + strlen("OPTIONS  HTTP/1.0\r\n\r\n") + 1;
                                curproxy->check_req = (char *)malloc(reqlen);
                                curproxy->check_len = snprintf(curproxy->check_req, reqlen,
                                                               "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
@@ -1060,8 +1061,35 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
                                free(curproxy->check_req);
                        }
                        curproxy->options &= ~PR_O_HTTP_CHK;
+                       curproxy->options &= ~PR_O_SMTP_CHK;
                        curproxy->options |= PR_O_SSL3_CHK;
                }
+               else if (!strcmp(args[1], "smtpchk")) {
+                       /* use SMTP request to check servers' health */
+                       if (curproxy->check_req != NULL) {
+                               free(curproxy->check_req);
+                       }
+                       curproxy->options &= ~PR_O_HTTP_CHK;
+                       curproxy->options &= ~PR_O_SSL3_CHK;
+                       curproxy->options |= PR_O_SMTP_CHK;
+
+                       if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
+                               curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
+                               curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
+                       } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
+                               if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
+                                       int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
+                                       curproxy->check_req = (char *)malloc(reqlen);
+                                       curproxy->check_len = snprintf(curproxy->check_req, reqlen,
+                                                                      "%s %s\r\n", args[2], args[3]); /* HELO hostname */
+                               } else {
+                                       /* this just hits the default for now, but you could potentially expand it to allow for other stuff
+                                          though, it's unlikely you'd want to send anything other than an EHLO or HELO */
+                                       curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
+                                       curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
+                               }
+                       }
+               }
                else if (!strcmp(args[1], "forwardfor")) {
                        /* insert x-forwarded-for field, but not for the
                         * IP address listed as an except.
index 14f0c8cc88a4a2e5b6e7b2cd732a0a57374b346c..ec56453a54f76ab75ba4976ac5af6b9ad50aec2e 100644 (file)
@@ -122,7 +122,8 @@ static int event_srv_chk_w(int fd)
        if (s->result != -1) {
                /* we don't want to mark 'UP' a server on which we detected an error earlier */
                if ((s->proxy->options & PR_O_HTTP_CHK) ||
-                   (s->proxy->options & PR_O_SSL3_CHK)) {
+                   (s->proxy->options & PR_O_SSL3_CHK) ||
+                   (s->proxy->options & PR_O_SMTP_CHK)) {
                        int ret;
                        /* we want to check if this host replies to HTTP or SSLv3 requests
                         * so we'll send the request, and won't wake the checker up now.
@@ -252,6 +253,10 @@ static int event_srv_chk_r(int fd)
                /* SSLv3 alert or handshake */
                result = 1;
        }
+       else if ((s->proxy->options & PR_O_SMTP_CHK) && (len >= 3) &&
+                  (reply[0] == '2')) /* 2xx (should be 250) */ {
+               result = 1;
+       }
 
        if (result == -1)
                fdtab[fd].state = FD_STERROR;