httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dean Gaudet <dgau...@hotwired.com>
Subject multiple server ip patch
Date Thu, 25 Jul 1996 07:03:03 GMT
Here's a patch (against vanilla 1.1.1) which expands the <VirtualHost>
syntax to allow the following:

    <VirtualHost addr1 addr2 ...>

Where addr1, addr2, and so on are possibly multihomed hosts.

It also adds the magic ip address 255.255.255.255 which becomes the
default for all unmatched ips.

This doesn't mix well with HTTP/1.1 virtualhosts.  In particular, it
doesn't do anything intelligent with all the server names.  But it
should be easy to fix -- I didn't fix it, because I couldn't grok
why there were so many ways to specify the "names" of a server.
It shouldn't break anything existing -- it just doesn't extend 
name-vhosts as naturally as it extends ip-vhosts.

I've uploaded this to incoming as multi-ip.patch.  I don't expect it
to go into 1.1, I'm submitting it for 1.2.

Dean

diff -c3 -r apache_1.1.1/src/http_config.c multi_ip/src/http_config.c
*** apache_1.1.1/src/http_config.c	Sat Jun 29 12:52:11 1996
--- multi_ip/src/http_config.c	Wed Jul 24 23:41:52 1996
***************
*** 631,639 ****
--- 631,708 ----
   * are with the command table in http_core.c.
   */
  
+ /*
+  * Parses a host of the form <address>[:port]
+  * paddr is used to create a list in the order of input
+  * **paddr is the ->next pointer of the last entry (or s->addrs)
+  * *paddr is the variable used to keep track of **paddr between calls
+  */
+ static void get_addresses (pool *p, char *w, server_addr_rec ***paddr)
+ {
+     struct hostent *hep;
+     unsigned long my_addr;
+     int ports;
+     server_addr_rec *sar;
+     int i;
+ 
+     if( *w == 0 ) return;
+ 
+     t = strchr(w, ':');
+     ports = 0;
+     if (t != NULL && strcmp(t+1, "*") != 0) ports = atoi(t+1);
+ 
+     if (t != NULL) *t = '\0';
+     if (strcmp(w, "*") == 0) {
+ 	sar = pcalloc( p, sizeof( server_addr_rec ) );
+ 	**paddr = sar;
+ 	*paddr = &sar->next;
+ 	sar->host_addr.s_addr = htonl(INADDR_ANY);
+ 	sar->host_port = ports;
+ 	sar->virthost = pstrdup(p, w);
+ 	if (t != NULL) *t = ':';
+ 	return;
+     }
+ 
+ #ifdef DGUX
+     my_addr = inet_network(w);
+ #else
+     my_addr = inet_addr(w);
+ #endif
+     if (my_addr != ((unsigned long) 0xffffffff)) {
+ 	sar = pcalloc( p, sizeof( server_addr_rec ) );
+ 	**paddr = sar;
+ 	*paddr = &sar->next;
+ 	sar->host_addr.s_addr = my_addr;
+ 	sar->host_port = ports;
+ 	sar->virthost = pstrdup(p, w);
+ 	if (t != NULL) *t = ':';
+ 	return;
+     }
+ 
+     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 ) {
+ 	sar = pcalloc( p, sizeof( server_addr_rec ) );
+ 	**paddr = sar;
+ 	*paddr = &sar->next;
+ 	sar->host_addr = *(struct in_addr *)hep->h_addr_list[i];
+ 	sar->host_port = ports;
+ 	sar->virthost = pstrdup(p, w);
+     }
+ 
+     if (t != NULL) *t = ':';
+ }
+ 
  server_rec *init_virtual_host (pool *p, char *hostname)
  {
      server_rec *s = (server_rec *)pcalloc (p, sizeof (server_rec));
+     char *t;
+     server_addr_rec **addrs;
  
  #ifdef RLIMIT_NOFILE
      struct rlimit limits;
***************
*** 654,670 ****
      s->timeout = 0;
      s->keep_alive_timeout = 0;
      s->keep_alive = -1;
!     s->host_addr.s_addr = get_virthost_addr (hostname, &s->host_port);
!     s->port = s->host_port;  /* set them the same, by default */
      s->next = NULL;
  
      s->is_virtual = 1;
-     s->virthost = pstrdup(p, hostname);
      s->names = NULL;
  
      s->module_config = create_empty_config (p);
      s->lookup_defaults = create_per_dir_config (p);
!     
      return s;
  }
  
