While looking for patches to NCSA for VirtualHost capability,
I was able to find 1.3 patches and a couple full source trees,
but no patch designed for 1.4.2 virgin source, so I ported it.
Others have expressed an interest in this, so for all who
desire, here it is. If any of the people with VirtualHost
web pages would put this up, that would be great.
--
Paul Phillips | "Click _here_ if you do not
<URL:mailto:pa...@cerf.net> | have a graphical browser"
<URL:http://www.primus.com/staff/paulp/> | -- Canter and Siegel, on
<URL:pots://+1-619-220-0850/is/paul/there?> | their short-lived web site
diff -c src-orig/Makefile src/Makefile
*** src-orig/Makefile Fri Sep 1 12:29:13 1995
--- src/Makefile Fri Sep 1 14:11:14 1995
***************
*** 19,25 ****
# If you want to ensure that CGI scripts can't mess with the log files,
# use -DSECURE_LOGS
#
! CFLAGS= -O2 -g
#CFLAGS= -g -Wall -ansi -pedantic
# Place here any extra libraries you may need to link to. You
--- 19,26 ----
# If you want to ensure that CGI scripts can't mess with the log files,
# use -DSECURE_LOGS
#
! CFLAGS= -O2 -g -DAPB_BIND_ADDRESS -DAPB_VIRTUAL_HOST
! #CFLAGS= -O2 -g
#CFLAGS= -g -Wall -ansi -pedantic
# Place here any extra libraries you may need to link to. You
diff -c src-orig/http_config.c src/http_config.c
*** src-orig/http_config.c Fri Sep 1 12:29:13 1995
--- src/http_config.c Fri Sep 1 13:58:36 1995
***************
*** 29,35 ****
/* Server config globals */
int standalone;
! int port;
uid_t user_id;
gid_t group_id;
char server_root[MAX_STRING_LEN];
--- 29,38 ----
/* Server config globals */
int standalone;
! int port; /* port in host byte order */
! #ifdef APB_BIND_ADDRESS
! struct in_addr bind_address; /* address in network byte order */
! #endif /* APB_BIND_ADDRESS */
uid_t user_id;
gid_t group_id;
char server_root[MAX_STRING_LEN];
***************
*** 49,60 ****
--- 52,139 ----
int timeout;
int do_rfc931;
+ #ifdef APB_VIRTUAL_HOST
+ /* Virtual host globals */
+ int num_virt;
+ virtual_host_data virt[MAX_VIRTUAL_HOSTS];
+ #endif /* APB_VIRTUAL_HOST */
+
#ifndef NO_PASS
int max_servers;
int start_servers;
#endif
+ #ifdef APB_VIRTUAL_HOST
+ /* Parse VirtualHost region of server config file,
+ * from <VirtualHost virt_host> to </VirtualHost> */
+ int parse_virtual_host(FILE *f, int line, char *virt_host,
+ char *cfg_file, FILE *errors)
+ {
+ char l[MAX_STRING_LEN];
+ char w[MAX_STRING_LEN];
+ struct hostent *hep;
+ int n=line;
+ register int x;
+ x = num_virt;
+
+ if (x >= MAX_VIRTUAL_HOSTS) {
+ fprintf(errors,"Error on line %d of %s:\n",n,cfg_file);
+ fprintf(errors,"Too many VirtualHost regions.\n");
+ exit(1);
+ }
+
+ virt[x].server_admin = NULL;
+ virt[x].server_hostname = NULL;
+ virt[x].document_root = NULL;
+
+ hep = gethostbyname(virt_host);
+ if (hep && hep->h_addrtype == AF_INET &&
+ hep->h_addr_list[0] && !hep->h_addr_list[1])
+ {
+ memcpy(&virt[x].virt_addr, hep->h_addr_list[0],
+ sizeof(struct in_addr));
+ } else {
+ fprintf(errors,"Syntax error on line %d of %s:\n",n,cfg_file);
+ fprintf(errors,"Argument for VirtualHost must be a numeric IP address,\n"
+ );
+ fprintf(errors,"or a name that maps to exactly one address.\n");
+ exit(1);
+ }
+
+ while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
+ ++n;
+ if((l[0] == '#') || (!l[0])) continue;
+ cfg_getword(w,l);
+
+ if(!strcasecmp(w,"ServerAdmin")) {
+ cfg_getword(w,l);
+ if(!(virt[x].server_admin = strdup(w)))
+ die(NO_MEMORY,"parse_virtual_host",errors);
+ }
+ else if(!strcasecmp(w,"ServerName")) {
+ cfg_getword(w,l);
+ if(!(virt[x].server_hostname = strdup(w)))
+ die(NO_MEMORY,"parse_virtual_host",errors);
+ }
+ else if(!strcasecmp(w,"DocumentRoot")) {
+ cfg_getword(w,l);
+ if(!(virt[x].document_root = strdup(w)))
+ die(NO_MEMORY,"parse_virtual_host",errors);
+ }
+ else if(!strcasecmp(w,"</VirtualHost>"))
+ break;
+ else {
+ fprintf(errors,"Syntax error on line %d of %s:\n",n,cfg_file);
+ fprintf(errors,"Unknown keyword %s in VirtualHost region.\n",w);
+ exit(1);
+ }
+ }
+ ++num_virt;
+ return n;
+ }
+ #endif /* APB_VIRTUAL_HOST */
+
void process_server_config(FILE *errors) {
FILE *cfg;
char l[MAX_STRING_LEN],w[MAX_STRING_LEN];
***************
*** 62,67 ****
--- 141,149 ----
standalone = 1;
port = DEFAULT_PORT;
+ #ifdef APB_BIND_ADDRESS
+ bind_address.s_addr = htonl(INADDR_ANY);
+ #endif /* APB_BIND_ADDRESS */
user_id = uname2id(DEFAULT_USER);
group_id = gname2id(DEFAULT_GROUP);
***************
*** 90,95 ****
--- 172,180 ----
timeout = DEFAULT_TIMEOUT;
do_rfc931 = DEFAULT_RFC931;
+ #ifdef APB_VIRTUAL_HOST
+ num_virt = 0;
+ #endif /* APB_VIRTUAL_HOST */
if(!(cfg = fopen(server_confname,"r"))) {
fprintf(errors,"httpd: could not open server config. file %s\n",server_confname);
***************
*** 114,119 ****
--- 199,226 ----
cfg_getword(w,l);
port = atoi(w);
}
+ #ifdef APB_BIND_ADDRESS
+ else if(!strcasecmp(w,"BindAddress")) {
+ struct hostent *hep;
+ cfg_getword(w,l);
+ if (!strcmp(w, "*")) {
+ bind_address.s_addr = htonl(INADDR_ANY);
+ } else {
+ hep = gethostbyname(w);
+ if (hep && hep->h_addrtype == AF_INET &&
+ hep->h_addr_list[0] && !hep->h_addr_list[1])
+ {
+ memcpy(&bind_address, hep->h_addr_list[0],
+ sizeof(struct in_addr));
+ } else {
+ fprintf(errors,"Syntax error on line %d of %s:\n",n,server_confname);
+ fprintf(errors,"BindAddress must be \"*\", or a numeric IP address,\n");
+ fprintf(errors,"or a name that maps to exactly one address.\n");
+ exit(1);
+ }
+ }
+ }
+ #endif /* APB_BIND_ADDRESS */
else if(!strcasecmp(w,"User")) {
cfg_getword(w,l);
user_id = uname2id(w);
***************
*** 236,241 ****
--- 343,354 ----
fprintf(errors,"This compile doesn't support StartServers on line %d of %s:\n",n,server_confname);
#endif
}
+ #ifdef APB_VIRTUAL_HOST
+ else if(!strcasecmp(w,"<VirtualHost")) {
+ getword(w,l,'>');
+ n=parse_virtual_host(cfg,n,w,server_confname,errors);
+ }
+ #endif /* APB_VIRTUAL_HOST */
else {
fprintf(errors,"Syntax error on line %d of %s:\n",n,server_confname);
fprintf(errors,"Unknown keyword %s.\n",w);
***************
*** 547,552 ****
--- 660,670 ----
x = num_sec;
+ if (x >= MAX_SECURITY) {
+ access_syntax_error(n,
+ "Too many Directory regions.",file,out);
+ }
+
sec[x].opts=OPT_UNSET;
sec[x].override = or;
if(!(sec[x].d = (char *)malloc((sizeof(char)) * (strlen(dir) + 2))))
***************
*** 1051,1053 ****
--- 1169,1217 ----
process_resource_config(errors);
process_access_config(errors);
}
+
+
+ #ifdef APB_VIRTUAL_HOST
+ /* Check whether the specified hostaddr is one of the virtual host addresses
+ * that we want to treat specially, and if so, then override selected config
+ * variables.
+ */
+ void use_virtual_host_config(struct in_addr hostaddr, FILE *out) {
+ int x;
+
+ for (x=0; x<num_virt && x<MAX_VIRTUAL_HOSTS; x++) {
+ if (virt[x].virt_addr.s_addr == hostaddr.s_addr) {
+ if (virt[x].server_admin) {
+ strcpy(server_admin, virt[x].server_admin);
+ }
+ if (virt[x].server_hostname) {
+ if(server_hostname)
+ free(server_hostname);
+ if(!(server_hostname = strdup(virt[x].server_hostname)))
+ die(NO_MEMORY,"use_virtual_host_config",out);
+ }
+ if (virt[x].document_root) {
+ strcpy(document_root, virt[x].document_root);
+ }
+ break;
+ }
+ }
+ }
+ #endif /* APB_VIRTUAL_HOST */
+
+ #ifdef APB_VIRTUAL_HOST
+ /* Remove virtual host configuration */
+ void kill_virtual_host_config() {
+ int x;
+
+ for (x=0; x<num_virt && x<MAX_VIRTUAL_HOSTS; x++) {
+ if (virt[x].server_admin)
+ free(virt[x].server_admin);
+ if (virt[x].server_hostname)
+ free(virt[x].server_hostname);
+ if (virt[x].document_root)
+ free(virt[x].document_root);
+ }
+ num_virt = 0;
+ }
+ #endif /* APB_VIRTUAL_HOST */
diff -c src-orig/http_log.c src/http_log.c
*** src-orig/http_log.c Fri Sep 1 12:29:14 1995
--- src/http_log.c Fri Sep 1 14:00:43 1995
***************
*** 151,157 ****
timz = -timz;
strftime(tstr,MAX_STRING_LEN,"%d/%b/%Y:%H:%M:%S",t);
! sprintf(str,"%s %s %s [%s %c%02d%02d] \"%s\" ",
remote_name,
(do_rfc931 ? remote_logname : "-"),
(user[0] ? user : "-"),
--- 151,157 ----
timz = -timz;
strftime(tstr,MAX_STRING_LEN,"%d/%b/%Y:%H:%M:%S",t);
! sprintf(str,"%s %s %s [%s %c%02d%02d] ",
remote_name,
(do_rfc931 ? remote_logname : "-"),
(user[0] ? user : "-"),
***************
*** 158,165 ****
tstr,
sign,
timz/3600,
! timz%3600,
! the_request);
if(status != -1)
sprintf(str,"%s%d ",str,status);
else
--- 158,172 ----
tstr,
sign,
timz/3600,
! timz%3600);
! #ifdef APB_VIRTUAL_HOST
! if(num_virt > 0) {
! strcat(str,server_hostname);
! strcat(str," ");
! }
! #endif /* APB_VIRTUAL_HOST */
! sprintf(str,"%s\"%s\" ",str,the_request);
!
if(status != -1)
sprintf(str,"%s%d ",str,status);
else
diff -c src-orig/http_request.c src/http_request.c
*** src-orig/http_request.c Fri Sep 1 12:29:15 1995
--- src/http_request.c Fri Sep 1 14:05:19 1995
***************
*** 185,190 ****
--- 185,193 ----
get_remote_host(in);
signal(SIGPIPE,send_fd_timed_out);
+ #ifdef APB_VIRTUAL_HOST
+ use_virtual_host_config(get_local_addr(in,out), out);
+ #endif /* APB_VIRTUAL_HOST */
if(getline(as_requested,HUGE_STRING_LEN,in,timeout))
return;
diff -c src-orig/httpd.c src/httpd.c
*** src-orig/httpd.c Fri Sep 1 12:29:15 1995
--- src/httpd.c Fri Sep 1 14:07:23 1995
***************
*** 207,212 ****
--- 207,215 ----
kill_mime();
kill_security();
kill_indexing();
+ #ifdef APB_VIRTUAL_HOST
+ kill_virtual_host_config();
+ #endif /* APB_VIRTUAL_HOST */
#ifndef NO_PASS
for(x=0;x<num_children;x++) {
***************
*** 482,491 ****
bzero((char *) &sa_server, sizeof(sa_server));
sa_server.sin_family=AF_INET;
sa_server.sin_addr.s_addr=htonl(INADDR_ANY);
sa_server.sin_port=htons(port);
if(bind(sd,(struct sockaddr *) &sa_server,sizeof(sa_server)) == -1) {
! fprintf(stderr,"httpd: could not bind to port %d\n",port);
perror("bind");
exit(1);
}
--- 485,505 ----
bzero((char *) &sa_server, sizeof(sa_server));
sa_server.sin_family=AF_INET;
+ #ifdef APB_BIND_ADDRESS
+ sa_server.sin_addr=bind_address;
+ #else /* APB_BIND_ADDRESS */
sa_server.sin_addr.s_addr=htonl(INADDR_ANY);
+ #endif /* APB_BIND_ADDRESS */
sa_server.sin_port=htons(port);
if(bind(sd,(struct sockaddr *) &sa_server,sizeof(sa_server)) == -1) {
! #ifdef APB_BIND_ADDRESS
! if (bind_address.s_addr != htonl(INADDR_ANY))
! fprintf(stderr,"httpd: could not bind to address %s port %d\n",
! inet_ntoa(bind_address), port);
! else
! #endif /* APB_BIND_ADDRESS */
! fprintf(stderr,"httpd: could not bind to port %d\n",port);
!
perror("bind");
exit(1);
}
diff -c src-orig/httpd.h src/httpd.h
*** src-orig/httpd.h Fri Sep 1 12:29:15 1995
--- src/httpd.h Fri Sep 1 14:10:30 1995
***************
*** 352,357 ****
--- 352,362 ----
/* Max. number of security defines */
#define MAX_SECURITY 50
+ #ifdef APB_VIRTUAL_HOST
+ /* Max. number of virtual hosts */
+ #define MAX_VIRTUAL_HOSTS 20
+ #endif /* APB_VIRTUAL_HOST */
+
/* Default administrator's address */
#define DEFAULT_ADMIN "[no address given]"
***************
*** 574,584 ****
--- 579,610 ----
char *deny[METHODS][MAX_SECURITY];
} security_data;
+ #ifdef APB_VIRTUAL_HOST
+ /* Data that is kept separate for each virtual host running on a
+ * physical host. */
+ typedef struct {
+ /* The address to which this data applies */
+ struct in_addr virt_addr;
+ /* Stuff that usually comes from the server config file */
+ /* Note that server_root is deliberately excluded here,
+ * because lots of stuff that depends on server_root
+ * is done before we know which virtual host is to be used.
+ */
+ char *server_admin;
+ char *server_hostname;
+ /* Stuff that usually comes from the document config file */
+ char *document_root;
+ } virtual_host_data;
+ #endif /* APB_VIRTUAL_HOST */
+
/* Global, global, who's got the globals? */
/* Server config */
extern int standalone;
extern int port;
+ #ifdef APB_BIND_ADDRESS
+ extern struct in_addr bind_address;
+ #endif /* APB_BIND_ADDRESS */
extern uid_t user_id;
extern gid_t group_id;
extern char server_root[MAX_STRING_LEN];
***************
*** 611,616 ****
--- 637,648 ----
extern int fancy_indexing;
extern char readme_fname[MAX_STRING_LEN];
+ #ifdef APB_VIRTUAL_HOST
+ /* Virtual host config */
+ extern int num_virt;
+ extern virtual_host_data virt[MAX_VIRTUAL_HOSTS];
+ #endif /* APB_VIRTUAL_HOST */
+
/* Security config */
extern int num_sec;
extern security_data sec[MAX_SECURITY];
***************
*** 654,659 ****
--- 686,693 ----
/* http_config */
void read_config();
void parse_htaccess(char *dir, char override, FILE *out);
+ void use_virtual_host_config(struct in_addr hostaddr, FILE *out);
+ void kill_virtual_host_config();
int get_pw(char *user, char *pw, FILE *errors);
int in_group(char *user, char *group);
int init_group(char *grpfile, FILE *out);
***************
*** 813,818 ****
--- 847,853 ----
void construct_url(char *d, char *s);
void get_local_host();
int get_portnum(int sd,FILE *out);
+ struct in_addr get_local_addr(int sd,FILE *out);
int can_exec(struct stat *finfo);
#ifdef NEED_INITGROUPS
int initgroups(const char *name, gid_t basegid);
diff -c src-orig/util.c src/util.c
*** src-orig/util.c Fri Sep 1 12:29:16 1995
--- src/util.c Fri Sep 1 14:10:57 1995
***************
*** 980,985 ****
--- 980,998 ----
return ntohs(((struct sockaddr_in *)&addr)->sin_port);
}
+ #ifdef APB_VIRTUAL_HOST
+ struct in_addr get_local_addr(int sd,FILE *out) {
+ struct sockaddr addr;
+ int len;
+
+ len = sizeof(struct sockaddr);
+ if(getsockname(sd,&addr,&len) < 0)
+ die(SERVER_ERROR,"could not get local address",out);
+ return ((struct sockaddr_in *)&addr)->sin_addr;
+ }
+ #endif /* APB_VIRTUAL_HOST */
+
+
char *find_fqdn(struct hostent *p) {
int x;