00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <syslog.h>
00032 #include <pthread.h>
00033 #include <signal.h>
00034 #include <errno.h>
00035 #include <time.h>
00036 
00037 
00038 #include <sys/types.h>
00039 #include <unistd.h>
00040 
00041 
00042 #include <string.h>
00043 
00044 
00045 #include <sys/wait.h>
00046 
00047 #include "httpd.h"
00048 #include "safe.h"
00049 #include "debug.h"
00050 #include "conf.h"
00051 #include "gateway.h"
00052 #include "firewall.h"
00053 #include "commandline.h"
00054 #include "auth.h"
00055 #include "http.h"
00056 #include "client_list.h"
00057 #include "wdctl_thread.h"
00058 #include "ping_thread.h"
00059 #include "httpd_thread.h"
00060 #include "util.h"
00061 
00066 static pthread_t tid_fw_counter = 0;
00067 static pthread_t tid_ping = 0; 
00068 
00076 void
00077 sigchld_handler(int s)
00078 {
00079         int     status;
00080         
00081         wait(&status);
00082 }
00083 
00086 void
00087 termination_handler(int s)
00088 {
00089         static  pthread_mutex_t sigterm_mutex = PTHREAD_MUTEX_INITIALIZER;
00090 
00091         debug(LOG_INFO, "Caught signal %d", s);
00092 
00093         
00094         if (pthread_mutex_trylock(&sigterm_mutex)) {
00095                 debug(LOG_INFO, "Another thread already began global termination handler. I'm exiting");
00096                 pthread_exit(NULL);
00097         }
00098         else {
00099                 debug(LOG_INFO, "Cleaning up and exiting");
00100         }
00101 
00102         debug(LOG_DEBUG, "Flushing firewall rules...");
00103         fw_destroy();
00104 
00105         
00106 
00107 
00108 
00109         if (tid_fw_counter) {
00110                 debug(LOG_INFO, "Explicitly killing the fw_counter thread");
00111                 pthread_kill(tid_fw_counter, SIGKILL);
00112         }
00113         if (tid_ping) {
00114                 debug(LOG_INFO, "Explicitly killing the ping thread");
00115                 pthread_kill(tid_ping, SIGKILL);
00116         }
00117 
00118         debug(LOG_DEBUG, "Exiting...");
00119         exit(s == 0 ? 1 : 0);
00120 }
00121 
00125 static void
00126 init_signals(void)
00127 {
00128         struct sigaction sa;
00129 
00130         debug(LOG_DEBUG, "Initializing signal handlers");
00131         
00132         sa.sa_handler = sigchld_handler;
00133         sigemptyset(&sa.sa_mask);
00134         sa.sa_flags = SA_RESTART;
00135         if (sigaction(SIGCHLD, &sa, NULL) == -1) {
00136                 debug(LOG_ERR, "sigaction(): %s", strerror(errno));
00137                 exit(1);
00138         }
00139 
00140         
00141         
00142 
00143 
00144 
00145 
00146         sa.sa_handler = SIG_IGN;
00147         if (sigaction(SIGPIPE, &sa, NULL) == -1) {
00148                 debug(LOG_ERR, "sigaction(): %s", strerror(errno));
00149                 exit(1);
00150         }
00151 
00152         sa.sa_handler = termination_handler;
00153         sigemptyset(&sa.sa_mask);
00154         sa.sa_flags = SA_RESTART;
00155 
00156         
00157         if (sigaction(SIGTERM, &sa, NULL) == -1) {
00158                 debug(LOG_ERR, "sigaction(): %s", strerror(errno));
00159                 exit(1);
00160         }
00161 
00162         
00163         if (sigaction(SIGQUIT, &sa, NULL) == -1) {
00164                 debug(LOG_ERR, "sigaction(): %s", strerror(errno));
00165                 exit(1);
00166         }
00167 
00168         
00169         if (sigaction(SIGINT, &sa, NULL) == -1) {
00170                 debug(LOG_ERR, "sigaction(): %s", strerror(errno));
00171                 exit(1);
00172         }
00173 }
00174 
00178 static void
00179 main_loop(void)
00180 {
00181         httpd * webserver;
00182         int result;
00183         pthread_t       tid;
00184         s_config *config = config_get_config();
00185         request *r;
00186         void **params;
00187 
00188         
00189         client_list_init();
00190 
00191     
00192     if (!config->gw_address) {
00193         debug(LOG_DEBUG, "Finding IP address of %s", config->gw_interface);
00194         if ((config->gw_address = get_iface_ip(config->gw_interface)) == NULL) {
00195                     debug(LOG_ERR, "Could not get IP address information of %s, exiting...", config->gw_interface);
00196             exit(1);
00197         }
00198         debug(LOG_DEBUG, "%s = %s", config->gw_interface, config->gw_address);
00199     }
00200 
00201         
00202         debug(LOG_NOTICE, "Creating web server on %s:%d", 
00203                         config->gw_address, config->gw_port);
00204         webserver = httpdCreate(config->gw_address, config->gw_port);
00205         if (webserver == NULL) {
00206                 debug(LOG_ERR, "Could not create web server: %s",
00207                                 strerror(errno));
00208                 exit(1);
00209         }
00210         debug(LOG_DEBUG, "Assigning callbacks to web server");
00211         httpdAddCContent(webserver, "/", "wifidog", 0, NULL, http_callback_wifidog);
00212         httpdAddCContent(webserver, "/wifidog", "", 0, NULL, http_callback_wifidog);
00213         httpdAddCContent(webserver, "/wifidog", "about", 0, NULL, http_callback_about);
00214         httpdAddCContent(webserver, "/wifidog", "status", 0, NULL, http_callback_status);
00215         httpdAddCContent(webserver, "/wifidog", "auth", 0, NULL, http_callback_auth);
00216         httpdAddC404Content(webserver, http_callback_404);
00217 
00218         
00219         init_signals();
00220 
00221         
00222         fw_destroy();
00223         fw_init();
00224 
00225         
00226         result = pthread_create(&tid_fw_counter, NULL, (void *)thread_client_timeout_check, NULL);
00227         if (result != 0) {
00228                 debug(LOG_ERR, "FATAL: Failed to create a new thread (fw_counter) - exiting");
00229                 termination_handler(0);
00230         }
00231         pthread_detach(tid_fw_counter);
00232 
00233         
00234         result = pthread_create(&tid, NULL, (void *)thread_wdctl, (void *)safe_strdup(config->wdctl_sock));
00235         if (result != 0) {
00236                 debug(LOG_ERR, "FATAL: Failed to create a new thread (wdctl) - exiting");
00237                 termination_handler(0);
00238         }
00239         pthread_detach(tid);
00240         
00241         
00242         result = pthread_create(&tid_ping, NULL, (void *)thread_ping, NULL);
00243         if (result != 0) {
00244                 debug(LOG_ERR, "FATAL: Failed to create a new thread (ping) - exiting");
00245                 termination_handler(0);
00246         }
00247         pthread_detach(tid_ping);
00248         
00249         debug(LOG_NOTICE, "Waiting for connections");
00250         while(1) {
00251                 r = httpdGetConnection(webserver, NULL);
00252 
00253                 
00254 
00255                 if (webserver->lastError == -1) {
00256                         
00257                         continue; 
00258                 }
00259                 else if (webserver->lastError < -1) {
00260                         
00261 
00262 
00263 
00264 
00265                         debug(LOG_ERR, "FATAL: httpdGetConnection returned unexpected value %d, exiting.", webserver->lastError);
00266                         termination_handler(0);
00267                 }
00268                 else if (r != NULL) {
00269                         
00270 
00271 
00272 
00273 
00274                         debug(LOG_INFO, "Received connection from %s, spawning worker thread", r->clientAddr);
00275                         
00276 
00277                         params = safe_malloc(2 * sizeof(void *));
00278                         *params = webserver;
00279                         *(params + 1) = r;
00280 
00281                         result = pthread_create(&tid, NULL, (void *)thread_httpd, (void *)params);
00282                         if (result != 0) {
00283                                 debug(LOG_ERR, "FATAL: Failed to create a new thread (httpd) - exiting");
00284                                 termination_handler(0);
00285                         }
00286                         pthread_detach(tid);
00287                 }
00288                 else {
00289                         
00290                         
00291 
00292                 }
00293         }
00294 
00295         
00296 }
00297 
00299 int
00300 main(int argc, char **argv)
00301 {
00302         s_config *config = config_get_config();
00303         config_init();
00304 
00305         parse_commandline(argc, argv);
00306 
00307         config_read(config->configfile);
00308         config_validate();
00309 
00310         if (config->daemon) {
00311 
00312                 debug(LOG_INFO, "Forking into background");
00313 
00314                 switch(fork()) {
00315                 case -1: 
00316                         debug(LOG_ERR, "fork(): %s", strerror(errno));
00317                         exit(1);
00318                         break;
00319 
00320                 case 0: 
00321                         main_loop();
00322                         break;
00323 
00324                 default: 
00325                         exit(0);
00326                         break;
00327                 }
00328         } else {
00329                 main_loop();
00330         }
00331 
00332         return(0); 
00333 }