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

Revision 935, 10.6 KB (checked in by benoitg, 7 years ago)
  • src/fw_iptables.c: Add the global ruleset to the nat table to fix #65. Add the table parameter to iptables_load_ruleset() and iptables_compile
  • libhttpd/protocol.c: Fix pointer type mismatch
  • src/conf.c,h: Remove deprecated option AuthServMaxTries? (which was already ignored anyway.
  • 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
219void mark_online() {
220        int before;
221        int after;
222
223        before = is_online();
224        time(&last_online_time);
225        after = is_online();
226
227        if (before != after) {
228                debug(LOG_INFO, "ONLINE status became %s", (after ? "ON" : "OFF"));
229        }
230
231}
232
233void mark_offline() {
234        int before;
235        int after;
236
237        before = is_online();
238        time(&last_offline_time);
239        after = is_online();
240
241        if (before != after) {
242                debug(LOG_INFO, "ONLINE status became %s", (after ? "ON" : "OFF"));
243        }
244
245        /* If we're offline it definately means the auth server is offline */
246        mark_auth_offline();
247
248}
249
250int is_online() {
251        if (last_online_time == 0 || (last_offline_time - last_online_time) >= (config_get_config()->checkinterval * 2) ) {
252                /* We're probably offline */
253                return (0);
254        }
255        else {
256                /* We're probably online */
257                return (1);
258        }
259}
260
261void mark_auth_online() {
262        int before;
263        int after;
264
265        before = is_auth_online();
266        time(&last_auth_online_time);
267        after = is_auth_online();
268
269        if (before != after) {
270                debug(LOG_INFO, "AUTH_ONLINE status became %s", (after ? "ON" : "OFF"));
271        }
272
273        /* If auth server is online it means we're definately online */
274        mark_online();
275
276}
277
278void mark_auth_offline() {
279        int before;
280        int after;
281
282        before = is_auth_online();
283        time(&last_auth_offline_time);
284        after = is_auth_online();
285
286        if (before != after) {
287                debug(LOG_INFO, "AUTH_ONLINE status became %s", (after ? "ON" : "OFF"));
288        }
289
290}
291
292int is_auth_online() {
293        if (!is_online()) {
294                /* If we're not online auth is definately not online :) */
295                return (0);
296        }
297        else if (last_auth_online_time == 0 || (last_auth_offline_time - last_auth_online_time) >= (config_get_config()->checkinterval * 2) ) {
298                /* Auth is  probably offline */
299                return (0);
300        }
301        else {
302                /* Auth is probably online */
303                return (1);
304        }
305}
306
307/*
308 * @return A string containing human-readable status text. MUST BE free()d by caller
309 */
310char * get_status_text() {
311        char buffer[STATUS_BUF_SIZ];
312        ssize_t len;
313        s_config *config;
314        t_auth_serv *auth_server;
315        t_client        *first;
316        int             count;
317        unsigned long int uptime = 0;
318        unsigned int days = 0, hours = 0, minutes = 0, seconds = 0;
319     t_trusted_mac *p;
320       
321        len = 0;
322        snprintf(buffer, (sizeof(buffer) - len), "WiFiDog status\n\n");
323        len = strlen(buffer);
324
325        uptime = time(NULL) - started_time;
326        days    = uptime / (24 * 60 * 60);
327        uptime -= days * (24 * 60 * 60);
328        hours   = uptime / (60 * 60);
329        uptime -= hours * (60 * 60);
330        minutes = uptime / 60;
331        uptime -= minutes * 60;
332        seconds = uptime;
333
334        snprintf((buffer + len), (sizeof(buffer) - len), "Version: " VERSION "\n");
335        len = strlen(buffer);
336
337        snprintf((buffer + len), (sizeof(buffer) - len), "Uptime: %ud %uh %um %us\n", days, hours, minutes, seconds);
338        len = strlen(buffer);
339
340        snprintf((buffer + len), (sizeof(buffer) - len), "Has been restarted: ");
341        len = strlen(buffer);
342        if (restart_orig_pid) {
343                snprintf((buffer + len), (sizeof(buffer) - len), "yes (from PID %d)\n", restart_orig_pid);
344                len = strlen(buffer);
345        }
346        else {
347                snprintf((buffer + len), (sizeof(buffer) - len), "no\n");
348                len = strlen(buffer);
349        }
350       
351        snprintf((buffer + len), (sizeof(buffer) - len), "Internet Connectivity: %s\n", (is_online() ? "yes" : "no"));
352        len = strlen(buffer);
353       
354        snprintf((buffer + len), (sizeof(buffer) - len), "Auth server reachable: %s\n", (is_auth_online() ? "yes" : "no"));
355        len = strlen(buffer);
356
357        snprintf((buffer + len), (sizeof(buffer) - len), "Clients served this session: %lu\n\n", served_this_session);
358        len = strlen(buffer);
359
360        LOCK_CLIENT_LIST();
361       
362        first = client_get_first_client();
363       
364        if (first == NULL) {
365                count = 0;
366        } else {
367                count = 1;
368                while (first->next != NULL) {
369                        first = first->next;
370                        count++;
371                }
372        }
373       
374        snprintf((buffer + len), (sizeof(buffer) - len), "%d clients "
375                        "connected.\n", count);
376        len = strlen(buffer);
377
378        first = client_get_first_client();
379
380        count = 0;
381        while (first != NULL) {
382                snprintf((buffer + len), (sizeof(buffer) - len), "\nClient %d\n", count);
383                len = strlen(buffer);
384
385                snprintf((buffer + len), (sizeof(buffer) - len), "  IP: %s MAC: %s\n", first->ip, first->mac);
386                len = strlen(buffer);
387
388                snprintf((buffer + len), (sizeof(buffer) - len), "  Token: %s\n", first->token);
389                len = strlen(buffer);
390
391                snprintf((buffer + len), (sizeof(buffer) - len), "  Downloaded: %llu\n  Uploaded: %llu\n" , first->counters.incoming, first->counters.outgoing);
392                len = strlen(buffer);
393
394                count++;
395                first = first->next;
396        }
397
398        UNLOCK_CLIENT_LIST();
399
400    config = config_get_config();
401   
402    if (config->trustedmaclist != NULL) {
403        snprintf((buffer + len), (sizeof(buffer) - len), "\nTrusted MAC addresses:\n");
404        len = strlen(buffer);
405
406        for (p = config->trustedmaclist; p != NULL; p = p->next) {
407            snprintf((buffer + len), (sizeof(buffer) - len), "  %s\n", p->mac);
408            len = strlen(buffer);
409        }
410    }
411
412    snprintf((buffer + len), (sizeof(buffer) - len), "\nAuthentication servers:\n");
413    len = strlen(buffer);
414
415    LOCK_CONFIG();
416
417    for (auth_server = config->auth_servers; auth_server != NULL; auth_server = auth_server->next) {
418        snprintf((buffer + len), (sizeof(buffer) - len), "  Host: %s (%s)\n", auth_server->authserv_hostname, auth_server->last_ip);
419        len = strlen(buffer);
420    }
421
422    UNLOCK_CONFIG();
423
424        return safe_strdup(buffer);
425}
Note: See TracBrowser for help on using the browser.