📄 gateway.c.svn-base
字号:
/********************************************************************\ * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free:Software Foundation; either version 2 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License* * along with this program; if not, contact: * * * * Free Software Foundation Voice: +1-617-542-5942 * * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 * * Boston, MA 02111-1307, USA gnu@gnu.org * * * \********************************************************************//* $Id$ *//** @internal @file gateway.c @brief Main loop @author Copyright (C) 2004 Philippe April <papril777@yahoo.com> @author Copyright (C) 2004 Alexandre Carmel-Veilleux <acv@miniguru.ca> */#include <stdio.h>#include <stdlib.h>#include <syslog.h>#include <pthread.h>#include <signal.h>#include <errno.h>#include <time.h>/* for strerror() */#include <string.h>/* for wait() */#include <sys/wait.h>/* for unix socket communication*/#include <sys/socket.h>#include <sys/un.h>#include "common.h"#include "httpd.h"#include "safe.h"#include "debug.h"#include "conf.h"#include "gateway.h"#include "firewall.h"#include "commandline.h"#include "auth.h"#include "http.h"#include "client_list.h"#include "wdctl_thread.h"#include "ping_thread.h"#include "httpd_thread.h"#include "util.h"/** XXX Ugly hack * We need to remember the thread IDs of threads that simulate wait with pthread_cond_timedwait * so we can explicitly kill them in the termination handler */static pthread_t tid_fw_counter = 0;static pthread_t tid_ping = 0; /* The internal web server */httpd * webserver = NULL;/* from commandline.c */extern char ** restartargv;extern pid_t restart_orig_pid;t_client *firstclient;/* from client_list.c */extern pthread_mutex_t client_list_mutex;/* Time when wifidog started */time_t started_time = 0;/* Appends -x, the current PID, and NULL to restartargv * see parse_commandline in commandline.c for details * * Why is restartargv global? Shouldn't it be at most static to commandline.c * and this function static there? -Alex @ 8oct2006 */void append_x_restartargv(void) { int i; for (i=0; restartargv[i]; i++); restartargv[i++] = safe_strdup("-x"); safe_asprintf(&(restartargv[i++]), "%d", getpid());}/* @internal * @brief During gateway restart, connects to the parent process via the internal socket * Downloads from it the active client list */void get_clients_from_parent(void) { int sock; struct sockaddr_un sa_un; s_config * config = NULL; char linebuffer[MAX_BUF]; int len = 0; char *running1 = NULL; char *running2 = NULL; char *token1 = NULL; char *token2 = NULL; char onechar; char *command = NULL; char *key = NULL; char *value = NULL; t_client * client = NULL; t_client * lastclient = NULL; config = config_get_config(); debug(LOG_INFO, "Connecting to parent to download clients"); /* Connect to socket */ sock = socket(AF_UNIX, SOCK_STREAM, 0); memset(&sa_un, 0, sizeof(sa_un)); sa_un.sun_family = AF_UNIX; strncpy(sa_un.sun_path, config->internal_sock, (sizeof(sa_un.sun_path) - 1)); if (connect(sock, (struct sockaddr *)&sa_un, strlen(sa_un.sun_path) + sizeof(sa_un.sun_family))) { debug(LOG_ERR, "Failed to connect to parent (%s) - client list not downloaded", strerror(errno)); return; } debug(LOG_INFO, "Connected to parent. Downloading clients"); LOCK_CLIENT_LIST(); command = NULL; memset(linebuffer, 0, sizeof(linebuffer)); len = 0; client = NULL; /* Get line by line */ while (read(sock, &onechar, 1) == 1) { if (onechar == '\n') { /* End of line */ onechar = '\0'; } linebuffer[len++] = onechar; if (!onechar) { /* We have a complete entry in linebuffer - parse it */ debug(LOG_DEBUG, "Received from parent: [%s]", linebuffer); running1 = linebuffer; while ((token1 = strsep(&running1, "|")) != NULL) { if (!command) { /* The first token is the command */ command = token1; } else { /* Token1 has something like "foo=bar" */ running2 = token1; key = value = NULL; while ((token2 = strsep(&running2, "=")) != NULL) { if (!key) { key = token2; } else if (!value) { value = token2; } } } if (strcmp(command, "CLIENT") == 0) { /* This line has info about a client in the client list */ if (!client) { /* Create a new client struct */ client = safe_malloc(sizeof(t_client)); memset(client, 0, sizeof(t_client)); } } if (key && value) { if (strcmp(command, "CLIENT") == 0) { /* Assign the key into the appropriate slot in the connection structure */ if (strcmp(key, "ip") == 0) { client->ip = safe_strdup(value); } else if (strcmp(key, "mac") == 0) { client->mac = safe_strdup(value); } else if (strcmp(key, "token") == 0) { client->token = safe_strdup(value); } else if (strcmp(key, "fw_connection_state") == 0) { client->fw_connection_state = atoi(value); } else if (strcmp(key, "fd") == 0) { client->fd = atoi(value); } else if (strcmp(key, "counters_incoming") == 0) { client->counters.incoming_history = atoll(value); client->counters.incoming = client->counters.incoming_history; } else if (strcmp(key, "counters_outgoing") == 0) { client->counters.outgoing_history = atoll(value); client->counters.outgoing = client->counters.outgoing_history; } else if (strcmp(key, "counters_last_updated") == 0) { client->counters.last_updated = atol(value); } else { debug(LOG_NOTICE, "I don't know how to inherit key [%s] value [%s] from parent", key, value); } } } } /* End of parsing this command */ if (client) { /* Add this client to the client list */ if (!firstclient) { firstclient = client; lastclient = firstclient; } else { lastclient->next = client; lastclient = client; } } /* Clean up */ command = NULL; memset(linebuffer, 0, sizeof(linebuffer)); len = 0; client = NULL; } } UNLOCK_CLIENT_LIST(); debug(LOG_INFO, "Client list downloaded successfully from parent"); close(sock);}/**@internal * @brief Handles SIGCHLD signals to avoid zombie processes * * When a child process exits, it causes a SIGCHLD to be sent to the * process. This handler catches it and reaps the child process so it * can exit. Otherwise we'd get zombie processes. */voidsigchld_handler(int s){ int status; pid_t rc; debug(LOG_DEBUG, "Handler for SIGCHLD called. Trying to reap a child"); rc = waitpid(-1, &status, WNOHANG); debug(LOG_DEBUG, "Handler for SIGCHLD reaped child PID %d", rc);}/** Exits cleanly after cleaning up the firewall. * Use this function anytime you need to exit after firewall initialization */voidtermination_handler(int s){ static pthread_mutex_t sigterm_mutex = PTHREAD_MUTEX_INITIALIZER; s_config *config = config_get_config(); debug(LOG_INFO, "Handler for termination caught signal %d", s); /* Makes sure we only call fw_destroy() once. */ if (pthread_mutex_trylock(&sigterm_mutex)) { debug(LOG_INFO, "Another thread already began global termination handler. I'm exiting");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -