⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wdctl_thread.c.svn-base

📁 The Wifidog project is an open source captive portal solution. It was designed primarily for wireles
💻 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$ *//** @file wdctl_thread.c    @brief Monitoring and control of wifidog, server part    @author Copyright (C) 2004 Alexandre Carmel-Veilleux <acv@acv.ca>*/#define _GNU_SOURCE#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <string.h>#include <stdarg.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#include <unistd.h>#include <syslog.h>#include <signal.h>#include <errno.h>#include "common.h"#include "httpd.h"#include "util.h"#include "conf.h"#include "debug.h"#include "auth.h"#include "centralserver.h"#include "fw_iptables.h"#include "firewall.h"#include "client_list.h"#include "wdctl_thread.h"/* Defined in clientlist.c */extern	pthread_mutex_t	client_list_mutex;extern	pthread_mutex_t	config_mutex;/* From commandline.c: */extern char ** restartargv;static void *thread_wdctl_handler(void *);static void wdctl_status(int);static void wdctl_stop(int);static void wdctl_reset(int, char *);static void wdctl_restart(int);/** Launches a thread that monitors the control socket for request@param arg Must contain a pointer to a string containing the Unix domain socket to open@todo This thread loops infinitely, need a watchdog to verify that it is still running?*/  voidthread_wdctl(void *arg){	int	fd;	char	*sock_name;	struct 	sockaddr_un	sa_un;	int result;	pthread_t	tid;	socklen_t len;	debug(LOG_DEBUG, "Starting wdctl.");	memset(&sa_un, 0, sizeof(sa_un));	sock_name = (char *)arg;	debug(LOG_DEBUG, "Socket name: %s", sock_name);	if (strlen(sock_name) > (sizeof(sa_un.sun_path) - 1)) {		/* TODO: Die handler with logging.... */		debug(LOG_ERR, "WDCTL socket name too long");		exit(1);	}		debug(LOG_DEBUG, "Creating socket");	wdctl_socket_server = socket(PF_UNIX, SOCK_STREAM, 0);	debug(LOG_DEBUG, "Got server socket %d", wdctl_socket_server);	/* If it exists, delete... Not the cleanest way to deal. */	unlink(sock_name);	debug(LOG_DEBUG, "Filling sockaddr_un");	strcpy(sa_un.sun_path, sock_name); /* XXX No size check because we					    * check a few lines before. */	sa_un.sun_family = AF_UNIX;		debug(LOG_DEBUG, "Binding socket (%s) (%d)", sa_un.sun_path,			strlen(sock_name));		/* Which to use, AF_UNIX, PF_UNIX, AF_LOCAL, PF_LOCAL? */	if (bind(wdctl_socket_server, (struct sockaddr *)&sa_un, strlen(sock_name) 				+ sizeof(sa_un.sun_family))) {		debug(LOG_ERR, "Could not bind control socket: %s",				strerror(errno));		pthread_exit(NULL);	}	if (listen(wdctl_socket_server, 5)) {		debug(LOG_ERR, "Could not listen on control socket: %s",				strerror(errno));		pthread_exit(NULL);	}	while (1) {		len = sizeof(sa_un); 		memset(&sa_un, 0, len);		if ((fd = accept(wdctl_socket_server, (struct sockaddr *)&sa_un, &len)) == -1){			debug(LOG_ERR, "Accept failed on control socket: %s",					strerror(errno));		} else {			debug(LOG_DEBUG, "Accepted connection on wdctl socket %d (%s)", fd, sa_un.sun_path);			result = pthread_create(&tid, NULL, &thread_wdctl_handler, (void *)fd);			if (result != 0) {				debug(LOG_ERR, "FATAL: Failed to create a new thread (wdctl handler) - exiting");				termination_handler(0);			}			pthread_detach(tid);		}	}}static void *thread_wdctl_handler(void *arg){	int	fd,		done,		i;	char	request[MAX_BUF];	ssize_t	read_bytes,		len;	debug(LOG_DEBUG, "Entering thread_wdctl_handler....");	fd = (int)arg;		debug(LOG_DEBUG, "Read bytes and stuff from %d", fd);	/* Init variables */	read_bytes = 0;	done = 0;	memset(request, 0, sizeof(request));		/* Read.... */	while (!done && read_bytes < (sizeof(request) - 1)) {		len = read(fd, request + read_bytes,				sizeof(request) - read_bytes);		/* Have we gotten a command yet? */		for (i = read_bytes; i < (read_bytes + len); i++) {			if (request[i] == '\r' || request[i] == '\n') {				request[i] = '\0';				done = 1;			}		}				/* Increment position */		read_bytes += len;	}	if (strncmp(request, "status", 6) == 0) {		wdctl_status(fd);	} else if (strncmp(request, "stop", 4) == 0) {		wdctl_stop(fd);	} else if (strncmp(request, "reset", 5) == 0) {		wdctl_reset(fd, (request + 6));	} else if (strncmp(request, "restart", 7) == 0) {		wdctl_restart(fd);	}	if (!done) {		debug(LOG_ERR, "Invalid wdctl request.");		shutdown(fd, 2);		close(fd);		pthread_exit(NULL);	}	debug(LOG_DEBUG, "Request received: [%s]", request);		shutdown(fd, 2);	close(fd);	debug(LOG_DEBUG, "Exiting thread_wdctl_handler....");	return NULL;}static voidwdctl_status(int fd){	char * status = NULL;	int len = 0;	status = get_status_text();	len = strlen(status);	write(fd, status, len);	free(status);}/** A bit of an hack, self kills.... */static voidwdctl_stop(int fd){	pid_t	pid;	pid = getpid();	kill(pid, SIGINT);}static voidwdctl_restart(int afd){	int	sock,		fd;	char	*sock_name;	struct 	sockaddr_un	sa_un;	int result;	s_config * conf = NULL;	t_client * client = NULL;	char * tempstring = NULL;	pid_t pid;	ssize_t written;	socklen_t len;	conf = config_get_config();	debug(LOG_NOTICE, "Will restart myself");	/*	 * First, prepare the internal socket	 */	memset(&sa_un, 0, sizeof(sa_un));	sock_name = conf->internal_sock;	debug(LOG_DEBUG, "Socket name: %s", sock_name);	if (strlen(sock_name) > (sizeof(sa_un.sun_path) - 1)) {		/* TODO: Die handler with logging.... */		debug(LOG_ERR, "INTERNAL socket name too long");		return;	}	debug(LOG_DEBUG, "Creating socket");	sock = socket(PF_UNIX, SOCK_STREAM, 0);	debug(LOG_DEBUG, "Got internal socket %d", sock);	/* If it exists, delete... Not the cleanest way to deal. */	unlink(sock_name);	debug(LOG_DEBUG, "Filling sockaddr_un");	strcpy(sa_un.sun_path, sock_name); /* XXX No size check because we check a few lines before. */	sa_un.sun_family = AF_UNIX;		debug(LOG_DEBUG, "Binding socket (%s) (%d)", sa_un.sun_path, strlen(sock_name));		/* Which to use, AF_UNIX, PF_UNIX, AF_LOCAL, PF_LOCAL? */	if (bind(sock, (struct sockaddr *)&sa_un, strlen(sock_name) + sizeof(sa_un.sun_family))) {		debug(LOG_ERR, "Could not bind internal socket: %s", strerror(errno));		return;	}	if (listen(sock, 5)) {		debug(LOG_ERR, "Could not listen on internal socket: %s", strerror(errno));		return;	}		/*	 * The internal socket is ready, fork and exec ourselves	 */	debug(LOG_DEBUG, "Forking in preparation for exec()...");	pid = safe_fork();	if (pid > 0) {		/* Parent */		/* Wait for the child to connect to our socket :*/		debug(LOG_DEBUG, "Waiting for child to connect on internal socket");		len = sizeof(sa_un);		if ((fd = accept(sock, (struct sockaddr *)&sa_un, &len)) == -1){			debug(LOG_ERR, "Accept failed on internal socket: %s", strerror(errno));			close(sock);			return;		}		close(sock);		debug(LOG_DEBUG, "Received connection from child.  Sending them all existing clients");		/* The child is connected. Send them over the socket the existing clients */		LOCK_CLIENT_LIST();		client = client_get_first_client();		while (client) {			/* Send this client */			safe_asprintf(&tempstring, "CLIENT|ip=%s|mac=%s|token=%s|fw_connection_state=%u|fd=%d|counters_incoming=%llu|counters_outgoing=%llu|counters_last_updated=%lu\n", client->ip, client->mac, client->token, client->fw_connection_state, client->fd, client->counters.incoming, client->counters.outgoing, client->counters.last_updated);			debug(LOG_DEBUG, "Sending to child client data: %s", tempstring);			len = 0;			while (len != strlen(tempstring)) {				written = write(fd, (tempstring + len), strlen(tempstring) - len);				if (written == -1) {					debug(LOG_ERR, "Failed to write client data to child: %s", strerror(errno));					free(tempstring);					break;				}				else {					len += written;				}			}			free(tempstring);			client = client->next;		}		UNLOCK_CLIENT_LIST();		close(fd);		debug(LOG_INFO, "Sent all existing clients to child.  Committing suicide!");		shutdown(afd, 2);		close(afd);		/* Our job in life is done. Commit suicide! */		wdctl_stop(afd);	}	else {		/* Child */		close(wdctl_socket_server);		close(icmp_fd);		close(sock);		shutdown(afd, 2);		close(afd);		debug(LOG_NOTICE, "Re-executing myself (%s)", restartargv[0]);		setsid();		execvp(restartargv[0], restartargv);		/* If we've reached here the exec() failed - die quickly and silently */		debug(LOG_ERR, "I failed to re-execute myself: %s", strerror(errno));		debug(LOG_ERR, "Exiting without cleanup");		exit(1);	}}static voidwdctl_reset(int fd, char *arg){	t_client	*node;	debug(LOG_DEBUG, "Entering wdctl_reset...");		LOCK_CLIENT_LIST();	debug(LOG_DEBUG, "Argument: %s (@%x)", arg, arg);		/* We get the node or return... */	if ((node = client_list_find_by_ip(arg)) != NULL);	else if ((node = client_list_find_by_mac(arg)) != NULL);	else {		debug(LOG_DEBUG, "Client not found.");		UNLOCK_CLIENT_LIST();		write(fd, "No", 2);		return;	}	debug(LOG_DEBUG, "Got node %x.", node);		/* deny.... */	/* TODO: maybe just deleting the connection is not best... But this	 * is a manual command, I don't anticipate it'll be that useful. */	fw_deny(node->ip, node->mac, node->fw_connection_state);	client_list_delete(node);		UNLOCK_CLIENT_LIST();		write(fd, "Yes", 3);		debug(LOG_DEBUG, "Exiting wdctl_reset...");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -