fw_iptables.c

00001 /********************************************************************\
00002  * This program is free software; you can redistribute it and/or    *
00003  * modify it under the terms of the GNU General Public License as   *
00004  * published by the Free Software Foundation; either version 2 of   *
00005  * the License, or (at your option) any later version.              *
00006  *                                                                  *
00007  * This program is distributed in the hope that it will be useful,  *
00008  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00009  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00010  * GNU General Public License for more details.                     *
00011  *                                                                  *
00012  * You should have received a copy of the GNU General Public License*
00013  * along with this program; if not, contact:                        *
00014  *                                                                  *
00015  * Free Software Foundation           Voice:  +1-617-542-5942       *
00016  * 59 Temple Place - Suite 330        Fax:    +1-617-542-2652       *
00017  * Boston, MA  02111-1307,  USA       gnu@gnu.org                   *
00018  *                                                                  *
00019  \********************************************************************/
00020 
00021 /* $Id: fw_iptables.c 1241 2007-06-24 04:13:13Z benoitg $ */
00028 #define _GNU_SOURCE
00029 
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <stdarg.h>
00033 #include <syslog.h>
00034 #include <errno.h>
00035 #include <string.h>
00036 #include <pthread.h>
00037 #include <sys/socket.h>
00038 #include <netinet/in.h>
00039 #include <arpa/inet.h>
00040 
00041 #include "common.h"
00042 
00043 #include "safe.h"
00044 #include "conf.h"
00045 #include "fw_iptables.h"
00046 #include "firewall.h"
00047 #include "debug.h"
00048 #include "util.h"
00049 #include "client_list.h"
00050 
00051 static int iptables_do_command(char *format, ...);
00052 static char *iptables_compile(char *, char *, t_firewall_rule *);
00053 static void iptables_load_ruleset(char *, char *, char *);
00054 
00055 extern pthread_mutex_t  client_list_mutex;
00056 extern pthread_mutex_t  config_mutex;
00057 
00060 static int fw_quiet = 0;
00061 
00064 static int
00065 iptables_do_command(char *format, ...)
00066 {
00067     va_list vlist;
00068     char *fmt_cmd,
00069         *cmd;
00070     int rc;
00071 
00072     va_start(vlist, format);
00073     safe_vasprintf(&fmt_cmd, format, vlist);
00074          va_end(vlist);
00075 
00076     safe_asprintf(&cmd, "iptables %s", fmt_cmd);
00077 
00078     free(fmt_cmd);
00079 
00080     debug(LOG_DEBUG, "Executing command: %s", cmd);
00081         
00082     rc = execute(cmd, fw_quiet);
00083 
00084     free(cmd);
00085 
00086     return rc;
00087 }
00088 
00097 static char *
00098 iptables_compile(char * table, char *chain, t_firewall_rule *rule)
00099 {
00100     char        command[MAX_BUF],
00101                 *mode;
00102     
00103     memset(command, 0, MAX_BUF);
00104     
00105     if (rule->block_allow == 1) {
00106         mode = safe_strdup("ACCEPT");
00107     } else {
00108         mode = safe_strdup("REJECT");
00109     }
00110     
00111     snprintf(command, sizeof(command),  "-t %s -A %s ",table, chain);
00112     if (rule->mask != NULL) {
00113         snprintf((command + strlen(command)), (sizeof(command) - 
00114                 strlen(command)), "-d %s ", rule->mask);
00115     }
00116     if (rule->protocol != NULL) {
00117         snprintf((command + strlen(command)), (sizeof(command) -
00118                 strlen(command)), "-p %s ", rule->protocol);
00119     }
00120     if (rule->port != NULL) {
00121         snprintf((command + strlen(command)), (sizeof(command) -
00122                 strlen(command)), "--dport %s ", rule->port);
00123     }
00124     snprintf((command + strlen(command)), (sizeof(command) - 
00125             strlen(command)), "-j %s", mode);
00126     
00127     free(mode);
00128 
00129     /* XXX The buffer command, an automatic variable, will get cleaned
00130      * off of the stack when we return, so we strdup() it. */
00131     return(safe_strdup(command));
00132 }
00133 
00141 static void
00142 iptables_load_ruleset(char * table, char *ruleset, char *chain)
00143 {
00144         t_firewall_rule         *rule;
00145         char                    *cmd;
00146 
00147         debug(LOG_DEBUG, "Load ruleset %s into table %s, chain %s", ruleset, table, chain);
00148         
00149         for (rule = get_ruleset(ruleset); rule != NULL; rule = rule->next) {
00150                 cmd = iptables_compile(table, chain, rule);
00151                 debug(LOG_DEBUG, "Loading rule \"%s\" into table %s, chain %s", cmd, table, chain);
00152                 iptables_do_command(cmd);
00153                 free(cmd);
00154         }
00155 
00156         debug(LOG_DEBUG, "Ruleset %s loaded into table %s, chain %s", ruleset, table, chain);
00157 }
00158 
00159 void
00160 iptables_fw_clear_authservers(void)
00161 {
00162     iptables_do_command("-t filter -F " TABLE_WIFIDOG_AUTHSERVERS);
00163     iptables_do_command("-t nat -F " TABLE_WIFIDOG_AUTHSERVERS);
00164 }
00165 
00166 void
00167 iptables_fw_set_authservers(void)
00168 {
00169     s_config *config;
00170     t_auth_serv *auth_server;
00171    
00172     config = config_get_config();
00173     
00174     for (auth_server = config->auth_servers; auth_server != NULL; auth_server = auth_server->next) {
00175             if (auth_server->last_ip && strcmp(auth_server->last_ip, "0.0.0.0") != 0) {
00176                 iptables_do_command("-t filter -A " TABLE_WIFIDOG_AUTHSERVERS " -d %s -j ACCEPT", auth_server->last_ip);
00177                 iptables_do_command("-t nat -A " TABLE_WIFIDOG_AUTHSERVERS " -d %s -j ACCEPT", auth_server->last_ip);
00178             }
00179     }
00180 
00181 }
00182 
00185 int
00186 iptables_fw_init(void)
00187 {
00188     s_config *config;
00189          char * gw_interface = NULL;
00190          char * gw_address = NULL;
00191          char * ext_interface = NULL;
00192          int gw_port = 0;
00193      t_trusted_mac *p;
00194    
00195     fw_quiet = 0;
00196 
00197          LOCK_CONFIG();
00198     config = config_get_config();
00199          gw_interface = safe_strdup(config->gw_interface);
00200          gw_address = safe_strdup(config->gw_address);
00201          gw_port = config->gw_port;
00202      if (config->external_interface) {
00203             ext_interface = safe_strdup(config->external_interface);
00204      } else {
00205             ext_interface = get_ext_iface();
00206      }
00207          UNLOCK_CONFIG();
00208     
00209          /*
00210           *
00211           * Everything in the MANGLE table
00212           *
00213           */
00214 
00215                         /* Create new chains */
00216                         iptables_do_command("-t mangle -N " TABLE_WIFIDOG_TRUSTED);
00217                         iptables_do_command("-t mangle -N " TABLE_WIFIDOG_OUTGOING);
00218                         iptables_do_command("-t mangle -N " TABLE_WIFIDOG_INCOMING);
00219 
00220                         /* Assign links and rules to these new chains */
00221                         iptables_do_command("-t mangle -I PREROUTING 1 -i %s -j " TABLE_WIFIDOG_OUTGOING, gw_interface);
00222                         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
00223                         iptables_do_command("-t mangle -I POSTROUTING 1 -o %s -j " TABLE_WIFIDOG_INCOMING, gw_interface);
00224 
00225             for (p = config->trustedmaclist; p != NULL; p = p->next)
00226                 iptables_do_command("-t mangle -A " TABLE_WIFIDOG_TRUSTED " -m mac --mac-source %s -j MARK --set-mark %d", p->mac, FW_MARK_KNOWN);
00227 
00228          /*
00229           *
00230           * Everything in the NAT table
00231           *
00232           */
00233 
00234                         /* Create new chains */
00235                         iptables_do_command("-t nat -N " TABLE_WIFIDOG_OUTGOING);
00236                         iptables_do_command("-t nat -N " TABLE_WIFIDOG_WIFI_TO_ROUTER);
00237                         iptables_do_command("-t nat -N " TABLE_WIFIDOG_WIFI_TO_INTERNET);
00238                         iptables_do_command("-t nat -N " TABLE_WIFIDOG_GLOBAL);
00239                         iptables_do_command("-t nat -N " TABLE_WIFIDOG_UNKNOWN);
00240                         iptables_do_command("-t nat -N " TABLE_WIFIDOG_AUTHSERVERS);
00241 
00242                         /* Assign links and rules to these new chains */
00243                         iptables_do_command("-t nat -A PREROUTING -i %s -j " TABLE_WIFIDOG_OUTGOING, gw_interface);
00244 
00245                         iptables_do_command("-t nat -A " TABLE_WIFIDOG_OUTGOING " -d %s -j " TABLE_WIFIDOG_WIFI_TO_ROUTER, gw_address);
00246                         iptables_do_command("-t nat -A " TABLE_WIFIDOG_WIFI_TO_ROUTER " -j ACCEPT");
00247 
00248                         iptables_do_command("-t nat -A " TABLE_WIFIDOG_OUTGOING " -j " TABLE_WIFIDOG_WIFI_TO_INTERNET);
00249                         iptables_do_command("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j ACCEPT", FW_MARK_KNOWN);
00250                         iptables_do_command("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j ACCEPT", FW_MARK_PROBATION);
00251                         iptables_do_command("-t nat -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_UNKNOWN);
00252 
00253                         iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -j " TABLE_WIFIDOG_AUTHSERVERS);
00254                         iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -j " TABLE_WIFIDOG_GLOBAL);
00255                         iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -p tcp --dport 80 -j REDIRECT --to-ports %d", gw_port);
00256 
00257 
00258          /*
00259           *
00260           * Everything in the FILTER table
00261           *
00262           */
00263 
00264                         /* Create new chains */
00265                         iptables_do_command("-t filter -N " TABLE_WIFIDOG_WIFI_TO_INTERNET);
00266                         iptables_do_command("-t filter -N " TABLE_WIFIDOG_AUTHSERVERS);
00267                         iptables_do_command("-t filter -N " TABLE_WIFIDOG_LOCKED);
00268                         iptables_do_command("-t filter -N " TABLE_WIFIDOG_GLOBAL);
00269                         iptables_do_command("-t filter -N " TABLE_WIFIDOG_VALIDATE);
00270                         iptables_do_command("-t filter -N " TABLE_WIFIDOG_KNOWN);
00271                         iptables_do_command("-t filter -N " TABLE_WIFIDOG_UNKNOWN);
00272 
00273                         /* Assign links and rules to these new chains */
00274 
00275             /* Insert at the beginning */
00276                         iptables_do_command("-t filter -I FORWARD -i %s -j " TABLE_WIFIDOG_WIFI_TO_INTERNET, gw_interface);
00277 
00278 
00279                         iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m state --state INVALID -j DROP");
00280 
00281                         /* XXX: Why this? it means that connections setup after authentication
00282                            stay open even after the connection is done... 
00283                            iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m state --state RELATED,ESTABLISHED -j ACCEPT");*/
00284 
00285                         //Won't this rule NEVER match anyway?!?!? benoitg, 2007-06-23
00286                         //iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -i %s -m state --state NEW -j DROP", ext_interface);
00287             
00288             /* TCPMSS rule for PPPoE */
00289                         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);
00290 
00291                         iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_AUTHSERVERS);
00292                         iptables_fw_set_authservers();
00293 
00294                         iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j " TABLE_WIFIDOG_LOCKED, FW_MARK_LOCKED);
00295                         iptables_load_ruleset("filter", "locked-users", TABLE_WIFIDOG_LOCKED);
00296 
00297                         iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_GLOBAL);
00298                         iptables_load_ruleset("filter", "global", TABLE_WIFIDOG_GLOBAL);
00299                         iptables_load_ruleset("nat", "global", TABLE_WIFIDOG_GLOBAL);
00300 
00301                         iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j " TABLE_WIFIDOG_VALIDATE, FW_MARK_PROBATION);
00302                         iptables_load_ruleset("filter", "validating-users", TABLE_WIFIDOG_VALIDATE);
00303 
00304                         iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -m mark --mark 0x%u -j " TABLE_WIFIDOG_KNOWN, FW_MARK_KNOWN);
00305                         iptables_load_ruleset("filter", "known-users", TABLE_WIFIDOG_KNOWN);
00306     
00307                         iptables_do_command("-t filter -A " TABLE_WIFIDOG_WIFI_TO_INTERNET " -j " TABLE_WIFIDOG_UNKNOWN);
00308                         iptables_load_ruleset("filter", "unknown-users", TABLE_WIFIDOG_UNKNOWN);
00309                         iptables_do_command("-t filter -A " TABLE_WIFIDOG_UNKNOWN " -j REJECT --reject-with icmp-port-unreachable");
00310 
00311         free(gw_interface);
00312         free(gw_address);
00313 
00314     return 1;
00315 }
00316 
00321 int
00322 iptables_fw_destroy(void)
00323 {
00324     fw_quiet = 1;
00325 
00326          debug(LOG_DEBUG, "Destroying our iptables entries");
00327 
00328          /*
00329           *
00330           * Everything in the MANGLE table
00331           *
00332           */
00333          debug(LOG_DEBUG, "Destroying chains in the MANGLE table");
00334          iptables_fw_destroy_mention("mangle", "PREROUTING", TABLE_WIFIDOG_TRUSTED);
00335          iptables_fw_destroy_mention("mangle", "PREROUTING", TABLE_WIFIDOG_OUTGOING);
00336          iptables_fw_destroy_mention("mangle", "POSTROUTING", TABLE_WIFIDOG_INCOMING);
00337     iptables_do_command("-t mangle -F " TABLE_WIFIDOG_TRUSTED);
00338     iptables_do_command("-t mangle -F " TABLE_WIFIDOG_OUTGOING);
00339     iptables_do_command("-t mangle -F " TABLE_WIFIDOG_INCOMING);
00340     iptables_do_command("-t mangle -X " TABLE_WIFIDOG_TRUSTED);
00341     iptables_do_command("-t mangle -X " TABLE_WIFIDOG_OUTGOING);
00342     iptables_do_command("-t mangle -X " TABLE_WIFIDOG_INCOMING);
00343 
00344         /*
00345          *
00346          * Everything in the NAT table
00347          *
00348          */
00349         debug(LOG_DEBUG, "Destroying chains in the NAT table");
00350         iptables_fw_destroy_mention("nat", "PREROUTING", TABLE_WIFIDOG_OUTGOING);
00351         iptables_do_command("-t nat -F " TABLE_WIFIDOG_AUTHSERVERS);
00352     iptables_do_command("-t nat -F " TABLE_WIFIDOG_OUTGOING);
00353     iptables_do_command("-t nat -F " TABLE_WIFIDOG_WIFI_TO_ROUTER);
00354     iptables_do_command("-t nat -F " TABLE_WIFIDOG_WIFI_TO_INTERNET);
00355     iptables_do_command("-t nat -F " TABLE_WIFIDOG_GLOBAL);
00356     iptables_do_command("-t nat -F " TABLE_WIFIDOG_UNKNOWN);
00357         iptables_do_command("-t nat -X " TABLE_WIFIDOG_AUTHSERVERS);
00358     iptables_do_command("-t nat -X " TABLE_WIFIDOG_OUTGOING);
00359     iptables_do_command("-t nat -X " TABLE_WIFIDOG_WIFI_TO_ROUTER);
00360     iptables_do_command("-t nat -X " TABLE_WIFIDOG_WIFI_TO_INTERNET);
00361     iptables_do_command("-t nat -X " TABLE_WIFIDOG_GLOBAL);
00362     iptables_do_command("-t nat -X " TABLE_WIFIDOG_UNKNOWN);
00363 
00364          /*
00365           *
00366           * Everything in the FILTER table
00367           *
00368           */
00369          debug(LOG_DEBUG, "Destroying chains in the FILTER table");
00370          iptables_fw_destroy_mention("filter", "FORWARD", TABLE_WIFIDOG_WIFI_TO_INTERNET);
00371          iptables_do_command("-t filter -F " TABLE_WIFIDOG_WIFI_TO_INTERNET);
00372          iptables_do_command("-t filter -F " TABLE_WIFIDOG_AUTHSERVERS);
00373          iptables_do_command("-t filter -F " TABLE_WIFIDOG_LOCKED);
00374          iptables_do_command("-t filter -F " TABLE_WIFIDOG_GLOBAL);
00375          iptables_do_command("-t filter -F " TABLE_WIFIDOG_VALIDATE);
00376          iptables_do_command("-t filter -F " TABLE_WIFIDOG_KNOWN);
00377          iptables_do_command("-t filter -F " TABLE_WIFIDOG_UNKNOWN);
00378          iptables_do_command("-t filter -X " TABLE_WIFIDOG_WIFI_TO_INTERNET);
00379          iptables_do_command("-t filter -X " TABLE_WIFIDOG_AUTHSERVERS);
00380          iptables_do_command("-t filter -X " TABLE_WIFIDOG_LOCKED);
00381          iptables_do_command("-t filter -X " TABLE_WIFIDOG_GLOBAL);
00382          iptables_do_command("-t filter -X " TABLE_WIFIDOG_VALIDATE);
00383          iptables_do_command("-t filter -X " TABLE_WIFIDOG_KNOWN);
00384          iptables_do_command("-t filter -X " TABLE_WIFIDOG_UNKNOWN);
00385 
00386     return 1;
00387 }
00388 
00389 /*
00390  * Helper for iptables_fw_destroy
00391  * @param table The table to search
00392  * @param chain The chain in that table to search
00393  * @param mention A word to find and delete in rules in the given table+chain
00394  */
00395 int
00396 iptables_fw_destroy_mention(
00397                 char * table,
00398                 char * chain,
00399                 char * mention
00400 ) {
00401         FILE *p = NULL;
00402         char *command = NULL;
00403         char *command2 = NULL;
00404         char line[MAX_BUF];
00405         char rulenum[10];
00406         int deleted = 0;
00407 
00408         debug(LOG_DEBUG, "Attempting to destroy all mention of %s from %s.%s", mention, table, chain);
00409 
00410         safe_asprintf(&command, "iptables -t %s -L %s -n --line-numbers -v", table, chain);
00411 
00412         if ((p = popen(command, "r"))) {
00413                 /* Skip first 2 lines */
00414                 while (!feof(p) && fgetc(p) != '\n');
00415                 while (!feof(p) && fgetc(p) != '\n');
00416                 /* Loop over entries */
00417                 while (fgets(line, sizeof(line), p)) {
00418                         /* Look for mention */
00419                         if (strstr(line, mention)) {
00420                                 /* Found mention - Get the rule number into rulenum*/
00421                                 if (sscanf(line, "%9[0-9]", rulenum) == 1) {
00422                                         /* Delete the rule: */
00423                                         debug(LOG_DEBUG, "Deleting rule %s from %s.%s because it mentions %s", rulenum, table, chain, mention);
00424                                         safe_asprintf(&command2, "-t %s -D %s %s", table, chain, rulenum);
00425                                         iptables_do_command(command2);
00426                                         free(command2);
00427                                         deleted = 1;
00428                                         /* Do not keep looping - the captured rulenums will no longer be accurate */
00429                                         break;
00430                                 }
00431                         }
00432                 }
00433                 pclose(p);
00434         }
00435 
00436         free(command);
00437 
00438         if (deleted) {
00439                 /* Recurse just in case there are more in the same table+chain */
00440                 iptables_fw_destroy_mention(table, chain, mention);
00441         }
00442 
00443         return (deleted);
00444 }
00445 
00447 int
00448 iptables_fw_access(fw_access_t type, char *ip, char *mac, int tag)
00449 {
00450     int rc;
00451 
00452     fw_quiet = 0;
00453 
00454     switch(type) {
00455         case FW_ACCESS_ALLOW:
00456             iptables_do_command("-t mangle -A " TABLE_WIFIDOG_OUTGOING " -s %s -m mac --mac-source %s -j MARK --set-mark %d", ip, mac, tag);
00457             rc = iptables_do_command("-t mangle -A " TABLE_WIFIDOG_INCOMING " -d %s -j ACCEPT", ip);
00458             break;
00459         case FW_ACCESS_DENY:
00460             iptables_do_command("-t mangle -D " TABLE_WIFIDOG_OUTGOING " -s %s -m mac --mac-source %s -j MARK --set-mark %d", ip, mac, tag);
00461             rc = iptables_do_command("-t mangle -D " TABLE_WIFIDOG_INCOMING " -d %s -j DROP", ip);
00462             break;
00463         default:
00464             rc = -1;
00465             break;
00466     }
00467 
00468     return rc;
00469 }
00470 
00472 int
00473 iptables_fw_counters_update(void)
00474 {
00475     FILE *output;
00476     char *script,
00477         ip[16],
00478         rc;
00479     unsigned long long int counter;
00480     t_client *p1;
00481          struct in_addr tempaddr;
00482 
00483     /* Look for outgoing traffic */
00484     safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " TABLE_WIFIDOG_OUTGOING);
00485     output = popen(script, "r");
00486     free(script);
00487     if (!output) {
00488         debug(LOG_ERR, "popen(): %s", strerror(errno));
00489         return -1;
00490     }
00491 
00492     /* skip the first two lines */
00493     while (('\n' != fgetc(output)) && !feof(output))
00494         ;
00495     while (('\n' != fgetc(output)) && !feof(output))
00496         ;
00497     while (output && !(feof(output))) {
00498         rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %15[0-9.] %*s %*s %*s %*s %*s 0x%*u", &counter, ip);
00499         if (2 == rc && EOF != rc) {
00500                           /* Sanity*/
00501                           if (!inet_aton(ip, &tempaddr)) {
00502                                   debug(LOG_WARNING, "I was supposed to read an IP address but instead got [%s] - ignoring it", ip);
00503                                   continue;
00504                           }
00505             debug(LOG_DEBUG, "Outgoing %s Bytes=%llu", ip, counter);
00506             LOCK_CLIENT_LIST();
00507             if ((p1 = client_list_find_by_ip(ip))) {
00508                 if ((p1->counters.outgoing - p1->counters.outgoing_history) < counter) {
00509                     p1->counters.outgoing = p1->counters.outgoing_history + counter;
00510                     p1->counters.last_updated = time(NULL);
00511                     debug(LOG_DEBUG, "%s - Updated counter.outgoing to %llu bytes", ip, counter);
00512                 }
00513             } else {
00514                 debug(LOG_ERR, "Could not find %s in client list", ip);
00515             }
00516             UNLOCK_CLIENT_LIST();
00517         }
00518     }
00519     pclose(output);
00520 
00521     /* Look for incoming traffic */
00522     safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " TABLE_WIFIDOG_INCOMING);
00523     output = popen(script, "r");
00524     free(script);
00525     if (!output) {
00526         debug(LOG_ERR, "popen(): %s", strerror(errno));
00527         return -1;
00528     }
00529 
00530     /* skip the first two lines */
00531     while (('\n' != fgetc(output)) && !feof(output))
00532         ;
00533     while (('\n' != fgetc(output)) && !feof(output))
00534         ;
00535     while (output && !(feof(output))) {
00536         rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %*s %15[0-9.]", &counter, ip);
00537         if (2 == rc && EOF != rc) {
00538                           /* Sanity*/
00539                           if (!inet_aton(ip, &tempaddr)) {
00540                                   debug(LOG_WARNING, "I was supposed to read an IP address but instead got [%s] - ignoring it", ip);
00541                                   continue;
00542                           }
00543             debug(LOG_DEBUG, "Incoming %s Bytes=%llu", ip, counter);
00544             LOCK_CLIENT_LIST();
00545             if ((p1 = client_list_find_by_ip(ip))) {
00546                 if ((p1->counters.incoming - p1->counters.incoming_history) < counter) {
00547                     p1->counters.incoming = p1->counters.incoming_history + counter;
00548                     debug(LOG_DEBUG, "%s - Updated counter.incoming to %llu bytes", ip, counter);
00549                 }
00550             } else {
00551                 debug(LOG_ERR, "Could not find %s in client list", ip);
00552             }
00553             UNLOCK_CLIENT_LIST();
00554         }
00555     }
00556     pclose(output);
00557 
00558     return 1;
00559 }

Generated on Sun Jun 24 00:29:52 2007 for WifiDog by  doxygen 1.5.1