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

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