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

Revision 1373, 20.0 KB (checked in by wichert, 5 years ago)

Clean up compiler warnings

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