VirtualHost patch for NCSA httpd 1.4.2

VirtualHost patch for NCSA httpd 1.4.2

Post by Paul Philli » Sat, 16 Sep 1995 04:00:00



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;

 
 
 

1. NCSA httpd: BindAddress and VirtualHosting

Is it possible to not bind to * and still use virtual
hosting?

A user wants Microsoft's Frontpage extensions installed.
They only support up to 1.5, not 1.5.2. For various reasons
I do _not_ want to back up versions. MS's solution suggests
upgrading to Apache, which isn't very feasible right now. So my
solution, which is theoretically possible, is to put up another
server, Apache, and have it bind to a different ip on port
80.

Apache is setup correctly to bind only to 128.196.139.69.

The end of my httpd.conf file is:

#BindAddress 128.196.

<VirtualHost 128.196.139.65>
ServerName w3.arizona.edu
ResourceConfig conf/srm.conf
</VirtualHost>

<VirtualHost 128.196.139.66>
ServerName wildcat.arizona.edu
ResourceConfig conf/wildcat_srm.conf
TransferLog logs/wildcat_access_log
</VirtualHost>

<VirtualHost 128.196.139.67>
ServerName www.openair.org
ResourceConfig conf/openair_srm.conf
TransferLog logs/openair_access_log

</VirtualHost>

<VirtualHost 128.196.139.68>
ServerName www.cesl.arizona.edu
ResourceConfig conf/cesl_srm.conf
TransferLog logs/access_log

</VirtualHost>

However, the server still appears to claim all IP addresses,
because on starting Apache I get

bind: Address already in use
httpd: could not bind to address 128.196.139.69 port 80

Any suggestions to work this out would be greatly
appreciated.

Thanks,
Brett

--
Brett Bendickson - UAInfo Web Team

2. Putting LILO on a boot diskette

3. VirtualHost Directive with NCSA httpd 1.5

4. shell access restriction

5. Setup VirtualHost and httpd processes for each VirtualHost

6. Linux JDK 1.2.2 - Font specified in font.properties not found

7. Default httpd.conf says Expected </VirtualHost> but saw </VirtualHost>

8. Test Only. Please ignore

9. VirtualHost patch for NCSA httpd1.4?

10. NCSA httpd & server-push - a patch

11. NCSA httpd 1.5a patch for Linux 1.3.100

12. NIS/YP patch for NCSA httpd 1.3, 1.4

13. Where is patch to NCSA httpd 1.4.2 to allow virtual hosts?