root/trunk/wifidog/src/fw_iptables.c @ 1241

Revision 1241, 19.6 KB (checked in by benoitg, 7 years ago)
  • Close #321: Make the Gateway retry forever if it cannot find it's interface. You never know when someone may finally replug the network cable or something...
  • Close #332: Apply patch from Laurent Marchal. biguphpc<AT>gmail<DOT>com
  • fw_iptables.c: Fix error in iptables_fw_access(). Rules were created as ACCEPT instead of DROP
  • firewall.c: Fix bug in fw_sync_with_authserver(). The traffic for the validation period of a user who validated his account while connected wouldn't get counted.
  • doc/wifidog_firewall_map.dia: At long last, full documentation of the firewall. We would have avoided a lot of stupid mistakes if we produced that sooner.
  • Release 1.1.3_rc1
  • 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/* $Id$ */
22/** @internal
23  @file fw_iptables.c
24  @brief Firewall iptables functions
25  @author Copyright (C) 2004 Philippe April <papril777@yahoo.com>
26 */
27
28#define _GNU_SOURCE
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <stdarg.h>
33#include <syslog.h>
34#include <errno.h>
35#include <string.h>
36#include <pthread.h>
37#include <sys/socket.h>
38#include <netinet/in.h>
39#include <arpa/inet.h>
40
41#include "common.h"
42
43#include "safe.h"
44#include "conf.h"
45#include "fw_iptables.h"
46#include "firewall.h"
47#include "debug.h"
48#include "util.h"
49#include "client_list.h"
50
51static int iptables_do_command(char *format, ...);
52static char *iptables_compile(char *, char *, t_firewall_rule *);
53static void iptables_load_ruleset(char *, char *, char *);
54
55extern pthread_mutex_t  client_list_mutex;
56extern pthread_mutex_t  config_mutex;
57
58/**
59Used to supress the error output of the firewall during destruction */ 
60static int fw_quiet = 0;
61
62/** @internal
63 * */
64static int
65iptables_do_command(char *format, ...)
66{
67    va_list vlist;
68    char *fmt_cmd,
69        *cmd;
70    int rc;
71
72    va_start(vlist, format);
73    safe_vasprintf(&fmt_cmd, format, vlist);
74         va_end(vlist);
75
76    safe_asprintf(&cmd, "iptables %s", fmt_cmd);
77
78    free(fmt_cmd);
79
80    debug(LOG_DEBUG, "Executing command: %s", cmd);
81       
82    rc = execute(cmd, fw_quiet);
83
84    free(cmd);
85
86    return rc;
87}
88
89/**
90 * @internal
91 * Compiles a struct definition of a firewall rule into a valid iptables
92 * command.
93 * @arg table Table containing the chain.
94 * @arg chain Chain that the command will be (-A)ppended to.
95 * @arg rule Definition of a rule into a struct, from conf.c.
96 */
97static char *
98iptables_compile(char * table, char *chain, t_firewall_rule *rule)
99{
100    char        command[MAX_BUF],
101                *mode;
102   
103    memset(command, 0, MAX_BUF);
104   
105    if (rule->block_allow == 1) {
106        mode = safe_strdup("ACCEPT");
107    } else {
108        mode = safe_strdup("REJECT");
109    }
110   
111    snprintf(command, sizeof(command),  "-t %s -A %s ",table, chain);
112    if (rule->mask != NULL) {
113        snprintf((command + strlen(command)), (sizeof(command) - 
114                strlen(command)), "-d %s ", rule->mask);
115    }
116    if (rule->protocol != NULL) {
117        snprintf((command + strlen(command)), (sizeof(command) -
118                strlen(command)), "-p %s ", rule->protocol);
119    }
120    if (rule->port != NULL) {
121        snprintf((command + strlen(command)), (sizeof(command) -
122                strlen(command)), "--dport %s ", rule->port);
123    }
124    snprintf((command + strlen(command)), (sizeof(command) - 
125            strlen(command)), "-j %s", mode);
126   
127    free(mode);
128
129    /* XXX The buffer command, an automatic variable, will get cleaned
130     * off of the stack when we return, so we strdup() it. */
131    return(safe_strdup(command));
132}
133
134/**
135 * @internal
136 * Load all the rules in a rule set.
137 * @arg ruleset Name of the ruleset
138 * @arg table Table containing the chain.
139 * @arg chain IPTables chain the rules go into
140 */
141static void
142iptables_load_ruleset(char * table, char *ruleset, char *chain)
143{
144        t_firewall_rule         *rule;
145        char                    *cmd;
146
147        debug(LOG_DEBUG, "Load ruleset %s into table %s, chain %s", ruleset, table, chain);
148       
149        for (rule = get_ruleset(ruleset); rule != NULL; rule = rule->next) {
150                cmd = iptables_compile(table, chain, rule);
151                debug(LOG_DEBUG, "Loading rule \"%s\" into table %s, chain %s", cmd, table, chain);
152                iptables_do_command(cmd);
153                free(cmd);
154        }
155
156        debug(LOG_DEBUG, "Ruleset %s loaded into table %s, chain %s", ruleset, table, chain);
157}
158
159void
160iptables_fw_clear_authservers(void)
161{
162    iptables_do_command("-t filter -F " TABLE_WIFIDOG_AUTHSERVERS);
163    iptables_do_command("-t nat -F " TABLE_WIFIDOG_AUTHSERVERS);
164}
165
166void
167iptables_fw_set_authservers(void)
168{
169    s_config *config;
170    t_auth_serv *auth_server;
171   
172    config = config_get_config();
173   
174    for (auth_server = config->auth_servers; auth_server != NULL; auth_server = auth_server->next) {
175            if (auth_server->last_ip && strcmp(auth_server->last_ip, "0.0.0.0") != 0) {
176                iptables_do_command("-t filter -A " TABLE_WIFIDOG_AUTHSERVERS " -d %s -j ACCEPT", auth_server->last_ip);
177                iptables_do_command("-t nat -A " TABLE_WIFIDOG_AUTHSERVERS " -d %s -j ACCEPT", auth_server->last_ip);
178            }
179    }
180
181}
182
183/** Initialize the firewall rules
184 */
185int
186iptables_fw_init(void)
187{
188    s_config *config;
189         char * gw_interface = NULL;
190         char * gw_address = NULL;
191         char * ext_interface = NULL;
192         int gw_port = 0;
193     t_trusted_mac *p;
194   
195    fw_quiet = 0;
196
197         LOCK_CONFIG();
198    config = config_get_config();
199         gw_interface = safe_strdup(config->gw_interface);
200         gw_address = safe_strdup(config->gw_address);
201         gw_port = config->gw_port;
202     if (config->external_interface) {
203            ext_interface = safe_strdup(config->external_interface);
204     } else {
205            ext_interface = get_ext_iface();
206     }
207         UNLOCK_CONFIG();
208   
209         /*
210          *
211          * Everything in the MANGLE table
212          *
213          */
214
215                        /* Create new chains */
216                        iptables_do_command("-t mangle -N " TABLE_WIFIDOG_TRUSTED);
217                        iptables_do_command("-t mangle -N " TABLE_WIFIDOG_OUTGOING);
218                        iptables_do_command("-t mangle -N " TABLE_WIFIDOG_INCOMING);
219
220                        /* Assign links and rules to these new chains */
221                        iptables_do_command("-t mangle -I PREROUTING 1 -i %s -j " TABLE_WIFIDOG_OUTGOING, gw_interface);
222                        iptables_do_command("-t mangle -I PREROUTING 1 -i %s -j " TABLE_WIFIDOG_TRUSTED, gw_interface);//this rule will be inserted before the prior one
223                        iptables_do_command("-t mangle -I POSTROUTING 1 -o %s -j " TABLE_WIFIDOG_INCOMING, gw_interface);
224
225            for (p = config->trustedmaclist; p != NULL; p = p->next)
226                iptables_do_command("-t mangle -A " TABLE_WIFIDOG_TRUSTED " -m mac --mac-source %s -j MARK --set-mark %d", p->mac, FW_MARK_KNOWN);
227
228         /*
229          *
230          * Everything in the NAT table
231          *
232          */
233
234                        /* Create new chains */
235                        iptables_do_command("-t nat -N " TABLE_WIFIDOG_OUTGOING);
236                        iptables_do_command("-t nat -N " TABLE_WIFIDOG_WIFI_TO_ROUTER);
237                        iptables_do_command("-t nat -N " TABLE_WIFIDOG_WIFI_TO_INTERNET);
238                        iptables_do_command("-t nat -N " TABLE_WIFIDOG_GLOBAL);
239                        iptables_do_command("-t nat -N " TABLE_WIFIDOG_UNKNOWN);
240                        iptables_do_command("-t nat -N " TABLE_WIFIDOG_AUTHSERVERS);
241
242                        /* Assign links and rules to these new chains */
243                        iptables_do_command("-t nat -A PREROUTING -i %s -j " TABLE_WIFIDOG_OUTGOING, gw_interface);
244
245                        iptables_do_command("-t nat -A " TABLE_WIFIDOG_OUTGOING " -d %s -j " TABLE_WIFIDOG_WIFI_TO_ROUTER, gw_address);
246                        iptables_do_command("-t nat -A " TABLE_WIFIDOG_WIFI_TO_ROUTER " -j ACCEPT");
247
248                        iptables_do_command("-t nat -A " TABLE_WIFIDOG_OUTGOING " -j " TABLE_WIFIDOG_WIFI_TO_INTERNET);
249                        iptables_do_command("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j ACCEPT", FW_MARK_KNOWN);
250                        iptables_do_command("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j ACCEPT", FW_MARK_PROBATION);
251                        iptables_do_command("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_UNKNOWN);
252
253                        iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -j " TABLE_WIFIDOG_AUTHSERVERS);
254                        iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -j " TABLE_WIFIDOG_GLOBAL);
255                        iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -p tcp --dport 80 -j REDIRECT --to-ports %d", gw_port);
256
257
258         /*
259          *
260          * Everything in the FILTER table
261          *
262          */
263
264                        /* Create new chains */
265                        iptables_do_command("-t filter -N " TABLE_WIFIDOG_WIFI_TO_INTERNET);
266                        iptables_do_command("-t filter -N " TABLE_WIFIDOG_AUTHSERVERS);
267                        iptables_do_command("-t filter -N " TABLE_WIFIDOG_LOCKED);
268                        iptables_do_command("-t filter -N " TABLE_WIFIDOG_GLOBAL);
269                        iptables_do_command("-t filter -N " TABLE_WIFIDOG_VALIDATE);
270                        iptables_do_command("-t filter -N " TABLE_WIFIDOG_KNOWN);
271                        iptables_do_command("-t filter -N " TABLE_WIFIDOG_UNKNOWN);
272
273                        /* Assign links and rules to these new chains */
274
275            /* Insert at the beginning */
276                        iptables_do_command("-t filter -I FORWARD -i %s -j " TABLE_WIFIDOG_WIFI_TO_INTERNET, gw_interface);
277
278
279                        iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m state --state INVALID -j DROP");
280
281                        /* XXX: Why this? it means that connections setup after authentication
282                           stay open even after the connection is done...
283                           iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m state --state RELATED,ESTABLISHED -j ACCEPT");*/
284
285                        //Won't this rule NEVER match anyway?!?!? benoitg, 2007-06-23
286                        //iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -i %s -m state --state NEW -j DROP", ext_interface);
287           
288            /* TCPMSS rule for PPPoE */
289                        iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -o %s -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu", ext_interface);
290
291                        iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_AUTHSERVERS);
292                        iptables_fw_set_authservers();
293
294                        iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j " TABLE_WIFIDOG_LOCKED, FW_MARK_LOCKED);
295                        iptables_load_ruleset("filter", "locked-users", TABLE_WIFIDOG_LOCKED);
296
297                        iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_GLOBAL);
298                        iptables_load_ruleset("filter", "global", TABLE_WIFIDOG_GLOBAL);
299                        iptables_load_ruleset("nat", "global", TABLE_WIFIDOG_GLOBAL);
300
301                        iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j " TABLE_WIFIDOG_VALIDATE, FW_MARK_PROBATION);
302                        iptables_load_ruleset("filter", "validating-users", TABLE_WIFIDOG_VALIDATE);
303
304                        iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j " TABLE_WIFIDOG_KNOWN, FW_MARK_KNOWN);
305                        iptables_load_ruleset("filter", "known-users", TABLE_WIFIDOG_KNOWN);
306   
307                        iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_UNKNOWN);
308                        iptables_load_ruleset("filter", "unknown-users", TABLE_WIFIDOG_UNKNOWN);
309                        iptables_do_command("-t filter -A " TABLE_WIFIDOG_UNKNOWN " -j REJECT --reject-with icmp-port-unreachable");
310
311        free(gw_interface);
312        free(gw_address);
313
314    return 1;
315}
316
317/** Remove the firewall rules
318 * This is used when we do a clean shutdown of WiFiDog and when it starts to make
319 * sure there are no rules left over
320 */
321int
322iptables_fw_destroy(void)
323{
324    fw_quiet = 1;
325
326         debug(LOG_DEBUG, "Destroying our iptables entries");
327
328         /*
329          *
330          * Everything in the MANGLE table
331          *
332          */
333         debug(LOG_DEBUG, "Destroying chains in the MANGLE table");
334         iptables_fw_destroy_mention("mangle", "PREROUTING", TABLE_WIFIDOG_TRUSTED);
335         iptables_fw_destroy_mention("mangle", "PREROUTING", TABLE_WIFIDOG_OUTGOING);
336         iptables_fw_destroy_mention("mangle", "POSTROUTING", TABLE_WIFIDOG_INCOMING);
337    iptables_do_command("-t mangle -F " TABLE_WIFIDOG_TRUSTED);
338    iptables_do_command("-t mangle -F " TABLE_WIFIDOG_OUTGOING);
339    iptables_do_command("-t mangle -F " TABLE_WIFIDOG_INCOMING);
340    iptables_do_command("-t mangle -X " TABLE_WIFIDOG_TRUSTED);
341    iptables_do_command("-t mangle -X " TABLE_WIFIDOG_OUTGOING);
342    iptables_do_command("-t mangle -X " TABLE_WIFIDOG_INCOMING);
343
344        /*
345         *
346         * Everything in the NAT table
347         *
348         */
349        debug(LOG_DEBUG, "Destroying chains in the NAT table");
350        iptables_fw_destroy_mention("nat", "PREROUTING", TABLE_WIFIDOG_OUTGOING);
351        iptables_do_command("-t nat -F " TABLE_WIFIDOG_AUTHSERVERS);
352    iptables_do_command("-t nat -F " TABLE_WIFIDOG_OUTGOING);
353    iptables_do_command("-t nat -F " TABLE_WIFIDOG_WIFI_TO_ROUTER);
354    iptables_do_command("-t nat -F " TABLE_WIFIDOG_WIFI_TO_INTERNET);
355    iptables_do_command("-t nat -F " TABLE_WIFIDOG_GLOBAL);
356    iptables_do_command("-t nat -F " TABLE_WIFIDOG_UNKNOWN);
357        iptables_do_command("-t nat -X " TABLE_WIFIDOG_AUTHSERVERS);
358    iptables_do_command("-t nat -X " TABLE_WIFIDOG_OUTGOING);
359    iptables_do_command("-t nat -X " TABLE_WIFIDOG_WIFI_TO_ROUTER);
360    iptables_do_command("-t nat -X " TABLE_WIFIDOG_WIFI_TO_INTERNET);
361    iptables_do_command("-t nat -X " TABLE_WIFIDOG_GLOBAL);
362    iptables_do_command("-t nat -X " TABLE_WIFIDOG_UNKNOWN);
363
364         /*
365          *
366          * Everything in the FILTER table
367          *
368          */
369         debug(LOG_DEBUG, "Destroying chains in the FILTER table");
370         iptables_fw_destroy_mention("filter", "FORWARD", TABLE_WIFIDOG_WIFI_TO_INTERNET);
371         iptables_do_command("-t filter -F " TABLE_WIFIDOG_WIFI_TO_INTERNET);
372         iptables_do_command("-t filter -F " TABLE_WIFIDOG_AUTHSERVERS);
373         iptables_do_command("-t filter -F " TABLE_WIFIDOG_LOCKED);
374         iptables_do_command("-t filter -F " TABLE_WIFIDOG_GLOBAL);
375         iptables_do_command("-t filter -F " TABLE_WIFIDOG_VALIDATE);
376         iptables_do_command("-t filter -F " TABLE_WIFIDOG_KNOWN);
377         iptables_do_command("-t filter -F " TABLE_WIFIDOG_UNKNOWN);
378         iptables_do_command("-t filter -X " TABLE_WIFIDOG_WIFI_TO_INTERNET);
379         iptables_do_command("-t filter -X " TABLE_WIFIDOG_AUTHSERVERS);
380         iptables_do_command("-t filter -X " TABLE_WIFIDOG_LOCKED);
381         iptables_do_command("-t filter -X " TABLE_WIFIDOG_GLOBAL);
382         iptables_do_command("-t filter -X " TABLE_WIFIDOG_VALIDATE);
383         iptables_do_command("-t filter -X " TABLE_WIFIDOG_KNOWN);
384         iptables_do_command("-t filter -X " TABLE_WIFIDOG_UNKNOWN);
385
386    return 1;
387}
388
389/*
390 * Helper for iptables_fw_destroy
391 * @param table The table to search
392 * @param chain The chain in that table to search
393 * @param mention A word to find and delete in rules in the given table+chain
394 */
395int
396iptables_fw_destroy_mention(
397                char * table,
398                char * chain,
399                char * mention
400) {
401        FILE *p = NULL;
402        char *command = NULL;
403        char *command2 = NULL;
404        char line[MAX_BUF];
405        char rulenum[10];
406        int deleted = 0;
407
408        debug(LOG_DEBUG, "Attempting to destroy all mention of %s from %s.%s", mention, table, chain);
409
410        safe_asprintf(&command, "iptables -t %s -L %s -n --line-numbers -v", table, chain);
411
412        if ((p = popen(command, "r"))) {
413                /* Skip first 2 lines */
414                while (!feof(p) && fgetc(p) != '\n');
415                while (!feof(p) && fgetc(p) != '\n');
416                /* Loop over entries */
417                while (fgets(line, sizeof(line), p)) {
418                        /* Look for mention */
419                        if (strstr(line, mention)) {
420                                /* Found mention - Get the rule number into rulenum*/
421                                if (sscanf(line, "%9[0-9]", rulenum) == 1) {
422                                        /* Delete the rule: */
423                                        debug(LOG_DEBUG, "Deleting rule %s from %s.%s because it mentions %s", rulenum, table, chain, mention);
424                                        safe_asprintf(&command2, "-t %s -D %s %s", table, chain, rulenum);
425                                        iptables_do_command(command2);
426                                        free(command2);
427                                        deleted = 1;
428                                        /* Do not keep looping - the captured rulenums will no longer be accurate */
429                                        break;
430                                }
431                        }
432                }
433                pclose(p);
434        }
435
436        free(command);
437
438        if (deleted) {
439                /* Recurse just in case there are more in the same table+chain */
440                iptables_fw_destroy_mention(table, chain, mention);
441        }
442
443        return (deleted);
444}
445
446/** Set if a specific client has access through the firewall */
447int
448iptables_fw_access(fw_access_t type, char *ip, char *mac, int tag)
449{
450    int rc;
451
452    fw_quiet = 0;
453
454    switch(type) {
455        case FW_ACCESS_ALLOW:
456            iptables_do_command("-t mangle -A " TABLE_WIFIDOG_OUTGOING " -s %s -m mac --mac-source %s -j MARK --set-mark %d", ip, mac, tag);
457            rc = iptables_do_command("-t mangle -A " TABLE_WIFIDOG_INCOMING " -d %s -j ACCEPT", ip);
458            break;
459        case FW_ACCESS_DENY:
460            iptables_do_command("-t mangle -D " TABLE_WIFIDOG_OUTGOING " -s %s -m mac --mac-source %s -j MARK --set-mark %d", ip, mac, tag);
461            rc = iptables_do_command("-t mangle -D " TABLE_WIFIDOG_INCOMING " -d %s -j DROP", ip);
462            break;
463        default:
464            rc = -1;
465            break;
466    }
467
468    return rc;
469}
470
471/** Update the counters of all the clients in the client list */
472int
473iptables_fw_counters_update(void)
474{
475    FILE *output;
476    char *script,
477        ip[16],
478        rc;
479    unsigned long long int counter;
480    t_client *p1;
481         struct in_addr tempaddr;
482
483    /* Look for outgoing traffic */
484    safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " TABLE_WIFIDOG_OUTGOING);
485    output = popen(script, "r");
486    free(script);
487    if (!output) {
488        debug(LOG_ERR, "popen(): %s", strerror(errno));
489        return -1;
490    }
491
492    /* skip the first two lines */
493    while (('\n' != fgetc(output)) && !feof(output))
494        ;
495    while (('\n' != fgetc(output)) && !feof(output))
496        ;
497    while (output && !(feof(output))) {
498        rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %15[0-9.] %*s %*s %*s %*s %*s 0x%*u", &counter, ip);
499        if (2 == rc && EOF != rc) {
500                          /* Sanity*/
501                          if (!inet_aton(ip, &tempaddr)) {
502                                  debug(LOG_WARNING, "I was supposed to read an IP address but instead got [%s] - ignoring it", ip);
503                                  continue;
504                          }
505            debug(LOG_DEBUG, "Outgoing %s Bytes=%llu", ip, counter);
506            LOCK_CLIENT_LIST();
507            if ((p1 = client_list_find_by_ip(ip))) {
508                if ((p1->counters.outgoing - p1->counters.outgoing_history) < counter) {
509                    p1->counters.outgoing = p1->counters.outgoing_history + counter;
510                    p1->counters.last_updated = time(NULL);
511                    debug(LOG_DEBUG, "%s - Updated counter.outgoing to %llu bytes", ip, counter);
512                }
513            } else {
514                debug(LOG_ERR, "Could not find %s in client list", ip);
515            }
516            UNLOCK_CLIENT_LIST();
517        }
518    }
519    pclose(output);
520
521    /* Look for incoming traffic */
522    safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " TABLE_WIFIDOG_INCOMING);
523    output = popen(script, "r");
524    free(script);
525    if (!output) {
526        debug(LOG_ERR, "popen(): %s", strerror(errno));
527        return -1;
528    }
529
530    /* skip the first two lines */
531    while (('\n' != fgetc(output)) && !feof(output))
532        ;
533    while (('\n' != fgetc(output)) && !feof(output))
534        ;
535    while (output && !(feof(output))) {
536        rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %*s %15[0-9.]", &counter, ip);
537        if (2 == rc && EOF != rc) {
538                          /* Sanity*/
539                          if (!inet_aton(ip, &tempaddr)) {
540                                  debug(LOG_WARNING, "I was supposed to read an IP address but instead got [%s] - ignoring it", ip);
541                                  continue;
542                          }
543            debug(LOG_DEBUG, "Incoming %s Bytes=%llu", ip, counter);
544            LOCK_CLIENT_LIST();
545            if ((p1 = client_list_find_by_ip(ip))) {
546                if ((p1->counters.incoming - p1->counters.incoming_history) < counter) {
547                    p1->counters.incoming = p1->counters.incoming_history + counter;
548                    debug(LOG_DEBUG, "%s - Updated counter.incoming to %llu bytes", ip, counter);
549                }
550            } else {
551                debug(LOG_ERR, "Could not find %s in client list", ip);
552            }
553            UNLOCK_CLIENT_LIST();
554        }
555    }
556    pclose(output);
557
558    return 1;
559}
Note: See TracBrowser for help on using the browser.