00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00031 #define _GNU_SOURCE
00032
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #include <syslog.h>
00036 #include <errno.h>
00037 #include <pthread.h>
00038 #include <sys/wait.h>
00039 #include <sys/types.h>
00040 #include <sys/unistd.h>
00041 #include <netinet/in.h>
00042 #include <sys/ioctl.h>
00043
00044 #ifdef __linux__
00045 #include <net/if.h>
00046 #endif
00047
00048 #include <string.h>
00049 #include <pthread.h>
00050 #include <netdb.h>
00051
00052 #include "common.h"
00053 #include "client_list.h"
00054 #include "safe.h"
00055 #include "util.h"
00056 #include "conf.h"
00057 #include "debug.h"
00058
00059 #include "../config.h"
00060
00061 static pthread_mutex_t ghbn_mutex = PTHREAD_MUTEX_INITIALIZER;
00062
00063
00064 extern time_t started_time;
00065
00066
00067 extern pthread_mutex_t client_list_mutex;
00068 extern pthread_mutex_t config_mutex;
00069
00070
00071 extern pid_t restart_orig_pid;
00072
00073
00074 static time_t last_online_time = 0;
00075 static time_t last_offline_time = 0;
00076 static time_t last_auth_online_time = 0;
00077 static time_t last_auth_offline_time = 0;
00078
00079 long served_this_session = 0;
00080
00086 int
00087 execute(char *cmd_line, int quiet)
00088 {
00089 int pid,
00090 status,
00091 rc;
00092
00093 const char *new_argv[4];
00094 new_argv[0] = "/bin/sh";
00095 new_argv[1] = "-c";
00096 new_argv[2] = cmd_line;
00097 new_argv[3] = NULL;
00098
00099 pid = safe_fork();
00100 if (pid == 0) {
00101
00102 if (quiet) close(2);
00103 if (execvp("/bin/sh", (char *const *)new_argv) < 0) {
00104 debug(LOG_ERR, "execvp(): %s", strerror(errno));
00105 exit(1);
00106 }
00107 }
00108 else {
00109 debug(LOG_DEBUG, "Waiting for PID %d to exit", pid);
00110 rc = waitpid(pid, &status, 0);
00111 debug(LOG_DEBUG, "Process PID %d exited", rc);
00112 }
00113
00114 return (WEXITSTATUS(status));
00115 }
00116
00117 struct in_addr *
00118 wd_gethostbyname(const char *name)
00119 {
00120 struct hostent *he;
00121 struct in_addr *h_addr, *in_addr_temp;
00122
00123
00124
00125 h_addr = safe_malloc(sizeof(struct in_addr));
00126
00127 LOCK_GHBN();
00128
00129 he = gethostbyname(name);
00130
00131 if (he == NULL) {
00132 free(h_addr);
00133 UNLOCK_GHBN();
00134 return NULL;
00135 }
00136
00137 mark_online();
00138
00139 in_addr_temp = (struct in_addr *)he->h_addr_list[0];
00140 h_addr->s_addr = in_addr_temp->s_addr;
00141
00142 UNLOCK_GHBN();
00143
00144 return h_addr;
00145 }
00146
00147 char *get_iface_ip(char *ifname) {
00148 #ifdef __linux__
00149 struct ifreq if_data;
00150 #endif
00151 struct in_addr in;
00152 char *ip_str;
00153 int sockd;
00154 u_int32_t ip;
00155
00156 #ifdef __linux__
00157
00158
00159 if ((sockd = socket (AF_INET, SOCK_PACKET, htons(0x8086))) < 0) {
00160 debug(LOG_ERR, "socket(): %s", strerror(errno));
00161 return NULL;
00162 }
00163
00164
00165 strcpy (if_data.ifr_name, ifname);
00166
00167
00168 if (ioctl (sockd, SIOCGIFADDR, &if_data) < 0) {
00169 debug(LOG_ERR, "ioctl(): SIOCGIFADDR %s", strerror(errno));
00170 return NULL;
00171 }
00172 memcpy ((void *) &ip, (void *) &if_data.ifr_addr.sa_data + 2, 4);
00173 in.s_addr = ip;
00174
00175 ip_str = (char *)inet_ntoa(in);
00176 close(sockd);
00177 return safe_strdup(ip_str);
00178 #else
00179 return safe_strdup("0.0.0.0");
00180 #endif
00181 }
00182
00183 char *get_iface_mac (char *ifname) {
00184 #ifdef __linux__
00185 int r, s;
00186 struct ifreq ifr;
00187 char *hwaddr, mac[13];
00188
00189 strcpy(ifr.ifr_name, ifname);
00190
00191 s = socket(PF_INET, SOCK_DGRAM, 0);
00192 if (-1 == s) {
00193 debug(LOG_ERR, "get_iface_mac socket: %s", strerror(errno));
00194 return NULL;
00195 }
00196
00197 r = ioctl(s, SIOCGIFHWADDR, &ifr);
00198 if (r == -1) {
00199 debug(LOG_ERR, "get_iface_mac ioctl(SIOCGIFHWADDR): %s", strerror(errno));
00200 close(s);
00201 return NULL;
00202 }
00203
00204 hwaddr = ifr.ifr_hwaddr.sa_data;
00205 snprintf(mac, 13, "%02X%02X%02X%02X%02X%02X",
00206 hwaddr[0] & 0xFF,
00207 hwaddr[1] & 0xFF,
00208 hwaddr[2] & 0xFF,
00209 hwaddr[3] & 0xFF,
00210 hwaddr[4] & 0xFF,
00211 hwaddr[5] & 0xFF
00212 );
00213
00214 close(s);
00215 return safe_strdup(mac);
00216 #else
00217 return NULL;
00218 #endif
00219 }
00220
00221 char *get_ext_iface (void) {
00222 #ifdef __linux__
00223 FILE *input;
00224 char *device, *gw;
00225 int i = 1;
00226 int keep_detecting = 1;
00227 pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
00228 pthread_mutex_t cond_mutex = PTHREAD_MUTEX_INITIALIZER;
00229 struct timespec timeout;
00230 device = (char *)malloc(16);
00231 gw = (char *)malloc(16);
00232 debug(LOG_DEBUG, "get_ext_iface(): Autodectecting the external interface from routing table");
00233 while(keep_detecting) {
00234 input = fopen("/proc/net/route", "r");
00235 while (!feof(input)) {
00236 fscanf(input, "%s %s %*s %*s %*s %*s %*s %*s %*s %*s %*s\n", device, gw);
00237 if (strcmp(gw, "00000000") == 0) {
00238 free(gw);
00239 debug(LOG_INFO, "get_ext_iface(): Detected %s as the default interface after try %d", device, i);
00240 return device;
00241 }
00242 }
00243 fclose(input);
00244 debug(LOG_ERR, "get_ext_iface(): Failed to detect the external interface after try %d (maybe the interface is not up yet?). Retry limit: %d", i, NUM_EXT_INTERFACE_DETECT_RETRY);
00245
00246 timeout.tv_sec = time(NULL) + EXT_INTERFACE_DETECT_RETRY_INTERVAL;
00247 timeout.tv_nsec = 0;
00248
00249 pthread_mutex_lock(&cond_mutex);
00250
00251 pthread_cond_timedwait(&cond, &cond_mutex, &timeout);
00252
00253 pthread_mutex_unlock(&cond_mutex);
00254
00255 if (NUM_EXT_INTERFACE_DETECT_RETRY != 0 && i>NUM_EXT_INTERFACE_DETECT_RETRY) {
00256 keep_detecting = 0;
00257 }
00258 i++;
00259 }
00260 debug(LOG_ERR, "get_ext_iface(): Failed to detect the external interface after %d tries, aborting", i);
00261 exit(1);
00262 free(device);
00263 free(gw);
00264 #endif
00265 return NULL;
00266 }
00267
00268 void mark_online() {
00269 int before;
00270 int after;
00271
00272 before = is_online();
00273 time(&last_online_time);
00274 after = is_online();
00275
00276 if (before != after) {
00277 debug(LOG_INFO, "ONLINE status became %s", (after ? "ON" : "OFF"));
00278 }
00279
00280 }
00281
00282 void mark_offline() {
00283 int before;
00284 int after;
00285
00286 before = is_online();
00287 time(&last_offline_time);
00288 after = is_online();
00289
00290 if (before != after) {
00291 debug(LOG_INFO, "ONLINE status became %s", (after ? "ON" : "OFF"));
00292 }
00293
00294
00295 mark_auth_offline();
00296
00297 }
00298
00299 int is_online() {
00300 if (last_online_time == 0 || (last_offline_time - last_online_time) >= (config_get_config()->checkinterval * 2) ) {
00301
00302 return (0);
00303 }
00304 else {
00305
00306 return (1);
00307 }
00308 }
00309
00310 void mark_auth_online() {
00311 int before;
00312 int after;
00313
00314 before = is_auth_online();
00315 time(&last_auth_online_time);
00316 after = is_auth_online();
00317
00318 if (before != after) {
00319 debug(LOG_INFO, "AUTH_ONLINE status became %s", (after ? "ON" : "OFF"));
00320 }
00321
00322
00323 mark_online();
00324
00325 }
00326
00327 void mark_auth_offline() {
00328 int before;
00329 int after;
00330
00331 before = is_auth_online();
00332 time(&last_auth_offline_time);
00333 after = is_auth_online();
00334
00335 if (before != after) {
00336 debug(LOG_INFO, "AUTH_ONLINE status became %s", (after ? "ON" : "OFF"));
00337 }
00338
00339 }
00340
00341 int is_auth_online() {
00342 if (!is_online()) {
00343
00344 return (0);
00345 }
00346 else if (last_auth_online_time == 0 || (last_auth_offline_time - last_auth_online_time) >= (config_get_config()->checkinterval * 2) ) {
00347
00348 return (0);
00349 }
00350 else {
00351
00352 return (1);
00353 }
00354 }
00355
00356
00357
00358
00359 char * get_status_text() {
00360 char buffer[STATUS_BUF_SIZ];
00361 ssize_t len;
00362 s_config *config;
00363 t_auth_serv *auth_server;
00364 t_client *first;
00365 int count;
00366 unsigned long int uptime = 0;
00367 unsigned int days = 0, hours = 0, minutes = 0, seconds = 0;
00368 t_trusted_mac *p;
00369
00370 len = 0;
00371 snprintf(buffer, (sizeof(buffer) - len), "WiFiDog status\n\n");
00372 len = strlen(buffer);
00373
00374 uptime = time(NULL) - started_time;
00375 days = uptime / (24 * 60 * 60);
00376 uptime -= days * (24 * 60 * 60);
00377 hours = uptime / (60 * 60);
00378 uptime -= hours * (60 * 60);
00379 minutes = uptime / 60;
00380 uptime -= minutes * 60;
00381 seconds = uptime;
00382
00383 snprintf((buffer + len), (sizeof(buffer) - len), "Version: " VERSION "\n");
00384 len = strlen(buffer);
00385
00386 snprintf((buffer + len), (sizeof(buffer) - len), "Uptime: %ud %uh %um %us\n", days, hours, minutes, seconds);
00387 len = strlen(buffer);
00388
00389 snprintf((buffer + len), (sizeof(buffer) - len), "Has been restarted: ");
00390 len = strlen(buffer);
00391 if (restart_orig_pid) {
00392 snprintf((buffer + len), (sizeof(buffer) - len), "yes (from PID %d)\n", restart_orig_pid);
00393 len = strlen(buffer);
00394 }
00395 else {
00396 snprintf((buffer + len), (sizeof(buffer) - len), "no\n");
00397 len = strlen(buffer);
00398 }
00399
00400 snprintf((buffer + len), (sizeof(buffer) - len), "Internet Connectivity: %s\n", (is_online() ? "yes" : "no"));
00401 len = strlen(buffer);
00402
00403 snprintf((buffer + len), (sizeof(buffer) - len), "Auth server reachable: %s\n", (is_auth_online() ? "yes" : "no"));
00404 len = strlen(buffer);
00405
00406 snprintf((buffer + len), (sizeof(buffer) - len), "Clients served this session: %lu\n\n", served_this_session);
00407 len = strlen(buffer);
00408
00409 LOCK_CLIENT_LIST();
00410
00411 first = client_get_first_client();
00412
00413 if (first == NULL) {
00414 count = 0;
00415 } else {
00416 count = 1;
00417 while (first->next != NULL) {
00418 first = first->next;
00419 count++;
00420 }
00421 }
00422
00423 snprintf((buffer + len), (sizeof(buffer) - len), "%d clients "
00424 "connected.\n", count);
00425 len = strlen(buffer);
00426
00427 first = client_get_first_client();
00428
00429 count = 0;
00430 while (first != NULL) {
00431 snprintf((buffer + len), (sizeof(buffer) - len), "\nClient %d\n", count);
00432 len = strlen(buffer);
00433
00434 snprintf((buffer + len), (sizeof(buffer) - len), " IP: %s MAC: %s\n", first->ip, first->mac);
00435 len = strlen(buffer);
00436
00437 snprintf((buffer + len), (sizeof(buffer) - len), " Token: %s\n", first->token);
00438 len = strlen(buffer);
00439
00440 snprintf((buffer + len), (sizeof(buffer) - len), " Downloaded: %llu\n Uploaded: %llu\n" , first->counters.incoming, first->counters.outgoing);
00441 len = strlen(buffer);
00442
00443 count++;
00444 first = first->next;
00445 }
00446
00447 UNLOCK_CLIENT_LIST();
00448
00449 config = config_get_config();
00450
00451 if (config->trustedmaclist != NULL) {
00452 snprintf((buffer + len), (sizeof(buffer) - len), "\nTrusted MAC addresses:\n");
00453 len = strlen(buffer);
00454
00455 for (p = config->trustedmaclist; p != NULL; p = p->next) {
00456 snprintf((buffer + len), (sizeof(buffer) - len), " %s\n", p->mac);
00457 len = strlen(buffer);
00458 }
00459 }
00460
00461 snprintf((buffer + len), (sizeof(buffer) - len), "\nAuthentication servers:\n");
00462 len = strlen(buffer);
00463
00464 LOCK_CONFIG();
00465
00466 for (auth_server = config->auth_servers; auth_server != NULL; auth_server = auth_server->next) {
00467 snprintf((buffer + len), (sizeof(buffer) - len), " Host: %s (%s)\n", auth_server->authserv_hostname, auth_server->last_ip);
00468 len = strlen(buffer);
00469 }
00470
00471 UNLOCK_CONFIG();
00472
00473 return safe_strdup(buffer);
00474 }