📄 gateway.c.svn-base
字号:
pthread_exit(NULL); } else { debug(LOG_INFO, "Cleaning up and exiting"); } debug(LOG_INFO, "Flushing firewall rules..."); fw_destroy(); /* XXX Hack * Aparently pthread_cond_timedwait under openwrt prevents signals (and therefore * termination handler) from happening so we need to explicitly kill the threads * that use that */ if (tid_fw_counter) { debug(LOG_INFO, "Explicitly killing the fw_counter thread"); pthread_kill(tid_fw_counter, SIGKILL); } if (tid_ping) { debug(LOG_INFO, "Explicitly killing the ping thread"); pthread_kill(tid_ping, SIGKILL); } debug(LOG_NOTICE, "Exiting..."); exit(s == 0 ? 1 : 0);}/** @internal * Registers all the signal handlers */static voidinit_signals(void){ struct sigaction sa; debug(LOG_DEBUG, "Initializing signal handlers"); sa.sa_handler = sigchld_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGCHLD, &sa, NULL) == -1) { debug(LOG_ERR, "sigaction(): %s", strerror(errno)); exit(1); } /* Trap SIGPIPE */ /* This is done so that when libhttpd does a socket operation on * a disconnected socket (i.e.: Broken Pipes) we catch the signal * and do nothing. The alternative is to exit. SIGPIPE are harmless * if not desirable. */ sa.sa_handler = SIG_IGN; if (sigaction(SIGPIPE, &sa, NULL) == -1) { debug(LOG_ERR, "sigaction(): %s", strerror(errno)); exit(1); } sa.sa_handler = termination_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; /* Trap SIGTERM */ if (sigaction(SIGTERM, &sa, NULL) == -1) { debug(LOG_ERR, "sigaction(): %s", strerror(errno)); exit(1); } /* Trap SIGQUIT */ if (sigaction(SIGQUIT, &sa, NULL) == -1) { debug(LOG_ERR, "sigaction(): %s", strerror(errno)); exit(1); } /* Trap SIGINT */ if (sigaction(SIGINT, &sa, NULL) == -1) { debug(LOG_ERR, "sigaction(): %s", strerror(errno)); exit(1); }}/**@internal * Main execution loop */static voidmain_loop(void){ int result; pthread_t tid; s_config *config = config_get_config(); request *r; void **params; FILE *fh; /* Set the time when wifidog started */ if (!started_time) { debug(LOG_INFO, "Setting started_time"); started_time = time(NULL); } else if (started_time < MINIMUM_STARTED_TIME) { debug(LOG_WARNING, "Detected possible clock skew - re-setting started_time"); started_time = time(NULL); } /* If we don't have the Gateway IP address, get it. Can't fail. */ if (!config->gw_address) { debug(LOG_DEBUG, "Finding IP address of %s", config->gw_interface); if ((config->gw_address = get_iface_ip(config->gw_interface)) == NULL) { debug(LOG_ERR, "Could not get IP address information of %s, exiting...", config->gw_interface); exit(1); } debug(LOG_DEBUG, "%s = %s", config->gw_interface, config->gw_address); } /* If we don't have the Gateway ID, construct it from the internal MAC address. * "Can't fail" so exit() if the impossible happens. */ if (!config->gw_id) { debug(LOG_DEBUG, "Finding MAC address of %s", config->gw_interface); if ((config->gw_id = get_iface_mac(config->gw_interface)) == NULL) { debug(LOG_ERR, "Could not get MAC address information of %s, exiting...", config->gw_interface); exit(1); } debug(LOG_DEBUG, "%s = %s", config->gw_interface, config->gw_id); } /* Initializes the web server */ debug(LOG_NOTICE, "Creating web server on %s:%d", config->gw_address, config->gw_port); if ((webserver = httpdCreate(config->gw_address, config->gw_port)) == NULL) { debug(LOG_ERR, "Could not create web server: %s", strerror(errno)); exit(1); } debug(LOG_DEBUG, "Assigning callbacks to web server"); httpdAddCContent(webserver, "/", "wifidog", 0, NULL, http_callback_wifidog); httpdAddCContent(webserver, "/wifidog", "", 0, NULL, http_callback_wifidog); httpdAddCContent(webserver, "/wifidog", "about", 0, NULL, http_callback_about); httpdAddCContent(webserver, "/wifidog", "status", 0, NULL, http_callback_status); httpdAddCContent(webserver, "/wifidog", "auth", 0, NULL, http_callback_auth); httpdAddC404Content(webserver, http_callback_404); /* Reset the firewall (if WiFiDog crashed) */ fw_destroy(); /* Then initialize it */ fw_init(); /* Start clean up thread */ result = pthread_create(&tid_fw_counter, NULL, (void *)thread_client_timeout_check, NULL); if (result != 0) { debug(LOG_ERR, "FATAL: Failed to create a new thread (fw_counter) - exiting"); termination_handler(0); } pthread_detach(tid_fw_counter); /* Start control thread */ result = pthread_create(&tid, NULL, (void *)thread_wdctl, (void *)safe_strdup(config->wdctl_sock)); if (result != 0) { debug(LOG_ERR, "FATAL: Failed to create a new thread (wdctl) - exiting"); termination_handler(0); } pthread_detach(tid); /* Start heartbeat thread */ result = pthread_create(&tid_ping, NULL, (void *)thread_ping, NULL); if (result != 0) { debug(LOG_ERR, "FATAL: Failed to create a new thread (ping) - exiting"); termination_handler(0); } pthread_detach(tid_ping); debug(LOG_NOTICE, "Waiting for connections"); while(1) { r = httpdGetConnection(webserver, NULL); /* We can't convert this to a switch because there might be * values that are not -1, 0 or 1. */ if (webserver->lastError == -1) { /* Interrupted system call */ continue; /* restart loop */ } else if (webserver->lastError < -1) { /* * FIXME * An error occurred - should we abort? * reboot the device ? */ debug(LOG_ERR, "FATAL: httpdGetConnection returned unexpected value %d, exiting.", webserver->lastError); termination_handler(0); } else if (r != NULL) { /* * We got a connection * * We should create another thread */ debug(LOG_INFO, "Received connection from %s, spawning worker thread", r->clientAddr); /* The void**'s are a simulation of the normal C * function calling sequence. */ params = safe_malloc(2 * sizeof(void *)); *params = webserver; *(params + 1) = r; result = pthread_create(&tid, NULL, (void *)thread_httpd, (void *)params); if (result != 0) { debug(LOG_ERR, "FATAL: Failed to create a new thread (httpd) - exiting"); termination_handler(0); } pthread_detach(tid); } else { /* webserver->lastError should be 2 */ /* XXX We failed an ACL.... No handling because * we don't set any... */ } } /* never reached */}/** Reads the configuration file and then starts the main loop */int main(int argc, char **argv) { s_config *config = config_get_config(); config_init(); parse_commandline(argc, argv); /* Initialize the config */ config_read(config->configfile); config_validate(); /* Initializes the linked list of connected clients */ client_list_init(); /* Init the signals to catch chld/quit/etc */ init_signals(); if (restart_orig_pid) { /* * We were restarted and our parent is waiting for us to talk to it over the socket */ get_clients_from_parent(); /* * At this point the parent will start destroying itself and the firewall. Let it finish it's job before we continue */ while (kill(restart_orig_pid, 0) != -1) { debug(LOG_INFO, "Waiting for parent PID %d to die before continuing loading", restart_orig_pid); sleep(1); } debug(LOG_INFO, "Parent PID %d seems to be dead. Continuing loading."); } if (config->daemon) { debug(LOG_INFO, "Forking into background"); switch(safe_fork()) { case 0: /* child */ setsid(); append_x_restartargv(); main_loop(); break; default: /* parent */ exit(0); break; } } else { append_x_restartargv(); main_loop(); } return(0); /* never reached */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -