I have this patch (attached) floating around that allows users to
configure a *fixed* UID for each vhost.

There are several places where we need an ID for vhosts, and where we
compute one based on ServerName/Port, addresses, configuration path
and line numbers, ...
This UID could be used instead, moreover since it has the property to
not change on (re)starts we can also use it for things bound to a
vhost regardless of the startup and unrelated configuration changes
(the attached patch uses it for SHMs in mod_proxy_balancer, as an
example).

If no ServerUID is configured, I _think_ we can compute one too,
better than the one usually computed in our code since it won't change
unless address(es)/port(s) or ServerName of the vhost changes (which
is not a "light" change anyway).
In any case the patch also handles collisions, if ever...
So for this what the patch does is (with rationale in comment):

+    int i, *num;
+    apr_hash_t *servers_uids = apr_hash_make(p);
[]
+        if (!s->server_uid) {
+            server_addr_rec *addr;
+            apr_md5_ctx_t md5_ctx;
+            unsigned char md5[APR_MD5_DIGESTSIZE];
+
+            /* Assumes the unique identifier of a vhost is its address(es)
+             * plus the ServerName:Port. Should two or more vhosts have this
+             * same identifier, the first one would always be elected to
+             * handle the requests, so this shouldn't be an issue...
+             */
+            apr_md5_init(&md5_ctx);
+            for (addr = s->addrs; addr; addr = addr->next) {
+                char host_ip[64]; /* for any IPv[46] string */
+                apr_sockaddr_ip_getbuf(host_ip, sizeof host_ip,
+                                       addr->host_addr);
+                apr_md5_update(&md5_ctx, (unsigned char *)host_ip,
+                                         strlen(host_ip));
+                apr_md5_update(&md5_ctx, (unsigned char *)&addr->host_port,
+                                         sizeof(addr->host_port));
+            }
+            apr_md5_update(&md5_ctx, (unsigned char *)s->server_hostname,
+                                     strlen(s->server_hostname));
+            apr_md5_update(&md5_ctx, (unsigned char *)&s->port,
+                                     sizeof(s->port));
+            apr_md5_final(md5, &md5_ctx);
+
+            s->server_uid = apr_pescape_hex(p, md5, sizeof md5, 0);
+        }
+        /* Handle collisions, that's Unique ID! */
+        num = apr_hash_get(servers_uids, s->server_uid,
+                           APR_HASH_KEY_STRING);
+        if (num) {
+            ++*num;
+            s->server_uid = apr_psprintf(p, "%s_%i", s->server_uid, *num);
+        }
+        else {
+            num = apr_pcalloc(p, sizeof *num);
+            apr_hash_set(servers_uids, s->server_uid,
+                         APR_HASH_KEY_STRING, num);
+        }
(Rest attached)

WDYT?
Index: include/httpd.h
===================================================================
--- include/httpd.h	(revision 1822878)
+++ include/httpd.h	(working copy)
@@ -1388,6 +1388,9 @@ struct server_rec {
      *  inherited (0) from the base server (either first
      *  server on the same IP:port or main server) */
     unsigned int keep_alive_timeout_set:1;
+
+    /** A unique ID for the server */
+    const char *server_uid;
 };
 
 /**
Index: server/core.c
===================================================================
--- server/core.c	(revision 1822878)
+++ server/core.c	(working copy)
@@ -4548,6 +4548,9 @@ AP_INIT_TAKE1("HostnameLookups", set_hostname_look
 AP_INIT_TAKE1("ServerAdmin", set_server_string_slot,
   (void *)APR_OFFSETOF(server_rec, server_admin), RSRC_CONF,
   "The email address of the server administrator"),
+AP_INIT_TAKE1("ServerUID", set_server_string_slot,
+  (void *)APR_OFFSETOF(server_rec, server_uid), RSRC_CONF,
+  "The unique identifier of the server"),
 AP_INIT_TAKE1("ServerName", server_hostname_port, NULL, RSRC_CONF,
   "The hostname and port of the server"),
 AP_INIT_TAKE1("ServerSignature", set_signature_flag, NULL, OR_ALL,
Index: server/vhost.c
===================================================================
--- server/vhost.c	(revision 1822878)
+++ server/vhost.c	(working copy)
@@ -25,6 +25,9 @@
 #include "apr_lib.h"
 #include "apr_version.h"
 
+#include "apr_md5.h"
+#include "apr_escape.h"
+
 #define APR_WANT_STRFUNC
 #include "apr_want.h"
 
@@ -574,8 +577,9 @@ AP_DECLARE(void) ap_fini_vhost_config(apr_pool_t *
     server_addr_rec *sar;
     int has_default_vhost_addr;
     server_rec *s;
-    int i;
+    int i, *num;
     ipaddr_chain **iphash_table_tail[IPHASH_TABLE_SIZE];
+    apr_hash_t *servers_uids = apr_hash_make(p);
 
     /* Main host first */
     s = main_s;
