httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dean Gaudet <dgau...@hotwired.com>
Subject multiple ips per virtual server feature
Date Sun, 07 Jan 1996 02:19:43 GMT
Uploaded to apache/incoming/multi_ip_per_virtual_server_patch.

This patch to Apache 0.8.16 (so I'm behind a bit) allows multiple ips
per virtual server.  One use is for multihomed machines.  Another use
is for load distribution with redundancy and no DNS timeout problems:

Suppose you have two machines w1 and w2 serving pages.  Suppose you have
two domains a and b that you serve pages for.  Then set your DNS up
something like this:

w1	IN A 10.0.0.1
w2	IN A 10.0.0.2
a1	IN A 10.0.0.3
a2	IN A 10.0.0.4
b1	IN A 10.0.0.5
b2	IN A 10.0.0.6
a	IN CNAME a1
a	IN CNAME a2
b	IN CNAME b1
b	IN CNAME b2

On w1 and w2 add ipaliases for ALL of a1, a2, b1, b2.  But on w1,
configure the a2 and b2 interfaces down (or just don't proxy arp them
according to how your OS does aliases).  On w2 configure the a1 and b1
interfaces down.

Run the same httpd.conf on both machines, with virtual definitions something
like this:

<VirtualHost a1 a2>
... defns for a
</VirtualHost>

<VirtualHost b1 b2>
... defns for b
</VirtualHost>

If w1 fails for some reason, then to shift its load to w2 it is a matter
of bringing up the {a,b}1 interfaces on w2 and flushing the arp cache
on your router.  (Or as Cliff suggested to me, do promiscuous arp if
your router supports it.)

This can be done in a matter of seconds after w1 fails.  The only
side-effect is that clients with connections in progress when w1 fails
will get connection reset.

The reason I give w1 and w2 distinct addresses above is so that you can
write code for w1 and w2 to negotiate which addresses they handle.  This
is the step I haven't done yet ;)

Dean

Index: http_config.c
===================================================================
RCS file: /hot/repository/apache/src/http_config.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 http_config.c
--- http_config.c	1995/10/10 22:04:07	1.1.1.3
+++ http_config.c	1996/01/07 01:50:06
@@ -611,9 +611,43 @@
  * are with the command table in http_core.c.
  */
 
-server_rec *init_virtual_host (pool *p, char *hostname)
+
+static server_addr_rec **get_addresses( pool *p, char *w, server_addr_rec **paddr )
+{
+    struct hostent *hep;
+    unsigned long my_addr;
+    int i;
+
+    my_addr = inet_addr( w );
+    if( my_addr != ((unsigned long) 0xffffffff) ) {
+	(*paddr) = pcalloc( p, sizeof( server_addr_rec ) );
+	(*paddr)->host_addr.s_addr = my_addr;
+	return( &(*paddr)->next );
+    }
+
+    hep = gethostbyname(w);
+
+    if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
+	fprintf (stderr, "Cannot resolve host name %s --- exiting!\n", w);
+	exit(1);
+    }
+
+    for( i = 0; hep->h_addr_list[i]; ++i ) {
+	(*paddr) = pcalloc( p, sizeof( server_addr_rec ) );
+	(*paddr)->host_addr = *(struct in_addr *)hep->h_addr_list[i];
+	paddr = &(*paddr)->next;
+    }
+    return( paddr );
+}
+
+
+server_rec *init_virtual_host (pool *p, char *hostnames)
 {
     server_rec *s = (server_rec *)pcalloc (p, sizeof (server_rec));
+    char *ptr;
+    server_addr_rec **paddr;
+    char *start_of_name;
+    int save_char;
 
 #ifdef RLIMIT_NOFILE
     struct rlimit limits;
@@ -634,7 +668,26 @@
     s->access_confname = NULL;
     s->timeout = 0;
     s->do_rfc931 = 0;
-    s->host_addr.s_addr = get_virthost_addr (hostname, 0);
+    /* parse hostnames */
+    s->addrs = NULL;
+    paddr = &s->addrs;
+    ptr = hostnames;
+    for(;;) {
+	if( *ptr == 0 ) break;
+	while( isspace( *ptr ) ) ++ptr;
+	if( *ptr == 0 ) break;
+	start_of_name = ptr;
+	while( *ptr && !isspace( *ptr ) ) ++ptr;
+	save_char = *ptr;
+	*ptr = 0;
+	paddr = get_addresses( p, start_of_name, paddr );
+	if( save_char == 0 ) break;
+	++ptr;
+    }
+    if( s->addrs == NULL ) {
+	fprintf( stderr, "virtual host must have at least one address\n" );
+	exit(1);
+    }
     s->next = NULL;
 
     s->module_config = create_empty_config (p);
@@ -645,7 +698,7 @@
 
 int is_virtual_server (server_rec *s)
 {
-    return s->host_addr.s_addr != htonl (INADDR_ANY);
+    return s->addrs->host_addr.s_addr != htonl (INADDR_ANY);
 }
 
 void fixup_virtual_hosts (pool *p, server_rec *main_server)
@@ -715,7 +768,8 @@
     s->timeout = DEFAULT_TIMEOUT;
     s->do_rfc931 = DEFAULT_RFC931;
     s->next = NULL;
-    s->host_addr.s_addr = htonl (INADDR_ANY); /* NOT virtual host;
+    s->addrs = pcalloc(p, sizeof (server_addr_rec) );
+    s->addrs->host_addr.s_addr = htonl (INADDR_ANY); /* NOT virtual host;
 					       * don't match any real network
 					       * interface.
 					       */
Index: http_main.c
===================================================================
RCS file: /hot/repository/apache/src/http_main.c,v
retrieving revision 1.5
diff -u -r1.5 http_main.c
--- http_main.c	1995/11/07 04:13:27	1.5
+++ http_main.c	1995/12/29 01:54:54
@@ -663,12 +663,14 @@
 {
     struct in_addr server_ip; 
     server_rec *virt;
+    server_addr_rec *addr;
 
     server_ip = get_local_addr (fileno(client_fd));
     
     for (virt = server->next; virt; virt = virt->next)
-	if (virt->host_addr.s_addr == server_ip.s_addr)
-	    return virt;
+	for(addr = virt->addrs; addr; addr = addr->next)
+	    if (addr->host_addr.s_addr == server_ip.s_addr)
+		return virt;
 
     return server;
 }
@@ -684,7 +686,7 @@
     
     for (s = s->next; s; s = s->next)
 	if (!s->server_hostname) {
-	    struct hostent *h = gethostbyaddr ((char *)&(s->host_addr),
+	    struct hostent *h = gethostbyaddr ((char *)&(s->addrs->host_addr),
 					       sizeof (struct in_addr),
 					       AF_INET);
 	    if (h != NULL) {
@@ -764,7 +766,7 @@
 
     memset((char *) &sa_server, 0, sizeof(sa_server));
     sa_server.sin_family=AF_INET;
-    sa_server.sin_addr.s_addr=server_conf->host_addr.s_addr;
+    sa_server.sin_addr.s_addr=server_conf->addrs->host_addr.s_addr;
     sa_server.sin_port=htons(server_conf->port);
 
 #ifdef NEXT
Index: httpd.h
===================================================================
RCS file: /hot/repository/apache/src/httpd.h,v
retrieving revision 1.7
diff -u -r1.7 httpd.h
--- httpd.h	1995/12/18 23:20:27	1.7
+++ httpd.h	1995/12/29 01:50:13
@@ -356,6 +356,12 @@
 
 /* Per-vhost config... */
 
+typedef struct server_addr_rec server_addr_rec;
+struct server_addr_rec {
+    server_addr_rec *next;
+    struct in_addr host_addr;
+};
+
 struct server_rec {
 
   server_rec *next;
@@ -386,7 +392,7 @@
   /* Transaction handling */
 
   short port;
-  struct in_addr host_addr;	/* Specific address, if "virtual" server */
+  server_addr_rec *addrs;	/* specific addresses if "virtual" server */
   int timeout;			/* Timeout, in seconds, before we give up */
   int do_rfc931;		/* See if client is advertising a username? */
   

Mime
View raw message