mirror of
https://github.com/openNDS/openNDS.git
synced 2026-01-14 22:27:57 -05:00
lindnermarek: tc rules to limit bandwidth per user; support forEnableVoucher, ForceVoucher and EnablePreAuth; also more little fixes and changes
This commit is contained in:
@@ -111,7 +111,7 @@ auth_client_action(char *ip, char *mac, t_authaction action)
|
||||
case AUTH_MAKE_AUTHENTICATED:
|
||||
if(client->fw_connection_state != FW_MARK_AUTHENTICATED) {
|
||||
client->fw_connection_state = FW_MARK_AUTHENTICATED;
|
||||
iptables_fw_access(AUTH_MAKE_AUTHENTICATED,client->ip,client->mac);
|
||||
iptables_fw_access(AUTH_MAKE_AUTHENTICATED, client);
|
||||
authenticated_since_start++;
|
||||
} else {
|
||||
debug(LOG_INFO, "Nothing to do, %s %s already authenticated", client->ip, client->mac);
|
||||
@@ -120,7 +120,7 @@ auth_client_action(char *ip, char *mac, t_authaction action)
|
||||
|
||||
case AUTH_MAKE_DEAUTHENTICATED:
|
||||
if(client->fw_connection_state == FW_MARK_AUTHENTICATED) {
|
||||
iptables_fw_access(AUTH_MAKE_DEAUTHENTICATED, client->ip, client->mac);
|
||||
iptables_fw_access(AUTH_MAKE_DEAUTHENTICATED, client);
|
||||
}
|
||||
client_list_delete(client);
|
||||
break;
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
|
||||
/** Client counter */
|
||||
static int client_count = 0;
|
||||
static t_client **client_arr;
|
||||
|
||||
/** Time last client added */
|
||||
static unsigned long int last_client_time = 0;
|
||||
@@ -83,8 +84,17 @@ client_get_first_client(void)
|
||||
void
|
||||
client_list_init(void)
|
||||
{
|
||||
s_config *config;
|
||||
int i;
|
||||
|
||||
firstclient = NULL;
|
||||
client_count = 0;
|
||||
|
||||
config = config_get_config();
|
||||
client_arr = safe_malloc(config->maxclients * sizeof(t_client *));
|
||||
|
||||
for (i = 0; i < config->maxclients; i++)
|
||||
client_arr[i] = NULL;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
@@ -103,7 +113,7 @@ _client_list_append(const char *ip, const char *mac, const char *token)
|
||||
{
|
||||
t_client *client, *prevclient;
|
||||
s_config *config;
|
||||
int maxclients;
|
||||
int maxclients, i;
|
||||
|
||||
config = config_get_config();
|
||||
maxclients = config->maxclients;
|
||||
@@ -133,6 +143,15 @@ _client_list_append(const char *ip, const char *mac, const char *token)
|
||||
client->counters.last_updated = last_client_time;
|
||||
client->added_time = last_client_time;
|
||||
|
||||
for (i = 0; i < maxclients; i++) {
|
||||
if (client_arr[i])
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
client_arr[i] = client;
|
||||
client->idx = i;
|
||||
|
||||
debug(LOG_NOTICE, "Adding %s %s token %s to client list",
|
||||
client->ip, client->mac, client->token ? client->token : "none");
|
||||
|
||||
@@ -301,6 +320,9 @@ _client_list_free_node(t_client * client)
|
||||
if (client->token != NULL)
|
||||
free(client->token);
|
||||
|
||||
if (client_arr[client->idx] == client)
|
||||
client_arr[client->idx] = NULL;
|
||||
|
||||
free(client);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,9 @@ typedef struct _t_client {
|
||||
t_counters counters; /**< @brief Counters for input/output of
|
||||
the client. */
|
||||
int attempts; /**< @brief Number of authentication attempts */
|
||||
int download_limit; /**< @brief Download limit, kb/s */
|
||||
int upload_limit; /**< @brief Upload limit, kb/s */
|
||||
int idx;
|
||||
} t_client;
|
||||
|
||||
/** @brief Get the first element of the list of connected clients
|
||||
|
||||
21
src/conf.c
21
src/conf.c
@@ -75,6 +75,9 @@ typedef enum {
|
||||
oGatewayAddress,
|
||||
oGatewayPort,
|
||||
oRemoteAuthenticatorAction,
|
||||
oEnablePreAuth,
|
||||
oEnableVoucher,
|
||||
oForceVoucher,
|
||||
oPasswordAuthentication,
|
||||
oUsernameAuthentication,
|
||||
oPasswordAttempts,
|
||||
@@ -131,6 +134,9 @@ static const struct {
|
||||
{ "gatewayaddress", oGatewayAddress },
|
||||
{ "gatewayport", oGatewayPort },
|
||||
{ "remoteauthenticatoraction", oRemoteAuthenticatorAction },
|
||||
{ "enablepreauth", oEnablePreAuth },
|
||||
{ "enablevoucher", oEnableVoucher },
|
||||
{ "forcevoucher", oForceVoucher },
|
||||
{ "passwordauthentication", oPasswordAuthentication },
|
||||
{ "usernameauthentication", oUsernameAuthentication },
|
||||
{ "passwordattempts", oPasswordAttempts },
|
||||
@@ -743,6 +749,21 @@ config_read(const char *filename)
|
||||
case oRemoteAuthenticatorAction:
|
||||
config.remote_auth_action = safe_strdup(p1);
|
||||
break;
|
||||
case oEnablePreAuth:
|
||||
value = parse_boolean_value(p1);
|
||||
if (value != - 1)
|
||||
config.enable_preauth = value;
|
||||
break;
|
||||
case oEnableVoucher:
|
||||
value = parse_boolean_value(p1);
|
||||
if (value != - 1)
|
||||
config.enable_voucher = value;
|
||||
break;
|
||||
case oForceVoucher:
|
||||
value = parse_boolean_value(p1);
|
||||
if (value != - 1)
|
||||
config.force_voucher = value;
|
||||
break;
|
||||
case oFirewallRuleSet:
|
||||
parse_firewall_ruleset(p1, fd, filename, &linenum);
|
||||
break;
|
||||
|
||||
@@ -144,6 +144,9 @@ typedef struct {
|
||||
char *gw_address; /**< @brief Internal IP address for our web server */
|
||||
unsigned int gw_port; /**< @brief Port the webserver will run on */
|
||||
char *remote_auth_action; /**< @brief Path for remote auth */
|
||||
char enable_preauth; /**< @brief enable pre-authentication support */
|
||||
char enable_voucher; /**< @brief enable voucher support */
|
||||
char force_voucher; /**< @brief force voucher */
|
||||
char *webroot; /**< @brief Directory containing splash pages, etc. */
|
||||
char *splashpage; /**< @brief Name of main splash page */
|
||||
char *infoskelpage; /**< @brief Name of info skeleton page */
|
||||
|
||||
@@ -67,10 +67,10 @@
|
||||
#include "safe.h"
|
||||
#include "debug.h"
|
||||
#include "conf.h"
|
||||
#include "client_list.h"
|
||||
#include "firewall.h"
|
||||
#include "fw_iptables.h"
|
||||
#include "auth.h"
|
||||
#include "client_list.h"
|
||||
|
||||
|
||||
extern pthread_mutex_t client_list_mutex;
|
||||
@@ -215,7 +215,7 @@ fw_refresh_client_list(void)
|
||||
cp1->ip, cp1->mac, config->checkinterval * config->clienttimeout,
|
||||
cp1->counters.incoming/1000, cp1->counters.outgoing/1000);
|
||||
if(cp1->fw_connection_state == FW_MARK_AUTHENTICATED) {
|
||||
iptables_fw_access(AUTH_MAKE_DEAUTHENTICATED, cp1->ip, cp1->mac);
|
||||
iptables_fw_access(AUTH_MAKE_DEAUTHENTICATED, cp1);
|
||||
}
|
||||
client_list_delete(cp1);
|
||||
} else if (added_time + (config->checkinterval * config->clientforceout) <= now) {
|
||||
@@ -224,7 +224,7 @@ fw_refresh_client_list(void)
|
||||
cp1->ip, cp1->mac, config->checkinterval * config->clientforceout,
|
||||
cp1->counters.incoming/1000, cp1->counters.outgoing/1000);
|
||||
if(cp1->fw_connection_state == FW_MARK_AUTHENTICATED) {
|
||||
iptables_fw_access(AUTH_MAKE_DEAUTHENTICATED, cp1->ip, cp1->mac);
|
||||
iptables_fw_access(AUTH_MAKE_DEAUTHENTICATED, cp1);
|
||||
}
|
||||
client_list_delete(cp1);
|
||||
}
|
||||
|
||||
@@ -44,11 +44,11 @@
|
||||
#include "safe.h"
|
||||
#include "conf.h"
|
||||
#include "auth.h"
|
||||
#include "client_list.h"
|
||||
#include "fw_iptables.h"
|
||||
#include "firewall.h"
|
||||
#include "debug.h"
|
||||
#include "util.h"
|
||||
#include "client_list.h"
|
||||
#include "tc.h"
|
||||
|
||||
static char * _iptables_compile(const char *, char *, t_firewall_rule *);
|
||||
@@ -410,7 +410,7 @@ iptables_fw_init(void)
|
||||
*/
|
||||
|
||||
/* packets coming in on gw_interface jump to CHAIN_OUTGOING */
|
||||
rc |= iptables_do_command("-t nat -I PREROUTING -i %s -s %s -j " CHAIN_OUTGOING, gw_interface, gw_iprange);
|
||||
rc |= iptables_do_command("-t nat -A PREROUTING -i %s -s %s -j " CHAIN_OUTGOING, gw_interface, gw_iprange);
|
||||
/* CHAIN_OUTGOING, packets marked TRUSTED ACCEPT */
|
||||
rc |= iptables_do_command("-t nat -A " CHAIN_OUTGOING " -m mark --mark 0x%x%s -j ACCEPT", FW_MARK_TRUSTED, markmask);
|
||||
/* CHAIN_OUTGOING, packets marked AUTHENTICATED ACCEPT */
|
||||
@@ -501,7 +501,7 @@ iptables_fw_init(void)
|
||||
*/
|
||||
|
||||
/* packets coming in on gw_interface jump to CHAIN_TO_INTERNET */
|
||||
rc |= iptables_do_command("-t filter -I FORWARD -i %s -s %s -j " CHAIN_TO_INTERNET, gw_interface, gw_iprange);
|
||||
rc |= iptables_do_command("-t filter -A FORWARD -i %s -s %s -j " CHAIN_TO_INTERNET, gw_interface, gw_iprange);
|
||||
/* CHAIN_TO_INTERNET packets marked BLOCKED DROP */
|
||||
rc |= iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%x%s -j DROP", FW_MARK_BLOCKED, markmask);
|
||||
/* CHAIN_TO_INTERNET, invalid packets DROP */
|
||||
@@ -716,31 +716,49 @@ iptables_fw_destroy_mention(
|
||||
/** Insert or delete firewall mangle rules marking a client's packets.
|
||||
*/
|
||||
int
|
||||
iptables_fw_access(t_authaction action, const char *ip, const char *mac)
|
||||
{
|
||||
int rc;
|
||||
iptables_fw_access(t_authaction action, t_client *client) {
|
||||
int rc = 0, download_limit, upload_limit;
|
||||
s_config *config;
|
||||
char *download_imqname, *upload_imqname;
|
||||
|
||||
fw_quiet = 0;
|
||||
|
||||
config = config_get_config();
|
||||
safe_asprintf(&download_imqname,"imq%d",config->download_imq); /* must free */
|
||||
safe_asprintf(&upload_imqname,"imq%d",config->upload_imq); /* must free */
|
||||
|
||||
download_limit = config->download_limit;
|
||||
upload_limit = config->upload_limit;
|
||||
|
||||
if ((client->download_limit > 0) && (client->upload_limit > 0)) {
|
||||
download_limit = client->download_limit;
|
||||
upload_limit = client->upload_limit;
|
||||
}
|
||||
|
||||
switch(action) {
|
||||
case AUTH_MAKE_AUTHENTICATED:
|
||||
debug(LOG_NOTICE, "Authenticating %s %s", ip, mac);
|
||||
debug(LOG_NOTICE, "Authenticating %s %s", client->ip, client->mac);
|
||||
/* This rule is for marking upload (outgoing) packets, and for upload byte counting */
|
||||
rc = iptables_do_command("-t mangle -A " CHAIN_OUTGOING " -s %s -m mac --mac-source %s -j MARK %s 0x%x", ip, mac, markop, FW_MARK_AUTHENTICATED);
|
||||
rc |= iptables_do_command("-t mangle -I " CHAIN_OUTGOING " -s %s -m mac --mac-source %s -j MARK %s 0x%x%x", client->ip, client->mac, markop, client->idx + 10, FW_MARK_AUTHENTICATED);
|
||||
rc |= iptables_do_command("-t mangle -I " CHAIN_INCOMING " -d %s -j MARK %s 0x%x%x", client->ip, markop, client->idx + 10, FW_MARK_AUTHENTICATED);
|
||||
/* This rule is just for download (incoming) byte counting, see iptables_fw_counters_update() */
|
||||
rc = iptables_do_command("-t mangle -A " CHAIN_INCOMING " -d %s -j ACCEPT", ip);
|
||||
rc |= iptables_do_command("-t mangle -A " CHAIN_INCOMING " -d %s -j ACCEPT", client->ip);
|
||||
rc |= tc_attach_client(download_imqname, download_limit, upload_imqname, upload_limit, client->idx, FW_MARK_AUTHENTICATED);
|
||||
break;
|
||||
case AUTH_MAKE_DEAUTHENTICATED:
|
||||
/* Remove the authentication rules. */
|
||||
debug(LOG_NOTICE, "Deauthenticating %s %s", ip, mac);
|
||||
rc = iptables_do_command("-t mangle -D " CHAIN_OUTGOING " -s %s -m mac --mac-source %s -j MARK %s 0x%x", ip, mac, markop, FW_MARK_AUTHENTICATED);
|
||||
rc = iptables_do_command("-t mangle -D " CHAIN_INCOMING " -d %s -j ACCEPT", ip);
|
||||
debug(LOG_NOTICE, "Deauthenticating %s %s", client->ip, client->mac);
|
||||
rc |= iptables_do_command("-t mangle -D " CHAIN_OUTGOING " -s %s -m mac --mac-source %s -j MARK %s 0x%x%x", client->ip, client->mac, markop, client->idx + 10, FW_MARK_AUTHENTICATED);
|
||||
rc |= iptables_do_command("-t mangle -D " CHAIN_INCOMING " -d %s -j ACCEPT", client->ip);
|
||||
rc |= tc_detach_client(download_imqname, upload_imqname, client->idx);
|
||||
break;
|
||||
default:
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
free(upload_imqname);
|
||||
free(download_imqname);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ int iptables_fw_destroy(void);
|
||||
int iptables_fw_destroy_mention( const char * table, const char * chain, const char * mention);
|
||||
|
||||
/** @brief Define the access of a specific client */
|
||||
int iptables_fw_access(t_authaction action, const char *ip, const char *mac);
|
||||
int iptables_fw_access(t_authaction action, t_client *client);
|
||||
|
||||
/** @brief Return the total download usage in bytes */
|
||||
unsigned long long int iptables_fw_total_download();
|
||||
|
||||
159
src/http.c
159
src/http.c
@@ -51,6 +51,76 @@
|
||||
|
||||
extern pthread_mutex_t client_list_mutex;
|
||||
|
||||
static int data_extract_bw(char *buff, t_client *client)
|
||||
{
|
||||
char *download_ptr, *upload_ptr;
|
||||
int download, upload;
|
||||
|
||||
download_ptr = strchr(buff, ' ');
|
||||
if (!download_ptr)
|
||||
goto err;
|
||||
|
||||
*download_ptr = '\0';
|
||||
download_ptr++;
|
||||
|
||||
upload_ptr = strchr(download_ptr, ' ');
|
||||
if (!upload_ptr)
|
||||
goto err;
|
||||
|
||||
*upload_ptr = '\0';
|
||||
upload_ptr++;
|
||||
|
||||
download = strtol(download_ptr, NULL, 10);
|
||||
if (download < 1)
|
||||
goto err;
|
||||
|
||||
upload = strtol(upload_ptr, NULL, 10);
|
||||
if (upload < 1)
|
||||
goto err;
|
||||
|
||||
client->download_limit = download;
|
||||
client->upload_limit = upload;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
client->download_limit = 0;
|
||||
client->upload_limit = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *system_exec(char *cmd)
|
||||
{
|
||||
char *data = NULL;
|
||||
int error, pipes[2], stderr_fd = -1;
|
||||
int data_len = 100, read_len;
|
||||
|
||||
data = malloc(data_len);
|
||||
if (!data)
|
||||
goto out;
|
||||
|
||||
memset(data, 0, data_len);
|
||||
|
||||
error = pipe(pipes);
|
||||
if (error < 0)
|
||||
goto out;
|
||||
|
||||
stderr_fd = dup(STDOUT_FILENO);
|
||||
|
||||
dup2(pipes[1], STDOUT_FILENO);
|
||||
close(pipes[1]);
|
||||
|
||||
error = system(cmd);
|
||||
|
||||
dup2(stderr_fd, STDOUT_FILENO);
|
||||
close(stderr_fd);
|
||||
|
||||
read_len = read(pipes[0], data, data_len - 1);
|
||||
data[read_len] = '\0';
|
||||
|
||||
close(pipes[0]);
|
||||
out:
|
||||
return data;
|
||||
}
|
||||
|
||||
/* response handler for HTTP 405 Method Not Allowed */
|
||||
void
|
||||
@@ -110,7 +180,8 @@ http_nodogsplash_first_contact(request *r)
|
||||
t_client *client;
|
||||
t_auth_target *authtarget;
|
||||
s_config *config;
|
||||
char *redir;
|
||||
char *redir, cmd_buff[50], *data = NULL;
|
||||
int ret, seconds;
|
||||
|
||||
/* only allow GET requests */
|
||||
if (r->request.method != HTTP_GET) {
|
||||
@@ -132,9 +203,31 @@ http_nodogsplash_first_contact(request *r)
|
||||
if(config->authenticate_immediately) {
|
||||
/* Don't serve splash, just authenticate */
|
||||
http_nodogsplash_callback_action(r,authtarget,AUTH_MAKE_AUTHENTICATED);
|
||||
} else if (config->enable_preauth) {
|
||||
snprintf(cmd_buff, sizeof(cmd_buff) - 1, "captive_portal auth_status %s", client->mac);
|
||||
data = system_exec(cmd_buff);
|
||||
|
||||
if(!data)
|
||||
goto serve_splash;
|
||||
|
||||
seconds = strtol(data, NULL, 10);
|
||||
if(seconds < 1)
|
||||
goto serve_splash;
|
||||
|
||||
ret = data_extract_bw(data, client);
|
||||
if(ret < 0)
|
||||
goto serve_splash;
|
||||
|
||||
debug(LOG_NOTICE, "Remote auth data: client [%s, %s] authenticated %d seconds",
|
||||
client->mac, client->ip, seconds);
|
||||
http_nodogsplash_callback_action(r,authtarget,AUTH_MAKE_AUTHENTICATED);
|
||||
client->added_time = time(NULL) - (config->checkinterval * config->clientforceout) + seconds;
|
||||
free(data);
|
||||
} else {
|
||||
/* Serve the splash page (or redirect to remote authenticator) */
|
||||
http_nodogsplash_serve_splash(r,authtarget);
|
||||
serve_splash:
|
||||
free(data);
|
||||
http_nodogsplash_serve_splash(r,authtarget, NULL);
|
||||
}
|
||||
|
||||
http_nodogsplash_free_authtarget(authtarget);
|
||||
@@ -248,16 +341,64 @@ http_nodogsplash_callback_action(request *r,
|
||||
void
|
||||
http_nodogsplash_callback_auth(httpd *webserver, request *r)
|
||||
{
|
||||
s_config *config;
|
||||
t_client *client;
|
||||
t_auth_target *authtarget;
|
||||
char *ip, *mac, *msg = NULL, cmd_buff[50], *data = NULL;
|
||||
int ret, seconds;
|
||||
|
||||
/* Get info we need from request, and do action */
|
||||
authtarget = http_nodogsplash_decode_authtarget(r);
|
||||
config = config_get_config();
|
||||
|
||||
if(http_nodogsplash_check_userpass(r,authtarget)) {
|
||||
if (config->enable_voucher && ((authtarget->voucher) || (config->force_voucher))) {
|
||||
ip = r->clientAddr;
|
||||
mac = arp_get(ip);
|
||||
|
||||
if (!mac)
|
||||
goto serve_splash;
|
||||
|
||||
LOCK_CLIENT_LIST();
|
||||
client = client_list_find(ip, mac);
|
||||
UNLOCK_CLIENT_LIST();
|
||||
|
||||
if (!client)
|
||||
goto serve_splash;
|
||||
|
||||
snprintf(cmd_buff, sizeof(cmd_buff) - 1, "captive_portal auth_voucher %s %s",
|
||||
client->mac, authtarget->voucher);
|
||||
data = system_exec(cmd_buff);
|
||||
|
||||
if (!data)
|
||||
goto serve_splash;
|
||||
|
||||
seconds = strtol(data, NULL, 10);
|
||||
if (seconds < 1)
|
||||
goto serve_splash;
|
||||
|
||||
ret = data_extract_bw(data, client);
|
||||
if (ret < 0)
|
||||
goto serve_splash;
|
||||
|
||||
debug(LOG_NOTICE, "Remote voucher: client [%s, %s] authenticated %d seconds",
|
||||
client->mac, client->ip, seconds);
|
||||
free(mac);
|
||||
free(data);
|
||||
http_nodogsplash_callback_action(r,authtarget,AUTH_MAKE_AUTHENTICATED);
|
||||
client->added_time = time(NULL) - (config->checkinterval * config->clientforceout) + seconds;
|
||||
} else if(http_nodogsplash_check_userpass(r,authtarget)) {
|
||||
http_nodogsplash_callback_action (r,authtarget,AUTH_MAKE_AUTHENTICATED);
|
||||
} else {
|
||||
/* Password check failed; just serve them the splash page again */
|
||||
http_nodogsplash_serve_splash(r,authtarget);
|
||||
serve_splash:
|
||||
if (data) {
|
||||
msg = strchr(data, ' ');
|
||||
if (msg)
|
||||
msg++;
|
||||
}
|
||||
http_nodogsplash_serve_splash(r,authtarget,msg);
|
||||
free(mac);
|
||||
free(data);
|
||||
}
|
||||
|
||||
http_nodogsplash_free_authtarget(authtarget);
|
||||
@@ -324,7 +465,7 @@ http_nodogsplash_redirect_remote_auth(request *r, t_auth_target *authtarget)
|
||||
* or redirect to remote authenticator as required.
|
||||
*/
|
||||
void
|
||||
http_nodogsplash_serve_splash(request *r, t_auth_target *authtarget)
|
||||
http_nodogsplash_serve_splash(request *r, t_auth_target *authtarget, char *error_msg)
|
||||
{
|
||||
char *tmpstr;
|
||||
char line [MAX_BUF];
|
||||
@@ -341,6 +482,10 @@ http_nodogsplash_serve_splash(request *r, t_auth_target *authtarget)
|
||||
}
|
||||
|
||||
/* Set variables; these can be interpolated in the splash page text. */
|
||||
if (error_msg)
|
||||
httpdAddVariable(r,"error_msg", error_msg);
|
||||
else
|
||||
httpdAddVariable(r,"error_msg", "");
|
||||
httpdAddVariable(r,"gatewayname",config->gw_name);
|
||||
httpdAddVariable(r,"tok",authtarget->token);
|
||||
httpdAddVariable(r,"redir",authtarget->redir);
|
||||
@@ -487,6 +632,10 @@ http_nodogsplash_decode_authtarget(request *r)
|
||||
authtarget->info = safe_strdup(var->value);
|
||||
}
|
||||
|
||||
var = httpdGetVariableByName(r,"voucher");
|
||||
if(var && var->value)
|
||||
authtarget->voucher = var->value;
|
||||
|
||||
return authtarget;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ typedef struct _auth_target_t {
|
||||
char *authtarget; /**< @brief Deny action */
|
||||
char *token; /**< @brief Client token */
|
||||
char *redir; /**< @brief Client redirect target */
|
||||
char *voucher; /**< @brief voucher token */
|
||||
char *username; /**< @brief User name */
|
||||
char *password; /**< @brief User password */
|
||||
char *info; /**< @brief Auxilliary info */
|
||||
@@ -68,7 +69,7 @@ void http_nodogsplash_redirect(request *r, char *url);
|
||||
/**@brief Redirect to remote auth server */
|
||||
void http_nodogsplash_redirect_remote_auth(request *r, t_auth_target *authtarget);
|
||||
/**@brief Serve the splash page from its file */
|
||||
void http_nodogsplash_serve_splash(request *r, t_auth_target *authtarget);
|
||||
void http_nodogsplash_serve_splash(request *r, t_auth_target *authtarget, char *error_msg);
|
||||
/**@brief Serve the info page from its file */
|
||||
void http_nodogsplash_serve_info(request *r, char *title, char *content);
|
||||
/**@brief Handle initial contact from client */
|
||||
|
||||
@@ -47,9 +47,10 @@
|
||||
#include "debug.h"
|
||||
#include "auth.h"
|
||||
#include "safe.h"
|
||||
#include "client_list.h"
|
||||
#include "fw_iptables.h"
|
||||
#include "firewall.h"
|
||||
#include "client_list.h"
|
||||
|
||||
#include "ndsctl_thread.h"
|
||||
|
||||
/* Defined in clientlist.c */
|
||||
|
||||
71
src/tc.c
71
src/tc.c
@@ -35,12 +35,13 @@
|
||||
|
||||
#include "safe.h"
|
||||
#include "conf.h"
|
||||
#include "client_list.h"
|
||||
#include "auth.h"
|
||||
#include "fw_iptables.h"
|
||||
#include "firewall.h"
|
||||
#include "debug.h"
|
||||
#include "util.h"
|
||||
#include "client_list.h"
|
||||
|
||||
#include "tc.h"
|
||||
|
||||
|
||||
@@ -76,6 +77,46 @@ tc_do_command(char *format, ...)
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
tc_attach_client(char *down_dev, int download_limit, char *up_dev, int upload_limit, int idx, int fw_mark) {
|
||||
int burst;
|
||||
int mtu = MTU + 40;
|
||||
int rc = 0;
|
||||
int r2q = 10;
|
||||
|
||||
if(download_limit < 120) r2q = 1;
|
||||
|
||||
burst = download_limit * 1000 / 8 / HZ; /* burst (buffer size) in bytes */
|
||||
burst = burst < mtu ? mtu : burst; /* but burst should be at least mtu */
|
||||
|
||||
rc |= tc_do_command("class add dev %s parent 1:1 classid 1:%i htb rate %dkbit ceil %dkbit burst %d cburst %d mtu %d prio 1",
|
||||
down_dev, idx + 10, download_limit, download_limit, burst*10, burst, mtu);
|
||||
rc |= tc_do_command("filter add dev %s protocol ip parent 1: handle 0x%x%x fw flowid 1:%i",
|
||||
down_dev, idx + 10, fw_mark, idx + 10);
|
||||
|
||||
/* to avoid some kernel warnings with small rates */
|
||||
if(upload_limit < 120) r2q = 1;
|
||||
|
||||
burst = upload_limit * 1000 / 8 / HZ; /* burst (buffer size) in bytes */
|
||||
burst = burst < mtu ? mtu : burst; /* but burst should be at least mtu */
|
||||
|
||||
rc |= tc_do_command("class add dev %s parent 1:1 classid 1:%i htb rate %dkbit ceil %dkbit burst %d cburst %d mtu %d prio 1",
|
||||
up_dev, idx + 10, upload_limit, upload_limit, burst*10, burst, mtu);
|
||||
rc |= tc_do_command("filter add dev %s protocol ip parent 1: handle 0x%x%x fw flowid 1:%i",
|
||||
up_dev, idx + 10, fw_mark, idx + 10);
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
tc_detach_client(char *down_dev, char *up_dev, int idx) {
|
||||
int rc = 0;
|
||||
|
||||
rc |= tc_do_command("class del dev %s parent 1: classid 1:%i", down_dev, idx + 10);
|
||||
rc |= tc_do_command("class del dev %s parent 1: classid 1:%i", up_dev, idx + 10);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Use HTB as a upload qdisc.
|
||||
* dev is name of device to attach qdisc to (typically an IMQ)
|
||||
@@ -86,20 +127,18 @@ tc_do_command(char *format, ...)
|
||||
static int
|
||||
tc_attach_upload_qdisc(char *dev, int upload_limit)
|
||||
{
|
||||
int rc = 0;
|
||||
int burst;
|
||||
int mtu = MTU + 40;
|
||||
int rc = 0;
|
||||
int r2q = 10;
|
||||
|
||||
/* to avoid some kernel warnings with small rates */
|
||||
if(upload_limit < 120) r2q = 1;
|
||||
|
||||
burst = upload_limit * 1000 / 8 / HZ; /* burst (buffer size) in bytes */
|
||||
burst = burst < mtu ? mtu : burst; /* but burst should be at least mtu */
|
||||
|
||||
rc |= tc_do_command("qdisc add dev %s root handle 1: htb default 1 r2q %d", dev,r2q);
|
||||
rc |= tc_do_command("class add dev %s parent 1: classid 1:1 htb rate %dkbit ceil %dkbit burst %d cburst %d mtu %d prio 1",
|
||||
dev, upload_limit, upload_limit, burst*2, burst, mtu);
|
||||
rc |= tc_do_command("qdisc add dev %s root handle 1: htb default 2 r2q %d", dev, 1700);
|
||||
rc |= tc_do_command("class add dev %s parent 1: classid 1:1 htb rate 100Mbps ceil 100Mbps burst %d cburst %d mtu %d",
|
||||
dev, burst*10, burst, mtu);
|
||||
rc |= tc_do_command("class add dev %s parent 1:1 classid 1:2 htb rate %dkbit ceil %dkbit burst %d cburst %d mtu %d prio 1",
|
||||
dev, upload_limit, upload_limit, burst*10, burst, mtu);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -113,21 +152,19 @@ tc_attach_upload_qdisc(char *dev, int upload_limit)
|
||||
static int
|
||||
tc_attach_download_qdisc(char *dev, int download_limit)
|
||||
{
|
||||
int rc = 0;
|
||||
int burst;
|
||||
int mtu = MTU + 40;
|
||||
int rc = 0;
|
||||
int r2q = 10;
|
||||
|
||||
/* to avoid some kernel warnings with small rates */
|
||||
if(download_limit < 120) r2q = 1;
|
||||
|
||||
burst = download_limit * 1000 / 8 / HZ; /* burst (buffer size) in bytes */
|
||||
burst = burst < mtu ? mtu : burst; /* but burst should be at least mtu */
|
||||
|
||||
rc |= tc_do_command("qdisc add dev %s root handle 1: htb default 2 r2q %d", dev, 1700);
|
||||
rc |= tc_do_command("class add dev %s parent 1: classid 1:1 htb rate 100Mbps ceil 100Mbps burst %d cburst %d mtu %d",
|
||||
dev, burst*10, burst, mtu);
|
||||
rc |= tc_do_command("class add dev %s parent 1:1 classid 1:2 htb rate %dkbit ceil %dkbit burst %d cburst %d mtu %d prio 1",
|
||||
dev, download_limit, download_limit, burst*10, burst, mtu);
|
||||
|
||||
rc |= tc_do_command("qdisc add dev %s root handle 1: htb default 1 r2q %d", dev, r2q);
|
||||
rc |= tc_do_command("class add dev %s parent 1: classid 1:1 htb rate %dkbit ceil %dkbit burst %d cburst %d mtu %d prio 1",
|
||||
dev, download_limit, download_limit, burst*2, burst, mtu);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user