00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
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
00097 unlink(sock_name);
00098
00099 debug(LOG_DEBUG, "Filling sockaddr_un");
00100 strcpy(sa_un.sun_path, sock_name);
00101
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
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
00156 read_bytes = 0;
00157 done = 0;
00158 memset(request, 0, sizeof(request));
00159
00160
00161 while (!done && read_bytes < (sizeof(request) - 1)) {
00162 len = read(fd, request + read_bytes,
00163 sizeof(request) - read_bytes);
00164
00165
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
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
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
00248
00249
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 }