akosut 96/08/19 11:33:03
Modified: src http_config.c http_core.c http_main.c
http_protocol.c httpd.h
Log:
Allow for multiple IP addresses per virtual host.
Submitted by: Dean Gaudet
Reviewed by: Alexei Kosut, Mark J Cox
Revision Changes Path
1.20 +86 -6 apache/src/http_config.c
Index: http_config.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_config.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -C3 -r1.19 -r1.20
*** http_config.c 1996/08/15 13:56:53 1.19
--- http_config.c 1996/08/19 18:32:56 1.20
***************
*** 685,693 ****
--- 685,763 ----
* 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;
+ char *t;
+ 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;
***************
*** 708,719 ****
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);
--- 778,798 ----
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);
***************
*** 804,818 ****
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;
}
--- 883,898 ----
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;
}
1.31 +5 -0 apache/src/http_core.c
Index: http_core.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_core.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -C3 -r1.30 -r1.31
*** http_core.c 1996/08/15 13:56:55 1.30
--- http_core.c 1996/08/19 18:32:57 1.31
***************
*** 722,727 ****
--- 722,732 ----
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!";
1.60 +46 -15 apache/src/http_main.c
Index: http_main.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_main.c,v
retrieving revision 1.59
retrieving revision 1.60
diff -C3 -r1.59 -r1.60
*** http_main.c 1996/08/15 23:00:09 1.59
--- http_main.c 1996/08/19 18:32:58 1.60
***************
*** 1203,1217 ****
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)
--- 1203,1230 ----
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)
***************
*** 1219,1251 ****
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);
--- 1232,1282 ----
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);
***************
*** 1253,1259 ****
}
}
}
!
void abort_connection (conn_rec *c)
{
/* Make sure further I/O DOES NOT HAPPEN */
--- 1284,1290 ----
}
}
}
!
void abort_connection (conn_rec *c)
{
/* Make sure further I/O DOES NOT HAPPEN */
1.41 +4 -2 apache/src/http_protocol.c
Index: http_protocol.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_protocol.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -C3 -r1.40 -r1.41
*** http_protocol.c 1996/08/19 18:05:32 1.40
--- http_protocol.c 1996/08/19 18:32:59 1.41
***************
*** 575,586 ****
char *host = getword(r->pool, &r->hostname, ':'); /* Get rid of port */
int port = (*r->hostname) ? atoi(r->hostname) : 80;
server_rec *s;
if (port && (port != r->server->port))
return;
! if ((host[strlen(host)-1]) == '.') {
! host[strlen(host)-1] = '\0';
}
r->hostname = host;
--- 575,588 ----
char *host = getword(r->pool, &r->hostname, ':'); /* Get rid of port */
int port = (*r->hostname) ? atoi(r->hostname) : 80;
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;
1.46 +10 -3 apache/src/httpd.h
Index: httpd.h
===================================================================
RCS file: /export/home/cvs/apache/src/httpd.h,v
retrieving revision 1.45
retrieving revision 1.46
diff -C3 -r1.45 -r1.46
*** httpd.h 1996/08/15 19:22:37 1.45
--- httpd.h 1996/08/19 18:32:59 1.46
***************
*** 477,482 ****
--- 477,491 ----
/* 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;
***************
*** 508,515 ****
*/
/* 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 */
--- 517,523 ----
*/
/* 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 */
***************
*** 518,524 ****
int pathlen; /* Length of path */
char *names; /* Wildcarded names for HostAlias servers */
- char *virthost; /* The name given in <VirtualHost> */
uid_t server_uid; /* effective user id when calling exec
wrapper */
gid_t server_gid; /* effective group id when calling exec
wrapper */
--- 526,531 ----