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

Revision 170, 11.0 KB (checked in by aprilp, 9 years ago)

Renamed iptables.[ch] to fw_iptables.[ch]

  • 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/* $Header$ */
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
38#include "conf.h"
39#include "fw_iptables.h"
40#include "firewall.h"
41#include "debug.h"
42#include "util.h"
43#include "client_list.h"
44
45static int iptables_do_command(char *format, ...);
46
47extern pthread_mutex_t  client_list_mutex;
48
49/**
50Used to supress the error output of the firewall during destruction */ 
51static int fw_quiet = 0;
52
53/** @internal */
54static int
55iptables_do_command(char *format, ...)
56{
57    va_list vlist;
58    char *fmt_cmd,
59        *cmd;
60    int rc;
61
62    va_start(vlist, format);
63    vasprintf(&fmt_cmd, format, vlist);
64    asprintf(&cmd, "iptables %s", fmt_cmd);
65
66    rc = execute(cmd, fw_quiet);
67
68    free(fmt_cmd);
69    free(cmd);
70
71    return rc;
72}
73
74/** Initialize the firewall rules
75 */
76int
77iptables_fw_init(void)
78{
79  s_config *config = config_get_config();
80    fw_quiet = 0;
81    iptables_do_command("-t nat -N " TABLE_WIFIDOG_VALIDATE);
82    iptables_do_command("-t nat -A " TABLE_WIFIDOG_VALIDATE " -d %s -j ACCEPT", config->gw_address);
83    iptables_do_command("-t nat -A " TABLE_WIFIDOG_VALIDATE " -d %s -j ACCEPT", config->authserv_hostname);
84    iptables_do_command("-t nat -A " TABLE_WIFIDOG_VALIDATE " -p udp --dport 67 -j ACCEPT");
85    iptables_do_command("-t nat -A " TABLE_WIFIDOG_VALIDATE " -p tcp --dport 67 -j ACCEPT");
86    iptables_do_command("-t nat -A " TABLE_WIFIDOG_VALIDATE " -p udp --dport 53 -j ACCEPT");
87    iptables_do_command("-t nat -A " TABLE_WIFIDOG_VALIDATE " -p tcp --dport 80 -j ACCEPT");
88    iptables_do_command("-t nat -A " TABLE_WIFIDOG_VALIDATE " -p tcp --dport 110 -j ACCEPT");
89    iptables_do_command("-t nat -A " TABLE_WIFIDOG_VALIDATE " -p tcp --dport 995 -j ACCEPT");
90    iptables_do_command("-t nat -A " TABLE_WIFIDOG_VALIDATE " -p tcp --dport 143 -j ACCEPT");
91    iptables_do_command("-t nat -A " TABLE_WIFIDOG_VALIDATE " -p tcp --dport 993 -j ACCEPT");
92    iptables_do_command("-t nat -A " TABLE_WIFIDOG_VALIDATE " -p tcp --dport 220 -j ACCEPT");
93    iptables_do_command("-t nat -A " TABLE_WIFIDOG_VALIDATE " -p tcp --dport 993 -j ACCEPT");
94    iptables_do_command("-t nat -A " TABLE_WIFIDOG_VALIDATE " -p tcp --dport 443 -j ACCEPT");
95    iptables_do_command("-t nat -A " TABLE_WIFIDOG_VALIDATE " -j DROP");
96
97    iptables_do_command("-t nat -N " TABLE_WIFIDOG_UNKNOWN);
98    iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -d %s -j ACCEPT", config->gw_address);
99    iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -d %s -j ACCEPT", config->authserv_hostname);
100    iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -p udp --dport 67 -j ACCEPT");
101    iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -p tcp --dport 67 -j ACCEPT");
102    iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -p udp --dport 53 -j ACCEPT");
103    iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -p tcp --dport 80 -j REDIRECT --to-ports %d", config->gw_port);
104    iptables_do_command("-t nat -A " TABLE_WIFIDOG_UNKNOWN " -j DROP");
105
106    iptables_do_command("-t nat -N " TABLE_WIFIDOG_KNOWN);
107    iptables_do_command("-t nat -A " TABLE_WIFIDOG_KNOWN " -j ACCEPT");
108
109    iptables_do_command("-t nat -N " TABLE_WIFIDOG_LOCKED);
110    iptables_do_command("-t nat -A " TABLE_WIFIDOG_LOCKED " -j DROP");
111
112    iptables_do_command("-t nat -N " TABLE_WIFIDOG_CLASS);
113    iptables_do_command("-t nat -A " TABLE_WIFIDOG_CLASS " -i %s -m mark --mark 0x%u -j " TABLE_WIFIDOG_VALIDATE, config->gw_interface, FW_MARK_PROBATION);
114    iptables_do_command("-t nat -A " TABLE_WIFIDOG_CLASS " -i %s -m mark --mark 0x%u -j " TABLE_WIFIDOG_KNOWN, config->gw_interface, FW_MARK_KNOWN);
115    iptables_do_command("-t nat -A " TABLE_WIFIDOG_CLASS " -i %s -m mark --mark 0x%u -j " TABLE_WIFIDOG_LOCKED, config->gw_interface, FW_MARK_LOCKED);
116    iptables_do_command("-t nat -A " TABLE_WIFIDOG_CLASS " -i %s -j " TABLE_WIFIDOG_UNKNOWN, config->gw_interface);
117    iptables_do_command("-t nat -I PREROUTING 1 -i %s -j " TABLE_WIFIDOG_CLASS, config->gw_interface);
118
119    iptables_do_command("-t mangle -N " TABLE_WIFIDOG_OUTGOING);
120    iptables_do_command("-t mangle -I PREROUTING 1 -i %s -j " TABLE_WIFIDOG_OUTGOING, config->gw_interface);
121
122    iptables_do_command("-t mangle -N " TABLE_WIFIDOG_INCOMING);
123    iptables_do_command("-t mangle -I FORWARD 1 -i %s -j " TABLE_WIFIDOG_INCOMING, config->external_interface);
124
125    return 1;
126}
127
128/** Remove the firewall rules
129 * This is used when we do a clean shutdown of WiFiDog and when it starts to make
130 * sure there are no rules left over
131 */
132int
133iptables_fw_destroy(void)
134{
135    int rc;
136    s_config *config = config_get_config();
137
138    fw_quiet = 1;
139    iptables_do_command("-t nat -F " TABLE_WIFIDOG_CLASS);
140    iptables_do_command("-t mangle -F " TABLE_WIFIDOG_OUTGOING);
141    iptables_do_command("-t mangle -F " TABLE_WIFIDOG_INCOMING);
142
143    iptables_do_command("-t nat -F " TABLE_WIFIDOG_VALIDATE);
144    iptables_do_command("-t nat -F " TABLE_WIFIDOG_UNKNOWN);
145    iptables_do_command("-t nat -F " TABLE_WIFIDOG_KNOWN);
146    iptables_do_command("-t nat -F " TABLE_WIFIDOG_LOCKED);
147    iptables_do_command("-t nat -X " TABLE_WIFIDOG_VALIDATE);
148    iptables_do_command("-t nat -X " TABLE_WIFIDOG_UNKNOWN);
149    iptables_do_command("-t nat -X " TABLE_WIFIDOG_KNOWN);
150    iptables_do_command("-t nat -X " TABLE_WIFIDOG_LOCKED);
151
152    /* We loop in case wifidog has crashed and left some unwanted rules,
153     * maybe we shouldn't loop forever, we'll try anyway
154     */
155    rc = 0;
156    while (rc == 0) {
157        rc = iptables_do_command("-t nat -D PREROUTING -i %s -j " TABLE_WIFIDOG_CLASS, config->gw_interface);
158    }
159    iptables_do_command("-t nat -X " TABLE_WIFIDOG_CLASS);
160
161    rc = 0;
162    while (rc == 0) {
163        rc = iptables_do_command("-t mangle -D PREROUTING -i %s -j " TABLE_WIFIDOG_OUTGOING, config->gw_interface);
164    }
165    iptables_do_command("-t mangle -X " TABLE_WIFIDOG_OUTGOING);
166
167    rc = 0;
168    while (rc == 0) {
169        rc = iptables_do_command("-t mangle -D FORWARD -i %s -j " TABLE_WIFIDOG_INCOMING, config->external_interface);
170    }
171    iptables_do_command("-t mangle -X " TABLE_WIFIDOG_INCOMING);
172
173    return 1;
174}
175
176/** Set the firewall access for a specific client */
177int
178iptables_fw_access(fw_access_t type, char *ip, char *mac, int tag)
179{
180    int rc;
181
182    fw_quiet = 0;
183
184    switch(type) {
185        case FW_ACCESS_ALLOW:
186            iptables_do_command("-t mangle -A " TABLE_WIFIDOG_OUTGOING " -s %s -m mac --mac-source %s -j MARK --set-mark %d", ip, mac, tag);
187            rc = iptables_do_command("-t mangle -A " TABLE_WIFIDOG_INCOMING " -d %s -j ACCEPT", ip);
188            break;
189        case FW_ACCESS_DENY:
190            iptables_do_command("-t mangle -D " TABLE_WIFIDOG_OUTGOING " -s %s -m mac --mac-source %s -j MARK --set-mark %d", ip, mac, tag);
191            rc = iptables_do_command("-t mangle -D " TABLE_WIFIDOG_INCOMING " -d %s -j ACCEPT", ip);
192            break;
193        default:
194            rc = -1;
195            break;
196    }
197
198    return rc;
199}
200
201/** Update the counters of all the clients in the client list */
202int
203iptables_fw_counters_update(void)
204{
205    FILE *output;
206    char *script,
207        ip[16],
208        rc;
209    unsigned long int counter;
210    t_client *p1;
211
212    /* Look for outgoing traffic */
213    asprintf(&script, "%s %s", "iptables", "-v -x -t mangle -L " TABLE_WIFIDOG_OUTGOING);
214    if (!(output = popen(script, "r"))) {
215        debug(LOG_ERR, "popen(): %s", strerror(errno));
216        return -1;
217    }
218    free(script);
219
220    /* skip the first two lines */
221    while (('\n' != fgetc(output)) && !feof(output))
222        ;
223    while (('\n' != fgetc(output)) && !feof(output))
224        ;
225    while (output && !(feof(output))) {
226        rc = fscanf(output, "%*s %lu %*s %*s %*s %*s %*s %s %*s %*s %*s %*s %*s 0x%*u", &counter, ip);
227        if (2 == rc && EOF != rc) {
228            debug(LOG_DEBUG, "Outgoing %s Bytes=%ld", ip, counter);
229            pthread_mutex_lock(&client_list_mutex);
230            if ((p1 = client_list_find_by_ip(ip))) {
231                if (p1->counters.outgoing < counter) {
232                    p1->counters.outgoing = counter;
233                    p1->counters.last_updated = time(NULL);
234                    debug(LOG_DEBUG, "%s - Updated counter to %ld bytes", ip, counter);
235                }
236            } else {
237                debug(LOG_ERR, "Could not find %s in client list", ip);
238            }
239            pthread_mutex_unlock(&client_list_mutex);
240        }
241    }
242    pclose(output);
243
244    /* Look for incoming traffic */
245    asprintf(&script, "%s %s", "iptables", "-v -x -t mangle -L " TABLE_WIFIDOG_INCOMING);
246    if (!(output = popen(script, "r"))) {
247        debug(LOG_ERR, "popen(): %s", strerror(errno));
248        return -1;
249    }
250    free(script);
251
252    /* skip the first two lines */
253    while (('\n' != fgetc(output)) && !feof(output))
254        ;
255    while (('\n' != fgetc(output)) && !feof(output))
256        ;
257    while (output && !(feof(output))) {
258        rc = fscanf(output, "%*s %lu %*s %*s %*s %*s %*s %*s %s", &counter, ip);
259        if (2 == rc && EOF != rc) {
260            debug(LOG_DEBUG, "Incoming %s Bytes=%ld", ip, counter);
261            pthread_mutex_lock(&client_list_mutex);
262            if ((p1 = client_list_find_by_ip(ip))) {
263                if (p1->counters.incoming < counter) {
264                    p1->counters.incoming = counter;
265                    p1->counters.last_updated = time(NULL);
266                    debug(LOG_DEBUG, "%s - Updated counter to %ld bytes", ip, counter);
267                }
268            } else {
269                debug(LOG_ERR, "Could not find %s in client list", ip);
270            }
271            pthread_mutex_unlock(&client_list_mutex);
272        }
273    }
274    pclose(output);
275
276    return 1;
277}
278
Note: See TracBrowser for help on using the browser.