Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.211
diff -u -p -r1.211 bootstrap.inc
--- includes/bootstrap.inc	26 May 2008 17:12:54 -0000	1.211
+++ includes/bootstrap.inc	25 Jun 2008 22:07:42 -0000
@@ -1160,16 +1160,20 @@ function language_default($property = NU
 
 /**
  * If Drupal is behind a reverse proxy, we use the X-Forwarded-For header
- * instead of $_SERVER['REMOTE_ADDR'], which would be the IP address
- * of the proxy server, and not the client's.
+ * instead of $_SERVER['REMOTE_ADDR'], which would be the IP address of 
+ * the proxy server, and not the client's.  If Drupal is run in a cluster
+ * we use the X-Cluster-Client-Ip header instead.
  *
+ * @param $reset
+ *   Reset the current ip address saved in static
  * @return
- *   IP address of client machine, adjusted for reverse proxy.
+ *   IP address of client machine, adjusted for reverse proxy and/or cluster
+ *   environments.
  */
-function ip_address() {
+function ip_address($reset = false) {
   static $ip_address = NULL;
 
-  if (!isset($ip_address)) {
+  if (!isset($ip_address) || $reset) {
     $ip_address = $_SERVER['REMOTE_ADDR'];
     if (variable_get('reverse_proxy', 0) && array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) {
       // If an array of known reverse proxy IPs is provided, then trust
@@ -1181,6 +1185,13 @@ function ip_address() {
         $ip_address = array_pop(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']));
       }
     }
+
+    // When Drupal is run in a cluster environment, REMOTE_ADDR contains the IP
+    // address of a server in the cluster, while the IP address of the client is
+    // stored in HTTP_X_CLUSTER_CLIENT_IP.
+    if (array_key_exists('HTTP_X_CLUSTER_CLIENT_IP', $_SERVER)) {
+      $ip_address = $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
+    }
   }
 
   return $ip_address;
Index: includes/bootstrap.test
===================================================================
RCS file: includes/bootstrap.test
diff -N includes/bootstrap.test
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ includes/bootstrap.test	25 Jun 2008 22:07:42 -0000
@@ -0,0 +1,83 @@
+<?php
+
+class BootstrapIPAddressTestCase extends DrupalWebTestCase {
+
+  /**
+   * Implementation of getInfo().
+   */
+  function getInfo() {
+    return array(
+      'name' => t('Ip address test'),
+      'description' => t('Get the ip address from the current visitor from the server variables.'),
+      'group' => t('Bootstrap')
+    );
+  }
+
+  /**
+   * Implementation of setUp().
+   */
+  function setUp() {
+    $this->oldserver = $_SERVER;
+
+    $this->remote_ip = '127.0.0.1';
+    $this->proxy_ip = '127.0.0.2';
+    $this->forwarded_ip = '127.0.0.3';
+    $this->cluster_ip = '127.0.0.4';
+    $this->untrusted_ip = '0.0.0.0';
+        
+    $_SERVER['REMOTE_ADDR'] = $this->remote_ip;
+    unset($_SERVER['HTTP_X_FORWARDED_FOR']);
+    unset($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']);
+    
+    parent::setUp();
+  }
+  
+  /**
+   * Implementation of tearDown().
+   */
+  function tearDown() {
+    $_SERVER = $this->oldserver;
+    parent::tearDown();
+  }
+
+  /**
+   * testIpAddress
+   */
+  function testIPAddress() {
+    // Normal ip address
+    $this->assertTrue(
+      ip_address(true) == $this->remote_ip,
+      t('Got remote ip address')
+    );
+    
+    // Proxy forwarding on but no proxy addresses defined
+    variable_set('reverse_proxy', 1);
+    $this->assertTrue(
+      ip_address(true) == $this->remote_ip,
+      t('Proxy forwarding without trusted proxies got remote ip address')
+    );
+    
+    // Proxy forwarding on and proxy address not trusted
+    variable_set('reverse_proxy_addresses', array($this->proxy_ip));
+    $_SERVER['REMOTE_ADDR'] = $this->untrusted_ip;
+    $this->assertTrue(
+      ip_address(true) == $this->untrusted_ip,
+      t('Proxy forwarding with untrusted proxy got remote ip address')
+    );
+
+    // Proxy forwarding on and proxy address trusted
+    $_SERVER['REMOTE_ADDR'] = $this->proxy_ip;
+    $_SERVER['HTTP_X_FORWARDED_FOR'] = $this->forwarded_ip;
+    $this->assertTrue(
+      ip_address(true) == $this->forwarded_ip,
+      t('Proxy forwarding with trusted proxy got forwarded ip address')
+    );   
+    
+    // Cluster environment
+    $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'] = $this->cluster_ip;
+    $this->assertTrue(
+      ip_address(true) == $this->cluster_ip,
+      t('Cluster environment got cluster client ip')
+    );
+  }
+}
