pound/2.5/dynamic-backends.patch
changeset 18 7ce365612e43
child 19 e12b21f08628
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pound/2.5/dynamic-backends.patch	Wed May 11 16:08:37 2011 +0200
@@ -0,0 +1,246 @@
+diff -r badbd0960f5b config.c
+--- a/config.c	Mon May 09 11:00:36 2011 +0200
++++ b/config.c	Wed May 11 16:04:14 2011 +0200
+@@ -77,7 +77,7 @@
+ static regex_t  Service, ServiceName, URL, HeadRequire, HeadDeny, BackEnd, Emergency, Priority, HAport, HAportAddr;
+ static regex_t  Redirect, RedirectN, TimeOut, Session, Type, TTL, ID, DynScale;
+ static regex_t  ClientCert, AddHeader, Ciphers, CAlist, VerifyList, CRLlist, NoHTTPS11;
+-static regex_t  Grace, Include, ConnTO, IgnoreCase, HTTPS, HTTPSCert;
++static regex_t  Grace, Include, ConnTO, IgnoreCase, HTTPS, HTTPSCert, DynamicAddress, DynamicHAAddress;
+ 
+ static regmatch_t   matches[5];
+ 
+@@ -182,7 +182,7 @@
+     if((res = (BACKEND *)malloc(sizeof(BACKEND))) == NULL)
+         conf_err("BackEnd config: out of memory - aborted");
+     memset(res, 0, sizeof(BACKEND));
+-    res->be_type = 0;
++    res->be_type = res->dyn_addr = res->dyn_ha_addr = 0;
+     res->addr.ai_socktype = SOCK_STREAM;
+     res->to = is_emergency? 120: be_to;
+     res->conn_to = is_emergency? 120: be_connto;
+@@ -200,6 +200,9 @@
+             lin[strlen(lin) - 1] = '\0';
+         if(!regexec(&Address, lin, 4, matches, 0)) {
+             lin[matches[1].rm_eo] = '\0';
++            if((res->hostname = (char *)malloc(matches[1].rm_eo - matches[1].rm_so)) == NULL)
++                conf_err("out of memory");
++            memcpy(res->hostname, lin + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
+             if(get_host(lin + matches[1].rm_so, &res->addr)) {
+                 /* if we can't resolve it assume this is a UNIX domain socket */
+                 res->addr.ai_socktype = SOCK_STREAM;
+@@ -243,6 +246,7 @@
+             if(is_emergency)
+                 conf_err("HAport is not supported for Emergency back-ends");
+             res->ha_addr = res->addr;
++            res->ha_hostname = res->hostname;
+             if((res->ha_addr.ai_addr = (struct sockaddr *)malloc(res->addr.ai_addrlen)) == NULL)
+                 conf_err("out of memory");
+             memcpy(res->ha_addr.ai_addr, res->addr.ai_addr, res->addr.ai_addrlen);
+@@ -264,6 +268,9 @@
+             if(is_emergency)
+                 conf_err("HAportAddr is not supported for Emergency back-ends");
+             lin[matches[1].rm_eo] = '\0';
++            if((res->ha_hostname = (char *)malloc(matches[1].rm_eo - matches[1].rm_so)) == NULL)
++                conf_err("out of memory");
++            memcpy(res->ha_hostname, lin + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
+             if(get_host(lin + matches[1].rm_so, &res->ha_addr)) {
+                 /* if we can't resolve it assume this is a UNIX domain socket */
+                 res->addr.ai_socktype = SOCK_STREAM;
+@@ -313,6 +320,10 @@
+             SSL_CTX_set_session_id_context(res->ctx, (unsigned char *)lin, strlen(lin));
+             SSL_CTX_set_tmp_rsa_callback(res->ctx, RSA_tmp_callback);
+             SSL_CTX_set_tmp_dh_callback(res->ctx, DH_tmp_callback);
++        } else if(!regexec(&DynamicAddress, lin, 4, matches, 0)) {
++            res->dyn_addr = 1;
++        } else if(!regexec(&DynamicHAAddress, lin, 4, matches, 0)) {
++            res->dyn_ha_addr = 1;
+         } else if(!regexec(&End, lin, 4, matches, 0)) {
+             if(!has_addr)
+                 conf_err("BackEnd missing Address - aborted");
+@@ -1163,6 +1174,8 @@
+     || regcomp(&IgnoreCase, "^[ \t]*IgnoreCase[ \t]+([01])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
+     || regcomp(&HTTPS, "^[ \t]*HTTPS[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
+     || regcomp(&HTTPSCert, "^[ \t]*HTTPS[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
++    || regcomp(&DynamicAddress, "^[ \t]*DynamicAddress[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
++    || regcomp(&DynamicHAAddress, "^[ \t]*DynamicHAAddress[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
+     ) {
+         logmsg(LOG_ERR, "bad config Regex - aborted");
+         exit(1);
+diff -r badbd0960f5b debian/changelog
+--- a/debian/changelog	Mon May 09 11:00:36 2011 +0200
++++ b/debian/changelog	Wed May 11 16:04:14 2011 +0200
+@@ -1,3 +1,9 @@
++pound (2.5-1~bpo50+2) lenny-backports; urgency=low
++
++  * patched to deal with backend addresses on dynamic ips
++
++ -- Matthias Förste <foerste@schlittermann.de>  Wed, 11 May 2011 15:52:38 +0200
++
+ pound (2.5-1~bpo50+1) lenny-backports; urgency=low
+ 
+   * Rebuild for lenny-backports.
+diff -r badbd0960f5b http.c
+--- a/http.c	Mon May 09 11:00:36 2011 +0200
++++ b/http.c	Wed May 11 16:04:14 2011 +0200
+@@ -773,6 +773,13 @@
+                 pthread_exit(NULL);
+                 break;
+             }
++            if (backend->dyn_addr && upd_addr(backend->hostname, &backend->addr)) {
++                logmsg(LOG_WARNING, "(%lx) e503 backend: failed to resolve hostname '%s': %s", pthread_self(), backend->hostname, strerror(errno));
++                err_reply(cl, h503, lstn->err503);
++                free_headers(headers);
++                clean_all();
++                pthread_exit(NULL);
++            }
+             if((sock = socket(sock_proto, SOCK_STREAM, 0)) < 0) {
+                 str_be(buf, MAXBUF - 1, backend);
+                 logmsg(LOG_WARNING, "(%lx) e503 backend %s socket create: %s", pthread_self(), buf, strerror(errno));
+diff -r badbd0960f5b pound.8
+--- a/pound.8	Mon May 09 11:00:36 2011 +0200
++++ b/pound.8	Wed May 11 16:04:14 2011 +0200
+@@ -682,6 +682,22 @@
+ .B Pound
+ uses the same address as the back-end server, but you may use a separate address
+ if you wish. This directive applies only to non Unix-domain servers.
++\fBDynamicAddress\fR
++If this directive is present then the
++.I Address
++given for this
++.I Backend
++is considered a dynamic address. It is resolved whenever a connection attempt
++to that
++.I Address
++is made.
++\fBDynamicHAAddress\fR
++This is the same as
++.I DynamicAddress
++except that it applies to the address given in the
++.I HAPort
++directive if any.
++
+ .SH "Emergency"
+ The emergency server will be used once all existing back-ends are "dead".
+ All configuration directives enclosed between
+diff -r badbd0960f5b pound.h
+--- a/pound.h	Mon May 09 11:00:36 2011 +0200
++++ b/pound.h	Wed May 11 16:04:14 2011 +0200
+@@ -308,6 +308,10 @@
+     int                 alive;      /* false if the back-end is dead */
+     int                 resurrect;  /* this back-end is to be resurrected */
+     int                 disabled;   /* true if the back-end is disabled */
++    int                 dyn_addr;     /* true if the address of the backend may change over time (dynamic ip for example) */
++    char                *hostname;    /* in case of a dynamic address we need to keep the hostname too */
++    int                 dyn_ha_addr;  /* like dynaddr but for the ha addr */
++    char                *ha_hostname; /* in case of a dynamic ha address we need to keep the hostname too */
+     struct _backend     *next;
+ }   BACKEND;
+ 
+@@ -571,3 +575,6 @@
+  * listens to client requests and calls the appropriate functions
+  */
+ extern void *thr_control(void *);
++
++/* update address */
++int upd_addr(char *hostname, struct addrinfo *ai);
+diff -r badbd0960f5b svc.c
+--- a/svc.c	Mon May 09 11:00:36 2011 +0200
++++ b/svc.c	Wed May 11 16:04:14 2011 +0200
+@@ -904,6 +904,9 @@
+         default:
+             continue;
+         }
++        if (be->dyn_ha_addr && upd_addr(be->ha_hostname, &be->ha_addr)) {
++            logmsg(LOG_NOTICE, "failed to resolve hostname '%s': %s", be->ha_hostname, strerror(errno));
++        }
+         if(connect_nb(sock, &be->ha_addr, be->conn_to) != 0) {
+             kill_be(svc, be, BE_KILL);
+             str_be(buf, MAXBUF - 1, be);
+@@ -940,6 +943,9 @@
+         default:
+             continue;
+         }
++        if (be->dyn_ha_addr && upd_addr(be->ha_hostname, &be->ha_addr)) {
++            logmsg(LOG_NOTICE, "failed to resolve hostname '%s': %s", be->ha_hostname, strerror(errno));
++        }
+         if(connect_nb(sock, &be->ha_addr, be->conn_to) != 0) {
+             kill_be(svc, be, BE_KILL);
+             str_be(buf, MAXBUF - 1, be);
+@@ -975,6 +981,9 @@
+                 default:
+                     continue;
+                 }
++                if (be->dyn_addr && upd_addr(be->hostname, &be->addr)) {
++                    logmsg(LOG_NOTICE, "failed to resolve hostname '%s': %s", be->hostname, strerror(errno));
++                }
+                 addr = &be->addr;
+             } else {
+                 switch(be->ha_addr.ai_family) {
+@@ -993,6 +1002,9 @@
+                 default:
+                     continue;
+                 }
++                if (be->dyn_ha_addr && upd_addr(be->ha_hostname, &be->ha_addr)) {
++                    logmsg(LOG_NOTICE, "failed to resolve hostname '%s': %s", be->ha_hostname, strerror(errno));
++                }
+                 addr = &be->ha_addr;
+             }
+             if(connect_nb(sock, addr, be->conn_to) == 0) {
+@@ -1044,6 +1056,9 @@
+                 default:
+                     continue;
+                 }
++                if (be->dyn_addr && upd_addr(be->hostname, &be->addr)) {
++                    logmsg(LOG_NOTICE, "failed to resolve hostname '%s': %s", be->hostname, strerror(errno));
++                }
+                 addr = &be->addr;
+             } else {
+                 switch(be->ha_addr.ai_family) {
+@@ -1062,6 +1077,9 @@
+                 default:
+                     continue;
+                 }
++                if (be->dyn_ha_addr && upd_addr(be->ha_hostname, &be->ha_addr)) {
++                    logmsg(LOG_NOTICE, "failed to resolve hostname '%s': %s", be->ha_hostname, strerror(errno));
++                }
+                 addr = &be->ha_addr;
+             }
+             if(connect_nb(sock, addr, be->conn_to) == 0) {
+@@ -1671,3 +1689,36 @@
+         close(ctl);
+     }
+ }
++
++/* update address */
++int
++upd_addr(char *hostname, struct addrinfo *ai)
++{
++
++    int r;
++    in_port_t port;
++
++    /* get_host will set the port to zero */
++    switch(ai->ai_family) {
++        case AF_INET:
++            port = ((struct sockaddr_in *)ai->ai_addr)->sin_port;
++            break;
++        case AF_INET6:
++            port = ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port;
++            break;
++    }
++
++    r = get_host(hostname, ai);
++
++    switch(ai->ai_family) {
++        case AF_INET:
++            ((struct sockaddr_in *)ai->ai_addr)->sin_port = port;
++            break;
++        case AF_INET6:
++            ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = port;
++            break;
++    }
++
++    return r;
++
++}