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 ----