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