Main Page | Data Structures | Directories | File List | Data Fields

wifidog-1.1.1/src/wdctl_thread.c

00001 /********************************************************************\
00002  * This program is free software; you can redistribute it and/or    *
00003  * modify it under the terms of the GNU General Public License as   *
00004  * published by the Free Software Foundation; either version 2 of   *
00005  * the License, or (at your option) any later version.              *
00006  *                                                                  *
00007  * This program is distributed in the hope that it will be useful,  *
00008  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00009  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00010  * GNU General Public License for more details.                     *
00011  *                                                                  *
00012  * You should have received a copy of the GNU General Public License*
00013  * along with this program; if not, contact:                        *
00014  *                                                                  *
00015  * Free Software Foundation           Voice:  +1-617-542-5942       *
00016  * 59 Temple Place - Suite 330        Fax:    +1-617-542-2652       *
00017  * Boston, MA  02111-1307,  USA       gnu@gnu.org                   *
00018  *                                                                  *
00019 \********************************************************************/
00020 
00021 /* $Header: /cvsroot/wifidog/wifidog/src/wdctl_thread.c,v 1.20 2005/03/07 19:19:38 minaguib Exp $ */
00027 #define _GNU_SOURCE
00028 
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <pthread.h>
00032 #include <string.h>
00033 #include <stdarg.h>
00034 #include <sys/types.h>
00035 #include <sys/socket.h>
00036 #include <sys/un.h>
00037 #include <unistd.h>
00038 #include <syslog.h>
00039 #include <signal.h>
00040 #include <errno.h>
00041 
00042 #include "common.h"
00043 #include "httpd.h"
00044 #include "util.h"
00045 #include "conf.h"
00046 #include "debug.h"
00047 #include "auth.h"
00048 #include "centralserver.h"
00049 #include "fw_iptables.h"
00050 #include "firewall.h"
00051 #include "client_list.h"
00052 #include "wdctl_thread.h"
00053 
00054 /* Defined in clientlist.c */
00055 extern  pthread_mutex_t client_list_mutex;
00056 extern  pthread_mutex_t config_mutex;
00057 
00058 static void *thread_wdctl_handler(void *);
00059 static void wdctl_status(int);
00060 static void wdctl_stop(int);
00061 static void wdctl_reset(int, char *);
00062 
00067 void
00068 thread_wdctl(void *arg)
00069 {
00070         int     sock,
00071                 fd,
00072                 len;
00073         char    *sock_name;
00074         struct  sockaddr_un     sa_un;
00075         int result;
00076         pthread_t       tid;
00077 
00078         debug(LOG_DEBUG, "Starting wdctl.");
00079 
00080         memset(&sa_un, 0, sizeof(sa_un));
00081         sock_name = (char *)arg;
00082         debug(LOG_DEBUG, "Socket name: %s", sock_name);
00083 
00084         if (strlen(sock_name) > (sizeof(sa_un.sun_path) - 1)) {
00085                 /* TODO: Die handler with logging.... */
00086                 debug(LOG_ERR, "WDCTL socket name too long");
00087                 exit(1);
00088         }
00089         
00090 
00091         debug(LOG_DEBUG, "Creating socket");
00092         sock = socket(PF_UNIX, SOCK_STREAM, 0);
00093 
00094         debug(LOG_DEBUG, "Got server socket %d", sock);
00095 
00096         /* If it exists, delete... Not the cleanest way to deal. */
00097         unlink(sock_name);
00098 
00099         debug(LOG_DEBUG, "Filling sockaddr_un");
00100         strcpy(sa_un.sun_path, sock_name); /* XXX No size check because we
00101                                             * check a few lines before. */
00102         sa_un.sun_family = AF_UNIX;
00103         
00104         debug(LOG_DEBUG, "Binding socket (%s) (%d)", sa_un.sun_path,
00105                         strlen(sock_name));
00106         
00107         /* Which to use, AF_UNIX, PF_UNIX, AF_LOCAL, PF_LOCAL? */
00108         if (bind(sock, (struct sockaddr *)&sa_un, strlen(sock_name) 
00109                                 + sizeof(sa_un.sun_family))) {
00110                 debug(LOG_ERR, "Could not bind control socket: %s",
00111                                 strerror(errno));
00112                 pthread_exit(NULL);
00113         }
00114 
00115         if (listen(sock, 5)) {
00116                 debug(LOG_ERR, "Could not listen on control socket: %s",
00117                                 strerror(errno));
00118                 pthread_exit(NULL);
00119         }
00120 
00121         while (1) {
00122                 memset(&sa_un, 0, sizeof(sa_un));
00123                 if ((fd = accept(sock, (struct sockaddr *)&sa_un, &len)) == -1){
00124                         debug(LOG_ERR, "Accept failed on control socket: %s",
00125                                         strerror(errno));
00126                 } else {
00127                         debug(LOG_DEBUG, "Accepted connection on wdctl socket %d (%s)", fd, sa_un.sun_path);
00128                         result = pthread_create(&tid, NULL, &thread_wdctl_handler, (void *)fd);
00129                         if (result != 0) {
00130                                 debug(LOG_ERR, "FATAL: Failed to create a new thread (wdctl handler) - exiting");
00131                                 termination_handler(0);
00132                         }
00133                         pthread_detach(tid);
00134                 }
00135         }
00136 }
00137 
00138 
00139 static void *
00140 thread_wdctl_handler(void *arg)
00141 {
00142         int     fd,
00143                 done,
00144                 i;
00145         char    request[MAX_BUF];
00146         ssize_t read_bytes,
00147                 len;
00148 
00149         debug(LOG_DEBUG, "Entering thread_wdctl_handler....");
00150 
00151         fd = (int)arg;
00152         
00153         debug(LOG_DEBUG, "Read bytes and stuff from %d", fd);
00154 
00155         /* Init variables */
00156         read_bytes = 0;
00157         done = 0;
00158         memset(request, 0, sizeof(request));
00159         
00160         /* Read.... */
00161         while (!done && read_bytes < (sizeof(request) - 1)) {
00162                 len = read(fd, request + read_bytes,
00163                                 sizeof(request) - read_bytes);
00164 
00165                 /* Have we gotten a command yet? */
00166                 for (i = read_bytes; i < (read_bytes + len); i++) {
00167                         if (request[i] == '\r' || request[i] == '\n') {
00168                                 request[i] = '\0';
00169                                 done = 1;
00170                         }
00171                 }
00172                 
00173                 /* Increment position */
00174                 read_bytes += len;
00175         }
00176 
00177         if (strcmp(request, "status") == 0) {
00178                 wdctl_status(fd);
00179         } else if (strcmp(request, "stop") == 0) {
00180                 wdctl_stop(fd);
00181         } else if (strncmp(request, "reset ", 6) == 0) {
00182                 wdctl_reset(fd, (request + 6));
00183         }
00184 
00185         if (!done) {
00186                 debug(LOG_ERR, "Invalid wdctl request.");
00187                 shutdown(fd, 2);
00188                 close(fd);
00189                 pthread_exit(NULL);
00190         }
00191 
00192         debug(LOG_DEBUG, "Request received: [%s]", request);
00193         
00194         shutdown(fd, 2);
00195         close(fd);
00196         debug(LOG_DEBUG, "Exiting thread_wdctl_handler....");
00197 
00198         return NULL;
00199 }
00200 
00201 static void
00202 wdctl_status(int fd)
00203 {
00204         char * status = NULL;
00205         int len = 0;
00206 
00207         status = get_status_text();
00208         len = strlen(status);
00209 
00210         write(fd, status, len);
00211 
00212         free(status);
00213 }
00214 
00216 static void
00217 wdctl_stop(int fd)
00218 {
00219         pid_t   pid;
00220 
00221         pid = getpid();
00222         kill(pid, SIGINT);
00223 }
00224 
00225 static void
00226 wdctl_reset(int fd, char *arg)
00227 {
00228         t_client        *node;
00229 
00230         debug(LOG_DEBUG, "Entering wdctl_reset...");
00231         
00232         LOCK_CLIENT_LIST();
00233         debug(LOG_DEBUG, "Argument: %s (@%x)", arg, arg);
00234         
00235         /* We get the node or return... */
00236         if ((node = client_list_find_by_ip(arg)) != NULL);
00237         else if ((node = client_list_find_by_mac(arg)) != NULL);
00238         else {
00239                 debug(LOG_DEBUG, "Client not found.");
00240                 UNLOCK_CLIENT_LIST();
00241                 write(fd, "No", 2);
00242                 return;
00243         }
00244 
00245         debug(LOG_DEBUG, "Got node %x.", node);
00246         
00247         /* deny.... */
00248         /* TODO: maybe just deleting the connection is not best... But this
00249          * is a manual command, I don't anticipate it'll be that useful. */
00250         fw_deny(node->ip, node->mac, node->fw_connection_state);
00251         client_list_delete(node);
00252         
00253         UNLOCK_CLIENT_LIST();
00254         
00255         write(fd, "Yes", 3);
00256         
00257         debug(LOG_DEBUG, "Exiting wdctl_reset...");
00258 }

Generated on Sun Apr 3 20:04:46 2005 for WifiDog by  doxygen 1.4.1