@@ -682,6 +686,47 @@ AP_DECLARE(void) ap_fini_vhost_config(apr_pool_t *
                 }
             }
         }
+
+        if (!s->server_uid) {
+            server_addr_rec *addr;
+            apr_md5_ctx_t md5_ctx;
+            unsigned char md5[APR_MD5_DIGESTSIZE];
+
+            /* Assumes the unique identifier of a vhost is its address(es)
+             * plus the ServerName:Port. Should two or more vhosts have this
+             * same identifier, the first one would always be elected to
+             * handle the requests, so this shouldn't be an issue...
+             */
+            apr_md5_init(&md5_ctx);
+            for (addr = s->addrs; addr; addr = addr->next) {
+                char host_ip[64]; /* for any IPv[46] string */
+                apr_sockaddr_ip_getbuf(host_ip, sizeof host_ip,
+                                       addr->host_addr);
+                apr_md5_update(&md5_ctx, (unsigned char *)host_ip,
+                                         strlen(host_ip));
+                apr_md5_update(&md5_ctx, (unsigned char *)&addr->host_port,
+                                         sizeof(addr->host_port));
+            }
+            apr_md5_update(&md5_ctx, (unsigned char *)s->server_hostname,
+                                     strlen(s->server_hostname));
+            apr_md5_update(&md5_ctx, (unsigned char *)&s->port,
+                                     sizeof(s->port));
+            apr_md5_final(md5, &md5_ctx);
+
+            s->server_uid = apr_pescape_hex(p, md5, sizeof md5, 0);
+        }
+        /* Handle collisions, that's Unique ID! */
+        num = apr_hash_get(servers_uids, s->server_uid,
+                           APR_HASH_KEY_STRING);
+        if (num) {
+            ++*num;
+            s->server_uid = apr_psprintf(p, "%s_%i", s->server_uid, *num);
+        }
+        else {
+            num = apr_pcalloc(p, sizeof *num);
+            apr_hash_set(servers_uids, s->server_uid,
+                         APR_HASH_KEY_STRING, num);
+        }
     }
 
 #ifdef IPHASH_STATISTICS
Index: modules/proxy/mod_proxy_balancer.c
===================================================================
--- modules/proxy/mod_proxy_balancer.c	(revision 1822878)
+++ modules/proxy/mod_proxy_balancer.c	(working copy)
@@ -775,7 +775,6 @@ static int balancer_post_config(apr_pool_t *pconf,
      */
     while (s) {
         int i,j;
-        char *id;
         proxy_balancer *balancer;
         ap_slotmem_type_t type;
         void *sconf = s->module_config;
@@ -784,16 +783,9 @@ static int balancer_post_config(apr_pool_t *pconf,
          * During create_proxy_config() we created a dummy id. Now that
          * we have identifying info, we can create the real id
          */
-        id = apr_psprintf(pconf, "%s.%s.%d.%s.%s.%u.%s",
-                          (s->server_scheme ? s->server_scheme : "????"),
-                          (s->server_hostname ? s->server_hostname : "???"),
-                          (int)s->port,
-                          (s->server_admin ? s->server_admin : "??"),
-                          (s->defn_name ? s->defn_name : "?"),
-                          s->defn_line_number,
-                          (s->error_fname ? s->error_fname : DEFAULT_ERRORLOG));
-        conf->id = apr_psprintf(pconf, "p%x",
-                                ap_proxy_hashfunc(id, PROXY_HASHFUNC_DEFAULT));
+        conf->id = apr_psprintf(pconf, "ap_lb%x",
+                                ap_proxy_hashfunc(s->server_uid,
+                                                  PROXY_HASHFUNC_DEFAULT));
         if (conf->bslot) {
             /* Shared memory already created for this proxy_server_conf.
              */

Reply via email to