]>
git.ipfire.org Git - ipfire-2.x.git/blob - src/misc-progs/captivectrl.c
1 /* This file is part of the IPFire Firewall.
3 * This program is distributed under the terms of the GNU General Public
4 * Licence. See the file COPYING for details. */
10 #include "libsmooth.h"
13 #define CAPTIVE_PORTAL_SETTINGS CONFIG_ROOT "/captive/settings"
14 #define ETHERNET_SETTINGS CONFIG_ROOT "/ethernet/settings"
16 #define CLIENTS CONFIG_ROOT "/captive/clients"
17 #define IPTABLES "/sbin/iptables --wait"
19 #define REDIRECT_PORT 1013
21 typedef struct client
{
22 char etheraddr
[STRING_SIZE
];
23 char ipaddr
[STRING_SIZE
];
30 static int parse_time(const char* s
) {
34 if (sscanf(s
, "%d:%d", &hrs
, &min
) == 2) {
35 return (hrs
* 60) + min
;
41 static char* format_time(int t
) {
42 char buffer
[STRING_SIZE
];
43 snprintf(buffer
, sizeof(buffer
), "%02d:%02d", (t
/ 60), (t
% 60));
45 return strdup(buffer
);
48 static client_t
* read_clients(char* filename
) {
51 if (!(f
= fopen(filename
, "r"))) {
52 fprintf(stderr
, "Could not open configuration file: %s\n", filename
);
56 char line
[STRING_SIZE
];
58 client_t
* client_first
= NULL
;
59 client_t
* client_last
= NULL
;
60 client_t
* client_curr
;
62 while ((fgets(line
, STRING_SIZE
, f
) != NULL
)) {
63 if (line
[strlen(line
) - 1] == '\n')
64 line
[strlen(line
) - 1] = '\0';
66 client_curr
= (client_t
*)malloc(sizeof(client_t
));
67 memset(client_curr
, 0, sizeof(client_t
));
69 if (client_first
== NULL
)
70 client_first
= client_curr
;
72 client_last
->next
= client_curr
;
73 client_last
= client_curr
;
75 unsigned int count
= 0;
82 while (*lineptr
!= '\0') {
83 if (*lineptr
== ',') {
94 strcpy(client_curr
->etheraddr
, word
);
99 strcpy(client_curr
->ipaddr
, word
);
104 client_curr
->time_start
= parse_time(word
);
109 client_curr
->time_end
= parse_time(word
);
124 static void flush_chains() {
126 safe_system(IPTABLES
" -F CAPTIVE_PORTAL");
127 safe_system(IPTABLES
" -F CAPTIVE_PORTAL_CLIENTS");
130 safe_system(IPTABLES
" -t nat -F CAPTIVE_PORTAL");
133 static int add_client_rules(const client_t
* clients
) {
134 char command
[STRING_SIZE
];
135 char match
[STRING_SIZE
];
138 char* time_start
= format_time(clients
->time_start
);
139 char* time_end
= format_time(clients
->time_end
);
141 snprintf(match
, sizeof(match
), "-s %s -m mac --mac-source %s"
142 " -m time %s --timestart %s --timestop %s",
143 clients
->ipaddr
, clients
->etheraddr
,
144 (clients
->time_start
> clients
->time_end
) ? "--contiguous" : "",
145 time_start
, time_end
);
151 snprintf(command
, sizeof(command
), IPTABLES
" -A CAPTIVE_PORTAL_CLIENTS"
152 " %s -j RETURN", match
);
153 safe_system(command
);
156 snprintf(command
, sizeof(command
), IPTABLES
" -t nat -A CAPTIVE_PORTAL"
157 " %s -j RETURN", match
);
158 safe_system(command
);
160 // Move on to the next client
161 clients
= clients
->next
;
167 static char* get_key(struct keyvalue
* settings
, char* key
) {
168 char value
[STRING_SIZE
];
170 if (!findkey(settings
, key
, value
))
173 return strdup(value
);
176 static int add_interface_rule(const char* intf
, int allow_webif_access
) {
178 char command
[STRING_SIZE
];
180 if ((intf
== NULL
) || (strlen(intf
) == 0)) {
181 fprintf(stderr
, "Empty interface given\n");
185 snprintf(command
, sizeof(command
), IPTABLES
" -A CAPTIVE_PORTAL -i %s"
186 " -j CAPTIVE_PORTAL_CLIENTS", intf
);
187 r
= safe_system(command
);
192 snprintf(command
, sizeof(command
), IPTABLES
" -A CAPTIVE_PORTAL -o %s"
193 " -j CAPTIVE_PORTAL_CLIENTS", intf
);
194 r
= safe_system(command
);
199 if (allow_webif_access
) {
200 snprintf(command
, sizeof(command
), IPTABLES
" -A CAPTIVE_PORTAL_CLIENTS"
201 " -i %s -p tcp --dport 444 -j RETURN", intf
);
202 r
= safe_system(command
);
207 // Redirect all unauthenticated clients
208 snprintf(command
, sizeof(command
), IPTABLES
" -t nat -A CAPTIVE_PORTAL -i %s"
209 " -p tcp --dport %d -j REDIRECT --to-ports %d", intf
, HTTP_PORT
, REDIRECT_PORT
);
210 r
= safe_system(command
);
217 static int add_interface_rules(struct keyvalue
* captive_portal_settings
, struct keyvalue
* ethernet_settings
) {
222 setting
= get_key(captive_portal_settings
, "ENABLE_GREEN");
223 if (setting
&& (strcmp(setting
, "on") == 0)) {
226 intf
= get_key(ethernet_settings
, "GREEN_DEV");
227 r
= add_interface_rule(intf
, /* allow webif access from green */ 1);
232 setting
= get_key(captive_portal_settings
, "ENABLE_BLUE");
233 if (setting
&& (strcmp(setting
, "on") == 0)) {
236 intf
= get_key(ethernet_settings
, "BLUE_DEV");
237 r
= add_interface_rule(intf
, /* do not allow webif access */ 0);
242 // Always pass DNS packets through all firewall rules
243 r
= safe_system(IPTABLES
" -A CAPTIVE_PORTAL_CLIENTS -p udp --dport 53 -j RETURN");
247 r
= safe_system(IPTABLES
" -A CAPTIVE_PORTAL_CLIENTS -p tcp --dport 53 -j RETURN");
251 char command
[STRING_SIZE
];
252 snprintf(command
, sizeof(command
), IPTABLES
" -A CAPTIVE_PORTAL_CLIENTS"
253 " -p tcp --dport %d -j RETURN", REDIRECT_PORT
);
254 r
= safe_system(command
);
259 r
= safe_system(IPTABLES
" -A CAPTIVE_PORTAL_CLIENTS -j DROP");
266 int main(int argc
, char** argv
) {
269 client_t
* clients
= NULL
;
274 struct keyvalue
* ethernet_settings
= initkeyvalues();
275 if (!readkeyvalues(ethernet_settings
, ETHERNET_SETTINGS
)) {
276 fprintf(stderr
, "Could not read %s\n", ETHERNET_SETTINGS
);
281 struct keyvalue
* captive_portal_settings
= initkeyvalues();
282 if (!readkeyvalues(captive_portal_settings
, CAPTIVE_PORTAL_SETTINGS
)) {
283 fprintf(stderr
, "Could not read %s\n", CAPTIVE_PORTAL_SETTINGS
);
288 clients
= read_clients(CLIENTS
);
290 // Clean up all old rules
293 // Add all client rules
294 r
= add_client_rules(clients
);
298 // Add all interface rules
299 r
= add_interface_rules(captive_portal_settings
, ethernet_settings
);
305 client_t
* head
= clients
;
306 clients
= clients
->next
;
311 if (ethernet_settings
)
312 freekeyvalues(ethernet_settings
);
314 if (captive_portal_settings
)
315 freekeyvalues(captive_portal_settings
);