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
00059 extern char ** restartargv;
00060 static void *thread_wdctl_handler(void *);
00061 static void wdctl_status(int);
00062 static void wdctl_stop(int);
00063 static void wdctl_reset(int, char *);
00064 static void wdctl_restart(int);
00065
00070 void
00071 thread_wdctl(void *arg)
00072 {
00073 int sock,
00074 fd;
00075 char *sock_name;
00076 struct sockaddr_un sa_un;
00077 int result;
00078 pthread_t tid;
00079 socklen_t len;
00080
00081 debug(LOG_DEBUG, "Starting wdctl.");
00082
00083 memset(&sa_un, 0, sizeof(sa_un));
00084 sock_name = (char *)arg;
00085 debug(LOG_DEBUG, "Socket name: %s", sock_name);
00086
00087 if (strlen(sock_name) > (sizeof(sa_un.sun_path) - 1)) {
00088
00089 debug(LOG_ERR, "WDCTL socket name too long");
00090 exit(1);
00091 }
00092
00093
00094 debug(LOG_DEBUG, "Creating socket");
00095 sock = socket(PF_UNIX, SOCK_STREAM, 0);
00096
00097 debug(LOG_DEBUG, "Got server socket %d", sock);
00098
00099
00100 unlink(sock_name);
00101
00102 debug(LOG_DEBUG, "Filling sockaddr_un");
00103 strcpy(sa_un.sun_path, sock_name);
00104
00105 sa_un.sun_family = AF_UNIX;
00106
00107 debug(LOG_DEBUG, "Binding socket (%s) (%d)", sa_un.sun_path,
00108 strlen(sock_name));
00109
00110
00111 if (bind(sock, (struct sockaddr *)&sa_un, strlen(sock_name)
00112 + sizeof(sa_un.sun_family))) {
00113 debug(LOG_ERR, "Could not bind control socket: %s",
00114 strerror(errno));
00115 pthread_exit(NULL);
00116 }
00117
00118 if (listen(sock, 5)) {
00119 debug(LOG_ERR, "Could not listen on control socket: %s",
00120 strerror(errno));
00121 pthread_exit(NULL);
00122 }
00123
00124 while (1) {
00125 memset(&sa_un, 0, sizeof(sa_un));
00126 if ((fd = accept(sock, (struct sockaddr *)&sa_un, &len)) == -1){
00127 debug(LOG_ERR, "Accept failed on control socket: %s",
00128 strerror(errno));
00129 } else {
00130 debug(LOG_DEBUG, "Accepted connection on wdctl socket %d (%s)", fd, sa_un.sun_path);
00131 result = pthread_create(&tid, NULL, &thread_wdctl_handler, (void *)fd);
00132 if (result != 0) {
00133 debug(LOG_ERR, "FATAL: Failed to create a new thread (wdctl handler) - exiting");
00134 termination_handler(0);
00135 }
00136 pthread_detach(tid);
00137 }
00138 }
00139 }
00140
00141
00142 static void *
00143 thread_wdctl_handler(void *arg)
00144 {
00145 int fd,
00146 done,
00147 i;
00148 char request[MAX_BUF];
00149 ssize_t read_bytes,
00150 len;
00151
00152 debug(LOG_DEBUG, "Entering thread_wdctl_handler....");
00153
00154 fd = (int)arg;
00155
00156 debug(LOG_DEBUG, "Read bytes and stuff from %d", fd);
00157
00158
00159 read_bytes = 0;
00160 done = 0;
00161 memset(request, 0, sizeof(request));
00162
00163
00164 while (!done && read_bytes < (sizeof(request) - 1)) {
00165 len = read(fd, request + read_bytes,
00166 sizeof(request) - read_bytes);
00167
00168
00169 for (i = read_bytes; i < (read_bytes + len); i++) {
00170 if (request[i] == '\r' || request[i] == '\n') {
00171 request[i] = '\0';
00172 done = 1;
00173 }
00174 }
00175
00176
00177 read_bytes += len;
00178 }
00179
00180 if (strcmp(request, "status") == 0) {
00181 wdctl_status(fd);
00182 } else if (strcmp(request, "stop") == 0) {
00183 wdctl_stop(fd);
00184 } else if (strncmp(request, "reset", 6) == 0) {
00185 wdctl_reset(fd, (request + 6));
00186 } else if (strncmp(request, "restart", 7) == 0) {
00187 wdctl_restart(fd);
00188 }
00189
00190 if (!done) {
00191 debug(LOG_ERR, "Invalid wdctl request.");
00192 shutdown(fd, 2);
00193 close(fd);
00194 pthread_exit(NULL);
00195 }
00196
00197 debug(LOG_DEBUG, "Request received: [%s]", request);
00198
00199 shutdown(fd, 2);
00200 close(fd);
00201 debug(LOG_DEBUG, "Exiting thread_wdctl_handler....");
00202
00203 return NULL;
00204 }
00205
00206 static void
00207 wdctl_status(int fd)
00208 {
00209 char * status = NULL;
00210 int len = 0;
00211
00212 status = get_status_text();
00213 len = strlen(status);
00214
00215 write(fd, status, len);
00216
00217 free(status);
00218 }
00219
00221 static void
00222 wdctl_stop(int fd)
00223 {
00224 pid_t pid;
00225
00226 pid = getpid();
00227 kill(pid, SIGINT);
00228 }
00229
00230 static void
00231 wdctl_restart(int afd)
00232 {
00233 int sock,
00234 fd;
00235 char *sock_name;
00236 struct sockaddr_un sa_un;
00237 int result;
00238 s_config * conf = NULL;
00239 t_client * client = NULL;
00240 char * tempstring = NULL;
00241 pid_t pid;
00242 ssize_t written;
00243 socklen_t len;
00244
00245 conf = config_get_config();
00246
00247 debug(LOG_NOTICE, "Will restart myself");
00248
00249
00250
00251
00252 memset(&sa_un, 0, sizeof(sa_un));
00253 sock_name = conf->internal_sock;
00254 debug(LOG_DEBUG, "Socket name: %s", sock_name);
00255
00256 if (strlen(sock_name) > (sizeof(sa_un.sun_path) - 1)) {
00257
00258 debug(LOG_ERR, "INTERNAL socket name too long");
00259 return;
00260 }
00261
00262 debug(LOG_DEBUG, "Creating socket");
00263 sock = socket(PF_UNIX, SOCK_STREAM, 0);
00264
00265 debug(LOG_DEBUG, "Got internal socket %d", sock);
00266
00267
00268 unlink(sock_name);
00269
00270 debug(LOG_DEBUG, "Filling sockaddr_un");
00271 strcpy(sa_un.sun_path, sock_name);
00272 sa_un.sun_family = AF_UNIX;
00273
00274 debug(LOG_DEBUG, "Binding socket (%s) (%d)", sa_un.sun_path, strlen(sock_name));
00275
00276
00277 if (bind(sock, (struct sockaddr *)&sa_un, strlen(sock_name) + sizeof(sa_un.sun_family))) {
00278 debug(LOG_ERR, "Could not bind internal socket: %s", strerror(errno));
00279 return;
00280 }
00281
00282 if (listen(sock, 5)) {
00283 debug(LOG_ERR, "Could not listen on internal socket: %s", strerror(errno));
00284 return;
00285 }
00286
00287
00288
00289
00290 debug(LOG_DEBUG, "Forking in preparation for exec()...");
00291 pid = safe_fork();
00292 if (pid > 0) {
00293
00294
00295
00296 debug(LOG_DEBUG, "Waiting for child to connect on internal socket");
00297 if ((fd = accept(sock, (struct sockaddr *)&sa_un, &len)) == -1){
00298 debug(LOG_ERR, "Accept failed on internal socket: %s", strerror(errno));
00299 close(sock);
00300 return;
00301 }
00302
00303 close(sock);
00304
00305 debug(LOG_DEBUG, "Received connection from child. Sending them all existing clients");
00306
00307
00308 LOCK_CLIENT_LIST();
00309 client = client_get_first_client();
00310 while (client) {
00311
00312 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);
00313 debug(LOG_DEBUG, "Sending to child client data: %s", tempstring);
00314 len = 0;
00315 while (len != strlen(tempstring)) {
00316 written = write(fd, (tempstring + len), strlen(tempstring) - len);
00317 if (written == -1) {
00318 debug(LOG_ERR, "Failed to write client data to child: %s", strerror(errno));
00319 free(tempstring);
00320 break;
00321 }
00322 else {
00323 len += written;
00324 }
00325 }
00326 free(tempstring);
00327 client = client->next;
00328 }
00329 UNLOCK_CLIENT_LIST();
00330
00331 close(fd);
00332
00333 debug(LOG_INFO, "Sent all existing clients to child. Committing suicide!");
00334
00335 shutdown(afd, 2);
00336 close(afd);
00337
00338
00339 wdctl_stop(afd);
00340 }
00341 else {
00342
00343 close(sock);
00344 shutdown(afd, 2);
00345 close(afd);
00346 debug(LOG_NOTICE, "Re-executing myself (%s)", restartargv[0]);
00347 setsid();
00348 execvp(restartargv[0], restartargv);
00349
00350 debug(LOG_ERR, "I failed to re-execute myself: %s", strerror(errno));
00351 debug(LOG_ERR, "Exiting without cleanup");
00352 exit(1);
00353 }
00354
00355 }
00356
00357 static void
00358 wdctl_reset(int fd, char *arg)
00359 {
00360 t_client *node;
00361
00362 debug(LOG_DEBUG, "Entering wdctl_reset...");
00363
00364 LOCK_CLIENT_LIST();
00365 debug(LOG_DEBUG, "Argument: %s (@%x)", arg, arg);
00366
00367
00368 if ((node = client_list_find_by_ip(arg)) != NULL);
00369 else if ((node = client_list_find_by_mac(arg)) != NULL);
00370 else {
00371 debug(LOG_DEBUG, "Client not found.");
00372 UNLOCK_CLIENT_LIST();
00373 write(fd, "No", 2);
00374 return;
00375 }
00376
00377 debug(LOG_DEBUG, "Got node %x.", node);
00378
00379
00380
00381
00382 fw_deny(node->ip, node->mac, node->fw_connection_state);
00383 client_list_delete(node);
00384
00385 UNLOCK_CLIENT_LIST();
00386
00387 write(fd, "Yes", 3);
00388
00389 debug(LOG_DEBUG, "Exiting wdctl_reset...");
00390 }