engine.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C), 2000-2002 by Contributors to the monit codebase. 
00003  * All Rights Reserved.
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License as
00007  * published by the Free Software Foundation; either version 2 of the
00008  * License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00018  */
00019 
00020 #include <config.h>
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <errno.h>
00025 
00026 #ifdef HAVE_SYS_TYPES_H
00027 #include <sys/types.h>
00028 #endif
00029 
00030 #include <sys/socket.h>
00031 #include <time.h>
00032 
00033 #ifdef HAVE_NETDB_H
00034 #include <netdb.h>
00035 #endif
00036 
00037 #ifdef HAVE_UNISTD_H
00038 #include <unistd.h>
00039 #endif
00040 
00041 #ifdef HAVE_STRING_H
00042 #include <string.h>
00043 #endif
00044 
00045 #ifdef HAVE_NETINET_IN_H
00046 #include <netinet/in.h>
00047 #endif
00048 
00049 #ifdef HAVE_ARPA_INET_H
00050 #include <arpa/inet.h>
00051 #endif
00052 
00053 #include "http_utils.h" 
00054 #include "engine.h" 
00055 
00056 #define  HOST      1
00057 #define  WRAPPER   2
00058 #define  INETADDR  3
00059 
00060 /* Private variables */
00061 static int myServerSocket= 0;
00062 static volatile int stopped= FALSE;
00063 static HostsAllow hostlist= NULL;
00064 static pthread_mutex_t hostlist_mutex= PTHREAD_MUTEX_INITIALIZER;
00065 
00066 
00067 /* Private prototypes */
00068 static void initialize_service();
00069 static void check_Impl();
00070 static int  authenticate(RequestWrapper);
00071 static int  is_host_allow(char *);
00072 static RequestWrapper socket_producer(int);
00073 static RequestWrapper create_wrapper(struct in_addr, int);
00074 static void destroy_host_allow(HostsAllow);
00075 
00101 /* ------------------------------------------------------------------ Public */
00102 
00103 
00110 void start_httpd(int port, int backlog, char *bindAddr) {
00111 
00112   RequestWrapper W;
00113 
00114   stopped= FALSE;
00115 
00116   
00117   if ( (myServerSocket= create_server_socket(port, backlog, bindAddr)) < 0 ) {
00118     
00119     error("http server: Could not create a server socket at port %d -- %s\n",
00120       port, STRERROR);
00121     
00122     error("monit HTTP server not available\n");
00123     
00124   } else {
00125   
00126     initialize_service();
00127     
00128     while( !stopped ) {
00129       
00130       if ( NULL == (W= socket_producer(myServerSocket)) ) {
00131     
00132     continue;
00133 
00134       }
00135       
00136       if ( (!W->status) || (!authenticate(W)) ) {
00137     
00138     destroy_wrapper(W);
00139     
00140     continue;
00141     
00142       }
00143       
00144       if ( !check_socket(W->socket) ) {
00145     
00146     error("http server: Client socket not ready -- %s\n", STRERROR);
00147     destroy_wrapper(W);
00148     
00149     continue;
00150     
00151       }
00152 
00153       http_processor(W);
00154       
00155     }
00156 
00157   }
00158 
00159 }
00160 
00161 
00165 void stop_httpd() {
00166 
00167   stopped= TRUE;
00168   close_socket(myServerSocket);
00169   
00170 }
00171 
00172 
00173 /* -------------------------------------------------------------- Properties */
00174 
00175 
00181 int add_host_allow(char *name) {
00182 
00183   struct hostent *hp;
00184 
00185   if ( ! (hp= gethostbyname(name)) ) {
00186     
00187     return FALSE;
00188     
00189   } else  {
00190     
00191     HostsAllow h= NEW(h);
00192     
00193     while(*hp->h_addr_list) {
00194 
00195       h->name= xstrdup( inet_ntoa( *(struct in_addr *) *hp->h_addr_list++) );
00196     
00197       LOCK(hostlist_mutex)
00198     
00199       if ( hostlist ) {
00200       
00201         HostsAllow p, n;
00202       
00203         for ( n= p= hostlist; p; n= p, p= p->next) {
00204     
00205       if ( !strcasecmp(p->name, name) ) {
00206       
00207         destroy_host_allow(h);
00208         goto done;
00209       
00210       }
00211     
00212         }
00213       
00214         n->next= h;
00215       
00216       } else {
00217       
00218         hostlist= h;
00219       
00220       }
00221 
00222       done:
00223       END_LOCK;
00224 
00225     }
00226 
00227   }
00228 
00229   return TRUE;
00230 
00231 }
00232 
00233 
00238 int has_hosts_allow() {
00239 
00240   int rv;
00241 
00242   LOCK(hostlist_mutex)
00243       rv= (hostlist != NULL );
00244   END_LOCK;
00245 
00246   return rv;
00247 
00248 }
00249 
00250 
00254 void destroy_hosts_allow() {
00255 
00256   if ( has_hosts_allow() ) {
00257     
00258     LOCK(hostlist_mutex)
00259     destroy_host_allow(hostlist);
00260         hostlist= NULL;
00261     END_LOCK;
00262     
00263   }
00264 
00265 }
00266 
00267 
00268 /* ----------------------------------------------------------------- Private */
00269 
00270 
00277 static void initialize_service() {
00278 
00279   init_service();
00280   check_Impl();
00281 
00282 }
00283 
00284 
00288 static void check_Impl() {
00289 
00290   if ( (Impl.doGet == 0) || (Impl.doPost == 0) ) {
00291     
00292     error("http server: Service Methods not implemented\n");
00293     _exit(1);
00294     
00295   }
00296   
00297 }
00298 
00299 
00306 static int authenticate(RequestWrapper w) {
00307 
00308   if ( is_host_allow(w->inetaddr->remote_host) ) {
00309     
00310     return TRUE;
00311     
00312   } 
00313 
00314   if ( ! has_hosts_allow() && Run.Auth.defined ) {
00315 
00316     return TRUE;
00317 
00318   }
00319   
00320   return FALSE;
00321 
00322 }
00323 
00324 
00325 
00330 static int is_host_allow(char *name) { 
00331 
00332   HostsAllow p;
00333   int rv= FALSE;
00334 
00335   LOCK(hostlist_mutex)
00336   
00337   for ( p= hostlist; p; p= p->next) {
00338 
00339     if ( !strncasecmp(p->name, name, STRLEN) ) {
00340       
00341       rv= TRUE;
00342       break;
00343       
00344     }
00345     
00346   }
00347 
00348   END_LOCK;
00349 
00350   return rv;
00351 
00352 }
00353 
00354 
00355 /* --------------------------------------------------------------- Factories */
00356 
00357 
00363 static RequestWrapper socket_producer(int server) {
00364 
00365   int client;
00366   int len= sizeof(struct sockaddr_in);
00367   struct sockaddr_in in;
00368 
00369   again:
00370   errno= 0;
00371   if ( (client= accept(server, (struct sockaddr*)&in, &len)) < 0) {
00372     
00373     if ( stopped ) {
00374       
00375       log("http server: service stopped\n");
00376       
00377     } else if ( errno == EINTR ) {
00378       
00379       goto again;
00380       
00381     } else {
00382       
00383       error("http server: cannot accept connection -- %s\n", STRERROR);
00384       
00385     }
00386     
00387     return NULL;
00388     
00389   }
00390 
00391   return create_wrapper(in.sin_addr, client);
00392 
00393 }
00394 
00395 
00403 static RequestWrapper create_wrapper(struct in_addr iaddr, int client) {
00404 
00405   RequestWrapper w= NEW(w);
00406   InetAddress i= NEW(i);
00407     
00408   i->remote_host= xstrdup( inet_ntoa(iaddr) );
00409   i->local_host= get_localhostname();
00410   w->inetaddr= i;
00411   w->socket= client;
00412   w->status= TRUE;
00413     
00414   return (w);
00415 
00416 }
00417 
00418 
00419 /* ----------------------------------------------------------------- Cleanup */
00420 
00421 
00425 static void destroy_host_allow(HostsAllow p) {
00426   
00427   HostsAllow a= p; 
00428   
00429   if ( a->next ) {
00430     
00431     destroy_host_allow(a->next);
00432     
00433   }
00434 
00435   free(a->name);
00436   free(a);
00437  
00438 }
00439