--- 723,748 ----
      s->timeout = 0;
      s->keep_alive_timeout = 0;
      s->keep_alive = -1;
!     /* start the list of addreses */
!     addrs = &s->addrs;
!     while( hostname[0] ) {
! 	get_addresses( p, getword_conf( p, &hostname ), &addrs );
!     }
!     /* terminate the list */
!     *addrs = NULL;
!     if( s->addrs == NULL ) {
! 	fprintf( stderr, "virtual host must have at least one address\n" );
! 	exit(1);
!     }
!     s->port = s->addrs->host_port;  /* set them the same, by default */
      s->next = NULL;
  
      s->is_virtual = 1;
      s->names = NULL;
  
      s->module_config = create_empty_config (p);
      s->lookup_defaults = create_per_dir_config (p);
! 
      return s;
  }
  
***************
*** 746,760 ****
      s->keep_alive_timeout = DEFAULT_KEEPALIVE_TIMEOUT;
      s->keep_alive = DEFAULT_KEEPALIVE;
      s->next = NULL;
!     s->host_addr.s_addr = htonl (INADDR_ANY); /* NOT virtual host;
  					       * don't match any real network
  					       * interface.
  					       */
!     s->host_port = 0; /* matches any port */
  
      s->module_config = create_server_config (p, s);
      s->lookup_defaults = create_default_per_dir_config (p);
!     
      return s;
  }
  
--- 824,839 ----
      s->keep_alive_timeout = DEFAULT_KEEPALIVE_TIMEOUT;
      s->keep_alive = DEFAULT_KEEPALIVE;
      s->next = NULL;
!     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.
  					       */
!     s->addrs->host_port = 0; /* matches any port */
  
      s->module_config = create_server_config (p, s);
      s->lookup_defaults = create_default_per_dir_config (p);
! 
      return s;
  }
  
diff -c3 -r apache_1.1.1/src/http_core.c multi_ip/src/http_core.c
*** apache_1.1.1/src/http_core.c	Wed Jun 12 11:14:31 1996
--- multi_ip/src/http_core.c	Fri Jul 12 22:09:19 1996
***************
*** 591,596 ****
--- 591,601 ----
  
      if (endp) *endp = '\0';
      
+     /* FIXME: There's another feature waiting to happen here -- since you
+ 	can now put multiple addresses/names on a single <VirtualHost>
+ 	you might want to use it to group common definitions and then
+ 	define other "subhosts" with their individual differences.  But
+ 	personally I'd rather just do it with a macro preprocessor. -djg */
      if (main_server->is_virtual)
  	return "<VirtualHost> doesn't nest!";
      
diff -c3 -r apache_1.1.1/src/http_main.c multi_ip/src/http_main.c
*** apache_1.1.1/src/http_main.c	Mon Jul  8 12:00:35 1996
--- multi_ip/src/http_main.c	Wed Jul 24 23:42:13 1996
***************
*** 1039,1053 ****
  				 server_rec *server)
  {
      server_rec *virt;
  
!     for (virt = server->next; virt; virt = virt->next)
! 	if ((virt->is_virtual == 1) &&	/* VirtualHost */
! 	    (virt->host_addr.s_addr == htonl(INADDR_ANY) ||
! 	     virt->host_addr.s_addr == server_ip.s_addr) &&
! 	    (virt->host_port == 0 || virt->host_port == port))
! 	    return virt;
  
!     return server;
  }
  
  void default_server_hostnames(server_rec *s)
