root/trunk/wifidog/src/util.c @ 964

Revision 964, 11.0 KB (checked in by papril, 8 years ago)

* src/fw_iptables.c:
* Changed order in the filter.FORWARD chain
* Added TCPMSS rule
* Fixed deleting the rules on shutdown

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/********************************************************************\
2 * This program is free software; you can redistribute it and/or    *
3 * modify it under the terms of the GNU General Public License as   *
4 * published by the Free Software Foundation; either version 2 of   *
5 * the License, or (at your option) any later version.              *
6 *                                                                  *
7 * This program is distributed in the hope that it will be useful,  *
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
10 * GNU General Public License for more details.                     *
11 *                                                                  *
12 * You should have received a copy of the GNU General Public License*
13 * along with this program; if not, contact:                        *
14 *                                                                  *
15 * Free Software Foundation           Voice:  +1-617-542-5942       *
16 * 59 Temple Place - Suite 330        Fax:    +1-617-542-2652       *
17 * Boston, MA  02111-1307,  USA       gnu@gnu.org                   *
18 *                                                                  *
19 \********************************************************************/
20
21/*
22 * $Id$
23 */
24/**
25  @file util.c
26  @brief Misc utility functions
27  @author Copyright (C) 2004 Philippe April <papril777@yahoo.com>
28 */
29
30#define _GNU_SOURCE
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <syslog.h>
35#include <errno.h>
36#include <pthread.h>
37#include <sys/wait.h>
38#include <sys/types.h>
39#include <sys/unistd.h>
40#include <netinet/in.h>
41#include <sys/ioctl.h>
42
43#ifdef __linux__
44#include <net/if.h>
45#endif
46
47#include <string.h>
48#include <pthread.h>
49#include <netdb.h>
50
51#include "common.h"
52#include "client_list.h"
53#include "safe.h"
54#include "util.h"
55#include "conf.h"
56#include "debug.h"
57
58#include "../config.h"
59
60static pthread_mutex_t ghbn_mutex = PTHREAD_MUTEX_INITIALIZER;
61
62/* Defined in ping_thread.c */
63extern time_t started_time;
64
65/* Defined in clientlist.c */
66extern  pthread_mutex_t client_list_mutex;
67extern  pthread_mutex_t config_mutex;
68
69/* Defined in commandline.c */
70extern pid_t restart_orig_pid;
71
72/* XXX Do these need to be locked ? */
73static time_t last_online_time = 0;
74static time_t last_offline_time = 0;
75static time_t last_auth_online_time = 0;
76static time_t last_auth_offline_time = 0;
77
78long served_this_session = 0;
79
80/** Fork a child and execute a shell command, the parent
81 * process waits for the child to return and returns the child's exit()
82 * value.
83 * @return Return code of the command
84 */
85int
86execute(char *cmd_line, int quiet)
87{
88    int pid,
89        status,
90        rc;
91
92    const char *new_argv[4];
93    new_argv[0] = "/bin/sh";
94    new_argv[1] = "-c";
95    new_argv[2] = cmd_line;
96    new_argv[3] = NULL;
97
98         pid = safe_fork();
99         if (pid == 0) {    /* for the child process:         */
100        /* We don't want to see any errors if quiet flag is on */
101        if (quiet) close(2);
102        if (execvp("/bin/sh", (char *const *)new_argv) < 0) {    /* execute the command  */
103            debug(LOG_ERR, "execvp(): %s", strerror(errno));
104            exit(1);
105        }
106    }
107         else {        /* for the parent:      */
108                debug(LOG_DEBUG, "Waiting for PID %d to exit", pid);
109                rc = waitpid(pid, &status, 0);
110                debug(LOG_DEBUG, "Process PID %d exited", rc);
111    }
112
113    return (WEXITSTATUS(status));
114}
115
116struct in_addr *
117wd_gethostbyname(const char *name)
118{
119        struct hostent *he;
120        struct in_addr *h_addr, *in_addr_temp;
121
122        /* XXX Calling function is reponsible for free() */
123
124        h_addr = safe_malloc(sizeof(struct in_addr));
125       
126        LOCK_GHBN();
127
128        he = gethostbyname(name);
129
130        if (he == NULL) {
131                free(h_addr);
132                UNLOCK_GHBN();
133                return NULL;
134        }
135
136        mark_online();
137
138        in_addr_temp = (struct in_addr *)he->h_addr_list[0];
139        h_addr->s_addr = in_addr_temp->s_addr;
140       
141        UNLOCK_GHBN();
142
143        return h_addr;
144}
145
146char *get_iface_ip(char *ifname) {
147#ifdef __linux__
148    struct ifreq if_data;
149#endif
150    struct in_addr in;
151    char *ip_str;
152    int sockd;
153    u_int32_t ip;
154
155#ifdef __linux__
156   
157    /* Create a socket */
158    if ((sockd = socket (AF_INET, SOCK_PACKET, htons(0x8086))) < 0) {
159        debug(LOG_ERR, "socket(): %s", strerror(errno));
160        return NULL;
161    }
162
163    /* Get IP of internal interface */
164    strcpy (if_data.ifr_name, ifname);
165
166    /* Get the IP address */
167    if (ioctl (sockd, SIOCGIFADDR, &if_data) < 0) {
168        debug(LOG_ERR, "ioctl(): SIOCGIFADDR %s", strerror(errno));
169        return NULL;
170    }
171    memcpy ((void *) &ip, (void *) &if_data.ifr_addr.sa_data + 2, 4);
172    in.s_addr = ip;
173
174    ip_str = (char *)inet_ntoa(in);
175    return safe_strdup(ip_str);
176#else
177    return safe_strdup("0.0.0.0");
178#endif
179}
180
181char *get_iface_mac (char *ifname) {
182#ifdef __linux__
183    int r, s;
184    struct ifreq ifr;
185    char *hwaddr, mac[13];
186   
187    strcpy(ifr.ifr_name, ifname);
188
189    s = socket(PF_INET, SOCK_DGRAM, 0);
190    if (-1 == s) {
191       debug(LOG_ERR, "get_iface_mac socket: %s", strerror(errno));
192       return NULL;
193    }
194
195    r = ioctl(s, SIOCGIFHWADDR, &ifr);
196    if (r == -1) {
197       debug(LOG_ERR, "get_iface_mac ioctl(SIOCGIFHWADDR): %s", strerror(errno));
198       close(s);
199       return NULL;
200    }
201
202    hwaddr = ifr.ifr_hwaddr.sa_data;
203    snprintf(mac, 13, "%02X%02X%02X%02X%02X%02X", 
204       hwaddr[0] & 0xFF,
205       hwaddr[1] & 0xFF,
206       hwaddr[2] & 0xFF,
207       hwaddr[3] & 0xFF,
208       hwaddr[4] & 0xFF,
209       hwaddr[5] & 0xFF
210       );
211       
212    close(s);
213    return safe_strdup(mac);
214#else
215    return NULL;
216#endif
217}
218
219char *get_gw_iface (void) {
220#ifdef __linux__
221    FILE *input;
222    char *device, *gw;
223
224    device = (char *)malloc(16);
225    gw = (char *)malloc(16);
226
227    input = fopen("/proc/net/route", "r");
228    while (!feof(input)) {
229        fscanf(input, "%s %s %*s %*s %*s %*s %*s %*s %*s %*s %*s\n", device, gw);
230        if (strcmp(gw, "00000000") == 0) {
231            free(gw);
232            return device;
233        }
234    }
235    fclose(input);
236
237    free(device);
238    free(gw);
239#endif
240    return NULL;
241}
242
243void mark_online() {
244        int before;
245        int after;
246
247        before = is_online();
248        time(&last_online_time);
249        after = is_online();
250
251        if (before != after) {
252                debug(LOG_INFO, "ONLINE status became %s", (after ? "ON" : "OFF"));
253        }
254
255}
256
257void mark_offline() {
258        int before;
259        int after;
260
261        before = is_online();
262        time(&last_offline_time);
263        after = is_online();
264
265        if (before != after) {
266                debug(LOG_INFO, "ONLINE status became %s", (after ? "ON" : "OFF"));
267        }
268
269        /* If we're offline it definately means the auth server is offline */
270        mark_auth_offline();
271
272}
273
274int is_online() {
275        if (last_online_time == 0 || (last_offline_time - last_online_time) >= (config_get_config()->checkinterval * 2) ) {
276                /* We're probably offline */
277                return (0);
278        }
279        else {
280                /* We're probably online */
281                return (1);
282        }
283}
284
285void mark_auth_online() {
286        int before;
287        int after;
288
289        before = is_auth_online();
290        time(&last_auth_online_time);
291        after = is_auth_online();
292
293        if (before != after) {
294                debug(LOG_INFO, "AUTH_ONLINE status became %s", (after ? "ON" : "OFF"));
295        }
296
297        /* If auth server is online it means we're definately online */
298        mark_online();
299
300}
301
302void mark_auth_offline() {
303        int before;
304        int after;
305
306        before = is_auth_online();
307        time(&last_auth_offline_time);
308        after = is_auth_online();
309
310        if (before != after) {
311                debug(LOG_INFO, "AUTH_ONLINE status became %s", (after ? "ON" : "OFF"));
312        }
313
314}
315
316int is_auth_online() {
317        if (!is_online()) {
318                /* If we're not online auth is definately not online :) */
319                return (0);
320        }
321        else if (last_auth_online_time == 0 || (last_auth_offline_time - last_auth_online_time) >= (config_get_config()->checkinterval * 2) ) {
322                /* Auth is  probably offline */
323                return (0);
324        }
325        else {
326                /* Auth is probably online */
327                return (1);
328        }
329}
330
331/*
332 * @return A string containing human-readable status text. MUST BE free()d by caller
333 */
334char * get_status_text() {
335        char buffer[STATUS_BUF_SIZ];
336        ssize_t len;
337        s_config *config;
338        t_auth_serv *auth_server;
339        t_client        *first;
340        int             count;
341        unsigned long int uptime = 0;
342        unsigned int days = 0, hours = 0, minutes = 0, seconds = 0;
343     t_trusted_mac *p;
344       
345        len = 0;
346        snprintf(buffer, (sizeof(buffer) - len), "WiFiDog status\n\n");
347        len = strlen(buffer);
348
349        uptime = time(NULL) - started_time;
350        days    = uptime / (24 * 60 * 60);
351        uptime -= days * (24 * 60 * 60);
352        hours   = uptime / (60 * 60);
353        uptime -= hours * (60 * 60);
354        minutes = uptime / 60;
355        uptime -= minutes * 60;
356        seconds = uptime;
357
358        snprintf((buffer + len), (sizeof(buffer) - len), "Version: " VERSION "\n");
359        len = strlen(buffer);
360
361        snprintf((buffer + len), (sizeof(buffer) - len), "Uptime: %ud %uh %um %us\n", days, hours, minutes, seconds);
362        len = strlen(buffer);
363
364        snprintf((buffer + len), (sizeof(buffer) - len), "Has been restarted: ");
365        len = strlen(buffer);
366        if (restart_orig_pid) {
367                snprintf((buffer + len), (sizeof(buffer) - len), "yes (from PID %d)\n", restart_orig_pid);
368                len = strlen(buffer);
369        }
370        else {
371                snprintf((buffer + len), (sizeof(buffer) - len), "no\n");
372                len = strlen(buffer);
373        }
374       
375        snprintf((buffer + len), (sizeof(buffer) - len), "Internet Connectivity: %s\n", (is_online() ? "yes" : "no"));
376        len = strlen(buffer);
377       
378        snprintf((buffer + len), (sizeof(buffer) - len), "Auth server reachable: %s\n", (is_auth_online() ? "yes" : "no"));
379        len = strlen(buffer);
380
381        snprintf((buffer + len), (sizeof(buffer) - len), "Clients served this session: %lu\n\n", served_this_session);
382        len = strlen(buffer);
383
384        LOCK_CLIENT_LIST();
385       
386        first = client_get_first_client();
387       
388        if (first == NULL) {
389                count = 0;
390        } else {
391                count = 1;
392                while (first->next != NULL) {
393                        first = first->next;
394                        count++;
395                }
396        }
397       
398        snprintf((buffer + len), (sizeof(buffer) - len), "%d clients "
399                        "connected.\n", count);
400        len = strlen(buffer);
401
402        first = client_get_first_client();
403
404        count = 0;
405        while (first != NULL) {
406                snprintf((buffer + len), (sizeof(buffer) - len), "\nClient %d\n", count);
407                len = strlen(buffer);
408
409                snprintf((buffer + len), (sizeof(buffer) - len), "  IP: %s MAC: %s\n", first->ip, first->mac);
410                len = strlen(buffer);
411
412                snprintf((buffer + len), (sizeof(buffer) - len), "  Token: %s\n", first->token);
413                len = strlen(buffer);
414
415                snprintf((buffer + len), (sizeof(buffer) - len), "  Downloaded: %llu\n  Uploaded: %llu\n" , first->counters.incoming, first->counters.outgoing);
416                len = strlen(buffer);
417
418                count++;
419                first = first->next;
420        }
421
422        UNLOCK_CLIENT_LIST();
423
424    config = config_get_config();
425   
426    if (config->trustedmaclist != NULL) {
427        snprintf((buffer + len), (sizeof(buffer) - len), "\nTrusted MAC addresses:\n");
428        len = strlen(buffer);
429
430        for (p = config->trustedmaclist; p != NULL; p = p->next) {
431            snprintf((buffer + len), (sizeof(buffer) - len), "  %s\n", p->mac);
432            len = strlen(buffer);
433        }
434    }
435
436    snprintf((buffer + len), (sizeof(buffer) - len), "\nAuthentication servers:\n");
437    len = strlen(buffer);
438
439    LOCK_CONFIG();
440
441    for (auth_server = config->auth_servers; auth_server != NULL; auth_server = auth_server->next) {
442        snprintf((buffer + len), (sizeof(buffer) - len), "  Host: %s (%s)\n", auth_server->authserv_hostname, auth_server->last_ip);
443        len = strlen(buffer);
444    }
445
446    UNLOCK_CONFIG();
447
448        return safe_strdup(buffer);
449}
Note: See TracBrowser for help on using the browser.