]>
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. */
14 #include "libsmooth.h"
17 #define CAPTIVE_PORTAL_SETTINGS CONFIG_ROOT "/captive/settings"
18 #define ETHERNET_SETTINGS CONFIG_ROOT "/ethernet/settings"
20 #define CLIENTS CONFIG_ROOT "/captive/clients"
21 #define IPTABLES "/sbin/iptables --wait"
23 #define REDIRECT_PORT 1013
25 typedef struct client
{
26 char etheraddr
[STRING_SIZE
];
27 char ipaddr
[STRING_SIZE
];
34 static time_t parse_time(const char* s
) {
37 if (sscanf(s
, "%d", &t
) == 1) {
44 static char* format_time(const time_t* t
) {
45 char buffer
[STRING_SIZE
];
47 struct tm
* tm
= gmtime(t
);
51 strftime(buffer
, sizeof(buffer
), "%Y-%m-%dT%H:%M", tm
);
53 return strdup(buffer
);
56 static client_t
* read_clients(char* filename
) {
59 if (!(f
= fopen(filename
, "r"))) {
60 fprintf(stderr
, "Could not open configuration file: %s\n", filename
);
64 char line
[STRING_SIZE
];
66 client_t
* client_first
= NULL
;
67 client_t
* client_last
= NULL
;
68 client_t
* client_curr
;
70 while ((fgets(line
, STRING_SIZE
, f
) != NULL
)) {
71 if (line
[strlen(line
) - 1] == '\n')
72 line
[strlen(line
) - 1] = '\0';
74 client_curr
= (client_t
*)malloc(sizeof(client_t
));
75 memset(client_curr
, 0, sizeof(client_t
));
77 if (client_first
== NULL
)
78 client_first
= client_curr
;
80 client_last
->next
= client_curr
;
81 client_last
= client_curr
;
83 unsigned int count
= 0;
90 while (*lineptr
!= '\0') {
91 if (*lineptr
== ',') {
102 strcpy(client_curr
->etheraddr
, word
);
107 strcpy(client_curr
->ipaddr
, word
);
112 client_curr
->time_start
= parse_time(word
);
117 client_curr
->expires
= atoi(word
);
132 static void flush_chains() {
134 safe_system(IPTABLES
" -F CAPTIVE_PORTAL");
135 safe_system(IPTABLES
" -F CAPTIVE_PORTAL_CLIENTS");
138 safe_system(IPTABLES
" -t nat -F CAPTIVE_PORTAL");
141 static int add_client_rules(const client_t
* clients
) {
142 char command
[STRING_SIZE
];
143 char match
[STRING_SIZE
];
146 time_t expires
= clients
->time_start
+ clients
->expires
;
148 char* time_start
= format_time(&clients
->time_start
);
149 char* time_end
= format_time(&expires
);
151 snprintf(match
, sizeof(match
), "-s %s -m mac --mac-source %s"
152 " -m time --datestart %s --datestop %s", clients
->ipaddr
,
153 clients
->etheraddr
, time_start
, time_end
);
159 snprintf(command
, sizeof(command
), IPTABLES
" -A CAPTIVE_PORTAL_CLIENTS"
160 " %s -j RETURN", match
);
161 safe_system(command
);
164 snprintf(command
, sizeof(command
), IPTABLES
" -t nat -A CAPTIVE_PORTAL"
165 " %s -j RETURN", match
);
166 safe_system(command
);
168 // Move on to the next client
169 clients
= clients
->next
;
175 static char* get_key(struct keyvalue
* settings
, char* key
) {
176 char value
[STRING_SIZE
];
178 if (!findkey(settings
, key
, value
))
181 return strdup(value
);
184 static int add_interface_rule(const char* intf
, int allow_webif_access
) {
186 char command
[STRING_SIZE
];
188 if ((intf
== NULL
) || (strlen(intf
) == 0)) {
189 fprintf(stderr
, "Empty interface given\n");
193 snprintf(command
, sizeof(command
), IPTABLES
" -A CAPTIVE_PORTAL -i %s"
194 " -j CAPTIVE_PORTAL_CLIENTS", intf
);
195 r
= safe_system(command
);
200 snprintf(command
, sizeof(command
), IPTABLES
" -A CAPTIVE_PORTAL -o %s"
201 " -j CAPTIVE_PORTAL_CLIENTS", intf
);
202 r
= safe_system(command
);
207 if (allow_webif_access
) {
208 snprintf(command
, sizeof(command
), IPTABLES
" -A CAPTIVE_PORTAL_CLIENTS"
209 " -i %s -p tcp --dport 444 -j RETURN", intf
);
210 r
= safe_system(command
);
215 // Redirect all unauthenticated clients
216 snprintf(command
, sizeof(command
), IPTABLES
" -t nat -A CAPTIVE_PORTAL -i %s"
217 " -p tcp --dport %d -j REDIRECT --to-ports %d", intf
, HTTP_PORT
, REDIRECT_PORT
);
218 r
= safe_system(command
);
225 static int add_interface_rules(struct keyvalue
* captive_portal_settings
, struct keyvalue
* ethernet_settings
) {
230 setting
= get_key(captive_portal_settings
, "ENABLE_GREEN");
231 if (setting
&& (strcmp(setting
, "on") == 0)) {
234 intf
= get_key(ethernet_settings
, "GREEN_DEV");
235 r
= add_interface_rule(intf
, /* allow webif access from green */ 1);
240 setting
= get_key(captive_portal_settings
, "ENABLE_BLUE");
241 if (setting
&& (strcmp(setting
, "on") == 0)) {
244 intf
= get_key(ethernet_settings
, "BLUE_DEV");
245 r
= add_interface_rule(intf
, /* do not allow webif access */ 0);
250 // Always pass DNS packets through all firewall rules
251 r
= safe_system(IPTABLES
" -A CAPTIVE_PORTAL_CLIENTS -p udp --dport 53 -j RETURN");
255 r
= safe_system(IPTABLES
" -A CAPTIVE_PORTAL_CLIENTS -p tcp --dport 53 -j RETURN");
259 char command
[STRING_SIZE
];
260 snprintf(command
, sizeof(command
), IPTABLES
" -A CAPTIVE_PORTAL_CLIENTS"
261 " -p tcp --dport %d -j RETURN", REDIRECT_PORT
);
262 r
= safe_system(command
);
267 r
= safe_system(IPTABLES
" -A CAPTIVE_PORTAL_CLIENTS -j DROP");
274 int main(int argc
, char** argv
) {
277 client_t
* clients
= NULL
;
282 struct keyvalue
* ethernet_settings
= initkeyvalues();
283 if (!readkeyvalues(ethernet_settings
, ETHERNET_SETTINGS
)) {
284 fprintf(stderr
, "Could not read %s\n", ETHERNET_SETTINGS
);
289 struct keyvalue
* captive_portal_settings
= initkeyvalues();
290 if (!readkeyvalues(captive_portal_settings
, CAPTIVE_PORTAL_SETTINGS
)) {
291 fprintf(stderr
, "Could not read %s\n", CAPTIVE_PORTAL_SETTINGS
);
296 clients
= read_clients(CLIENTS
);
298 // Clean up all old rules
301 // Add all client rules
302 r
= add_client_rules(clients
);
306 // Add all interface rules
307 r
= add_interface_rules(captive_portal_settings
, ethernet_settings
);
313 client_t
* head
= clients
;
314 clients
= clients
->next
;
319 if (ethernet_settings
)
320 freekeyvalues(ethernet_settings
);
322 if (captive_portal_settings
)
323 freekeyvalues(captive_portal_settings
);