--- 1039,1066 ----
  				 server_rec *server)
  {
      server_rec *virt;
+     server_addr_rec *sar;
+     server_rec *def;
  
!     def = server;
!     for (virt = server->next; virt; virt = virt->next) {
! 	for (sar = virt->addrs; sar; sar = sar->next) {
! 	    if ((virt->is_virtual == 1) &&	/* VirtualHost */
! 		(sar->host_addr.s_addr == htonl(INADDR_ANY) ||
! 		sar->host_addr.s_addr == server_ip.s_addr) &&
! 		(sar->host_port == 0 || sar->host_port == port)) {
! 		return virt;
! 	    } else if ( sar->host_addr.s_addr == 0xffffffff ) {
! 		/* this is so that you can build a server that is the
! 		    "default" for any interface which isn't explicitly
! 		    specified.  So that you can implement "deny anything
! 		    which isn't expressly permitted" -djg */
! 		def = virt;
! 	    }
! 	}
!     }
  
!     return def;
  }
  
  void default_server_hostnames(server_rec *s)
***************
*** 1055,1087 ****
      struct hostent *h, *main;
      char *def_hostname;
      int n;
  
      /* Main host first */
      
!     if (!s->server_hostname)
  	s->server_hostname = get_local_host(pconf);
  
      def_hostname = s->server_hostname;
      main = gethostbyname(def_hostname);
  
      /* Then virtual hosts */
      
      for (s = s->next; s; s = s->next) {
  	/* Check to see if we might be a HTTP/1.1 virtual host - same IP */
  	for (n = 0; main->h_addr_list[n] != NULL; n++) {
! 	  if (s->host_addr.s_addr ==
! 	      (((struct in_addr *)(main->h_addr_list[n]))->s_addr))
! 	    s->is_virtual = 2;
  	}
  
          if (!s->server_hostname) {
  	    if (s->is_virtual == 2)
! 	        s->server_hostname = s->virthost;
! 	    else if (s->host_addr.s_addr == htonl(INADDR_ANY))
  		s->server_hostname = def_hostname;
  	    else
  	    {
! 		h = gethostbyaddr ((char *)&(s->host_addr),
  				   sizeof (struct in_addr), AF_INET);
  		if (h != NULL)
  		    s->server_hostname = pstrdup (pconf, (char *)h->h_name);
--- 1068,1118 ----
      struct hostent *h, *main;
      char *def_hostname;
      int n;
+     server_addr_rec *sar;
+     int has_inaddr_any;
  
      /* Main host first */
      
!     if (!s->server_hostname) {
  	s->server_hostname = get_local_host(pconf);
+     }
  
      def_hostname = s->server_hostname;
      main = gethostbyname(def_hostname);
+     if( main == NULL ) {
+ 	fprintf(stderr,"httpd: cannot determine local host name.\n");
+ 	fprintf(stderr,"Use ServerName to set it manually.\n");
+ 	exit(1);
+     }
+ 
  
      /* Then virtual hosts */
      
      for (s = s->next; s; s = s->next) {
  	/* Check to see if we might be a HTTP/1.1 virtual host - same IP */
+ 	has_inaddr_any = 0;
  	for (n = 0; main->h_addr_list[n] != NULL; n++) {
! 	    for(sar = s->addrs; sar; sar = sar->next) {
! 		if (sar->host_addr.s_addr ==
! 		    (((struct in_addr *)(main->h_addr_list[n]))->s_addr))
! 		    s->is_virtual = 2;
! 		if( sar->host_addr.s_addr == htonl(INADDR_ANY) ) {
! 		    has_inaddr_any = 1;
! 		}
! 	    }
  	}
  
+ 	/* FIXME: some of this decision doesn't make a lot of sense in
+ 	    the presence of multiple addresses on the <VirtualHost>
+ 	    directive.  It should issue warnings here perhaps. -djg */
          if (!s->server_hostname) {
  	    if (s->is_virtual == 2)
! 	        s->server_hostname = s->addrs->virthost;
! 	    else if (has_inaddr_any)
  		s->server_hostname = def_hostname;
  	    else
  	    {
! 		h = gethostbyaddr ((char *)&(s->addrs->host_addr),
  				   sizeof (struct in_addr), AF_INET);
  		if (h != NULL)
  		    s->server_hostname = pstrdup (pconf, (char *)h->h_name);
***************
*** 1089,1095 ****
  	}
      }
  }
! 	
  void abort_connection (conn_rec *c)
  {
      /* Make sure further I/O DOES NOT HAPPEN */
--- 1120,1126 ----
  	}
      }
  }
! 
  void abort_connection (conn_rec *c)
  {
      /* Make sure further I/O DOES NOT HAPPEN */
diff -c3 -r apache_1.1.1/src/http_protocol.c multi_ip/src/http_protocol.c
*** apache_1.1.1/src/http_protocol.c	Sun Jun 23 11:05:16 1996
--- multi_ip/src/http_protocol.c	Fri Jul 12 23:10:08 1996
***************
*** 375,386 ****
    char *host = getword(r->pool, &r->hostname, ':');	/* Get rid of port */
    int port = (*r->hostname) ? atoi(r->hostname) : 0;
    server_rec *s;
  
    if (port && (port != r->server->port))
      return;
  
!   if ((host[strlen(host)-1]) == '.') {
!     host[strlen(host)-1] = '\0';
    }
  
    r->hostname = host;
--- 375,388 ----
    char *host = getword(r->pool, &r->hostname, ':');	/* Get rid of port */
    int port = (*r->hostname) ? atoi(r->hostname) : 0;
    server_rec *s;
+   int l;
  
    if (port && (port != r->server->port))
      return;
  
!   l = strlen(host)-1;
!   if ((host[l]) == '.') {
!     host[l] = '\0';
    }
  
    r->hostname = host;
diff -c3 -r apache_1.1.1/src/httpd.h multi_ip/src/httpd.h
*** apache_1.1.1/src/httpd.h	Mon Jul  8 12:01:19 1996
--- multi_ip/src/httpd.h	Wed Jul 24 20:07:04 1996
***************
*** 450,455 ****
--- 450,464 ----
  
  /* Per-vhost config... */
  
+ typedef struct server_addr_rec server_addr_rec;
+ struct server_addr_rec {
+     server_addr_rec *next;
+     struct in_addr host_addr;	/* The bound address, for this server */
+     short host_port;         	/* The bound port, for this server */   
+     char *virthost;		/* The name given in <VirtualHost> */
+ };
+ 
+ 
  struct server_rec {
  
    server_rec *next;
***************
*** 481,488 ****
  				 */
    /* Transaction handling */
  
!   struct in_addr host_addr;	/* The bound address, for this server */
!   short host_port;              /* The bound port, for this server */
    int timeout;			/* Timeout, in seconds, before we give up */
    int keep_alive_timeout;	/* Seconds we'll wait for another request */
    int keep_alive;		/* Maximum requests per connection */
--- 490,496 ----
  				 */
    /* Transaction handling */
  
!   server_addr_rec *addrs;	
    int timeout;			/* Timeout, in seconds, before we give up */
    int keep_alive_timeout;	/* Seconds we'll wait for another request */
    int keep_alive;		/* Maximum requests per connection */
***************
*** 491,497 ****
    int pathlen;			/* Length of path */
  
    char *names;			/* Wildcarded names for HostAlias servers */
-   char *virthost;		/* The name given in <VirtualHost> */
  };
  
  /* These are more like real hosts than virtual hosts */
--- 499,504 ----

Mime
View raw message