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

Revision 479, 8.5 KB (checked in by minaguib, 8 years ago)

* Do not update the last_updated field on incoming traffic - update it on outgoing traffic only. This should be a much more reliable indication of client no longer being there
* WifiDog status is now viewable with a web browser at  http://ip:port/wifidog/status
* Added new web hook for  http://ip:port/wifidog
* Beautified web interface at  http://ip:port/wifidog/*

  • 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 * $Header$
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#include <net/if.h>
43
44#include <string.h>
45#include <pthread.h>
46#include <netdb.h>
47
48#include "client_list.h"
49#include "safe.h"
50#include "util.h"
51#include "conf.h"
52#include "debug.h"
53
54static pthread_mutex_t ghbn_mutex = PTHREAD_MUTEX_INITIALIZER;
55
56/* Defined in ping_thread.c */
57extern time_t started_time;
58
59/* Defined in clientlist.c */
60extern  pthread_mutex_t client_list_mutex;
61extern  pthread_mutex_t config_mutex;
62
63/* XXX Do these need to be locked ? */
64static time_t last_online_time = 0;
65static time_t last_offline_time = 0;
66static time_t last_auth_online_time = 0;
67static time_t last_auth_offline_time = 0;
68
69/** Fork a child and execute a shell command, the parent
70 * process waits for the child to return and returns the child's exit()
71 * value.
72 * @return Return code of the command
73 */
74int
75execute(char *cmd_line, int quiet)
76{
77    int pid,
78        status,
79        rc;
80
81    const char *new_argv[4];
82    new_argv[0] = "/bin/sh";
83    new_argv[1] = "-c";
84    new_argv[2] = cmd_line;
85    new_argv[3] = NULL;
86
87    if ((pid = fork()) < 0) {    /* fork a child process           */
88        debug(LOG_ERR, "fork(): %s", strerror(errno));
89        exit(1);
90    } else if (pid == 0) {    /* for the child process:         */
91        /* We don't want to see any errors if quiet flag is on */
92        if (quiet) close(2);
93        if (execvp("/bin/sh", (char *const *)new_argv) < 0) {    /* execute the command  */
94            debug(LOG_ERR, "execvp(): %s", strerror(errno));
95            exit(1);
96        }
97    } else {        /* for the parent:      */
98        do {
99            rc = wait(&status);
100        } while (rc != pid && rc != -1);    /* wait for completion  */
101    }
102
103    return (WEXITSTATUS(status));
104}
105
106struct in_addr *
107wd_gethostbyname(const char *name)
108{
109        struct hostent *he;
110        struct in_addr *h_addr, *in_addr_temp;
111
112        /* XXX Calling function is reponsible for free() */
113
114        h_addr = safe_malloc(sizeof(struct in_addr));
115       
116        LOCK_GHBN();
117
118        he = gethostbyname(name);
119
120        if (he == NULL) {
121                free(h_addr);
122                UNLOCK_GHBN();
123                return NULL;
124        }
125
126        mark_online();
127
128        in_addr_temp = (struct in_addr *)he->h_addr_list[0];
129        h_addr->s_addr = in_addr_temp->s_addr;
130       
131        UNLOCK_GHBN();
132
133        return h_addr;
134}
135
136char *get_iface_ip(char *ifname) {
137    struct ifreq if_data;
138    struct in_addr in;
139    char *ip_str;
140    int sockd;
141    u_int32_t ip;
142
143    /* Create a socket */
144    if ((sockd = socket (AF_INET, SOCK_PACKET, htons(0x8086))) < 0) {
145        debug(LOG_ERR, "socket(): %s", strerror(errno));
146        return NULL;
147    }
148
149    /* Get IP of internal interface */
150    strcpy (if_data.ifr_name, ifname);
151
152    /* Get the IP address */
153    if (ioctl (sockd, SIOCGIFADDR, &if_data) < 0) {
154        debug(LOG_ERR, "ioctl(): SIOCGIFADDR %s", strerror(errno));
155        return NULL;
156    }
157    memcpy ((void *) &ip, (void *) &if_data.ifr_addr.sa_data + 2, 4);
158    in.s_addr = ip;
159
160    ip_str = (char *)inet_ntoa(in);
161    return safe_strdup(ip_str);
162}
163
164void mark_online() {
165        int before;
166        int after;
167
168        before = is_online();
169        time(&last_online_time);
170        after = is_online();
171
172        if (before != after) {
173                debug(LOG_INFO, "ONLINE status became %s", (after ? "ON" : "OFF"));
174        }
175
176}
177
178void mark_offline() {
179        int before;
180        int after;
181
182        before = is_online();
183        time(&last_offline_time);
184        after = is_online();
185
186        if (before != after) {
187                debug(LOG_INFO, "ONLINE status became %s", (after ? "ON" : "OFF"));
188        }
189
190        /* If we're offline it definately means the auth server is offline */
191        mark_auth_offline();
192
193}
194
195int is_online() {
196        if (last_online_time == 0 || (last_offline_time - last_online_time) >= (config_get_config()->checkinterval * 2) ) {
197                /* We're probably offline */
198                return (0);
199        }
200        else {
201                /* We're probably online */
202                return (1);
203        }
204}
205
206void mark_auth_online() {
207        int before;
208        int after;
209
210        before = is_auth_online();
211        time(&last_auth_online_time);
212        after = is_auth_online();
213
214        if (before != after) {
215                debug(LOG_INFO, "AUTH_ONLINE status became %s", (after ? "ON" : "OFF"));
216        }
217
218        /* If auth server is online it means we're definately online */
219        mark_online();
220
221}
222
223void mark_auth_offline() {
224        int before;
225        int after;
226
227        before = is_auth_online();
228        time(&last_auth_offline_time);
229        after = is_auth_online();
230
231        if (before != after) {
232                debug(LOG_INFO, "AUTH_ONLINE status became %s", (after ? "ON" : "OFF"));
233        }
234
235}
236
237int is_auth_online() {
238        if (!is_online()) {
239                /* If we're not online auth is definately not online :) */
240                return (0);
241        }
242        else if (last_auth_online_time == 0 || (last_auth_offline_time - last_auth_online_time) >= (config_get_config()->checkinterval * 2) ) {
243                /* Auth is  probably offline */
244                return (0);
245        }
246        else {
247                /* Auth is probably online */
248                return (1);
249        }
250}
251
252/*
253 * @return A string containing humn-readable status text. MUST BE free()d by caller
254 */
255char * get_status_text() {
256        char buffer[STATUS_BUF_SIZ];
257        ssize_t len;
258        s_config *config;
259        t_auth_serv *auth_server;
260        t_client        *first;
261        int             count;
262        unsigned long int uptime = 0;
263        unsigned int days = 0, hours = 0, minutes = 0, seconds = 0;
264
265        config = config_get_config();
266       
267        len = 0;
268        snprintf(buffer, (sizeof(buffer) - len), "WiFiDog status\n\n");
269        len = strlen(buffer);
270
271        uptime = time(NULL) - started_time;
272        days    = uptime / (24 * 60 * 60);
273        uptime -= days * (24 * 60 * 60);
274        hours   = uptime / (60 * 60);
275        uptime -= hours * (60 * 60);
276        minutes = uptime / 60;
277        uptime -= minutes * 60;
278        seconds = uptime;
279
280        snprintf((buffer + len), (sizeof(buffer) - len), "Uptime: %ud %uh %um %us\n", days, hours, minutes, seconds);
281        len = strlen(buffer);
282       
283        snprintf((buffer + len), (sizeof(buffer) - len), "is_online: %s\n", (is_online() ? "yes" : "no"));
284        len = strlen(buffer);
285       
286        snprintf((buffer + len), (sizeof(buffer) - len), "is_auth_online: %s\n\n", (is_auth_online() ? "yes" : "no"));
287        len = strlen(buffer);
288
289        LOCK_CLIENT_LIST();
290       
291        first = client_get_first_client();
292       
293        if (first == NULL) {
294                count = 0;
295        } else {
296                count = 1;
297                while (first->next != NULL) {
298                        first = first->next;
299                        count++;
300                }
301        }
302       
303        snprintf((buffer + len), (sizeof(buffer) - len), "%d clients "
304                        "connected.\n", count);
305        len = strlen(buffer);
306
307        first = client_get_first_client();
308
309        count = 0;
310        while (first != NULL) {
311                snprintf((buffer + len), (sizeof(buffer) - len), "Client %d\t"
312                                "Ip: %s\tMac: %s\tToken: %s\n", count, 
313                                first->ip, first->mac, first->token);
314                len = strlen(buffer);
315
316                snprintf((buffer + len), (sizeof(buffer) - len), "\tIn: %llu\t"
317                                "Out: %llu\n" , first->counters.incoming,
318                                first->counters.outgoing);
319                len = strlen(buffer);
320
321                count++;
322                first = first->next;
323        }
324       
325        UNLOCK_CLIENT_LIST();
326
327        LOCK_CONFIG();
328   
329        snprintf((buffer + len), (sizeof(buffer) - len), "\nAuthentication servers:\n");
330        len = strlen(buffer);
331
332        for (auth_server = config->auth_servers; auth_server != NULL; auth_server = auth_server->next) {
333                snprintf((buffer + len), (sizeof(buffer) - len), "  Host: %s (%s)\n", auth_server->authserv_hostname, auth_server->last_ip);
334                len = strlen(buffer);
335        }
336
337        UNLOCK_CONFIG();
338
339        return safe_strdup(buffer);
340}
Note: See TracBrowser for help on using the browser.