diff --git a/NEWS b/NEWS index 42c6bb1f..b6be7a45 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,10 @@ - Added the predictable-ips configuration option. That option allows to disable the default "stable" IP assignment, and use completely random assignment. +- The route configuration directive accepts the keyword 'default', + and will return a default route irrespective of any other route + directives. That allows overriding existing routes with a default + route for specific users and groups. * Version 0.3.4 (released 2014-05-01) diff --git a/src/config.c b/src/config.c index d93ffb86..2b222448 100644 --- a/src/config.c +++ b/src/config.c @@ -254,7 +254,7 @@ static void parse_cfg_file(const char* file, struct cfg_st *config) { tOptionValue const * pov; const tOptionValue* val, *prev; -unsigned j, mand; +unsigned j, i, mand; char** auth = NULL; unsigned auth_size = 0; unsigned prefix = 0; @@ -482,12 +482,16 @@ unsigned force_cert_auth; READ_MULTI_LINE("route", config->network.routes, config->network.routes_size); for (j=0;jnetwork.routes_size;j++) { - if (strstr(config->network.routes[j], "0.0.0.0/0") != 0) { - fprintf(stderr, "Illegal route '%s' detected; to set a default route remove all route directives\n", - config->network.routes[j]); - exit(1); + if (strcmp(config->network.routes[j], "0.0.0.0/0") == 0 || + strcmp(config->network.routes[j], "default") == 0) { + /* set default route */ + for (i=0;inetwork.routes[i]); + config->network.routes_size = 0; + break; } } + READ_MULTI_LINE("dns", config->network.dns, config->network.dns_size); if (config->network.dns_size == 0) { /* try the aliases */ diff --git a/src/ocserv-args.def b/src/ocserv-args.def index e38e5497..6d68ae21 100644 --- a/src/ocserv-args.def +++ b/src/ocserv-args.def @@ -338,7 +338,9 @@ ping-leases = false # config-per-user/group or even connect and disconnect scripts. # # To set the server as the default gateway for the client just -# comment out all routes from the server. +# comment out all routes from the server, or use the special keyword +# 'default'. + route = 192.168.1.0/255.255.255.0 route = 192.168.5.0/255.255.255.0 #route = fef4:db8:1000:1001::/64 diff --git a/src/worker-auth.c b/src/worker-auth.c index 1f716093..46fe8a67 100644 --- a/src/worker-auth.c +++ b/src/worker-auth.c @@ -327,8 +327,22 @@ static int recv_cookie_auth_reply(worker_st * ws) for (i = 0; i < ws->routes_size; i++) { ws->routes[i] = talloc_strdup(ws, msg->routes[i]); + + /* If a default route is detected */ + if (ws->routes[i] != NULL && + (strcmp(ws->routes[i], "default") == 0 || + strcmp(ws->routes[i], "0.0.0.0/0") == 0)) { + + /* disable all routes */ + ws->routes_size = 0; + ws->default_route = 1; + break; + } } + if (check_if_default_route(ws->routes, ws->routes_size)) + ws->default_route = 1; + ws->dns_size = msg->n_dns; for (i = 0; i < ws->dns_size; i++) { diff --git a/src/worker-misc.c b/src/worker-misc.c index 620698d4..67ddf269 100644 --- a/src/worker-misc.c +++ b/src/worker-misc.c @@ -171,6 +171,19 @@ udp_fd_fail: return -1; } +unsigned check_if_default_route(char **routes, unsigned routes_size) +{ + unsigned i; + + for (i=0;iconfig->network.routes_size > 0) vinfo->routes = ws->config->network.routes; + if (check_if_default_route(vinfo->routes, vinfo->routes_size)) + ws->default_route = 1; + vinfo->ipv4_netmask = ws->config->network.ipv4_netmask; vinfo->ipv6_netmask = ws->config->network.ipv6_netmask; vinfo->ipv6_prefix = ws->config->network.ipv6_prefix; diff --git a/src/worker-vpn.c b/src/worker-vpn.c index 1674c1dc..28cb1c32 100644 --- a/src/worker-vpn.c +++ b/src/worker-vpn.c @@ -1496,53 +1496,56 @@ static int connect_handler(worker_st * ws) SEND_ERR(ret); } - for (i = 0; i < ws->vinfo.routes_size; i++) { - if (strchr(ws->vinfo.routes[i], ':') != 0) - ip6 = 1; - else - ip6 = 0; + if (ws->default_route == 0) { + for (i = 0; i < ws->vinfo.routes_size; i++) { + if (strchr(ws->vinfo.routes[i], ':') != 0) + ip6 = 1; + else + ip6 = 0; - if (req->no_ipv6 != 0 && ip6 != 0) - continue; - if (req->no_ipv4 != 0 && ip6 == 0) - continue; - oclog(ws, LOG_DEBUG, "adding route %s", ws->vinfo.routes[i]); + if (req->no_ipv6 != 0 && ip6 != 0) + continue; + if (req->no_ipv4 != 0 && ip6 == 0) + continue; + oclog(ws, LOG_DEBUG, "adding route %s", ws->vinfo.routes[i]); - if (ip6 != 0 && ws->full_ipv6) { - ret = tls_printf(ws->session, + if (ip6 != 0 && ws->full_ipv6) { + ret = tls_printf(ws->session, "X-CSTP-Split-Include-IP6: %s\r\n", ws->vinfo.routes[i]); - } else { - ret = tls_printf(ws->session, + } else { + ret = tls_printf(ws->session, "X-CSTP-Split-Include: %s\r\n", ws->vinfo.routes[i]); + } + SEND_ERR(ret); } - SEND_ERR(ret); - } - for (i = 0; i < ws->routes_size; i++) { - if (strchr(ws->routes[i], ':') != 0) - ip6 = 1; - else - ip6 = 0; + for (i = 0; i < ws->routes_size; i++) { + if (strchr(ws->routes[i], ':') != 0) + ip6 = 1; + else + ip6 = 0; - if (req->no_ipv6 != 0 && ip6 != 0) - continue; - if (req->no_ipv4 != 0 && ip6 == 0) - continue; - oclog(ws, LOG_DEBUG, "adding private route %s", ws->routes[i]); + if (req->no_ipv6 != 0 && ip6 != 0) + continue; + if (req->no_ipv4 != 0 && ip6 == 0) + continue; + oclog(ws, LOG_DEBUG, "adding private route %s", ws->routes[i]); - if (ip6 != 0 && ws->full_ipv6) { - ret = tls_printf(ws->session, + if (ip6 != 0 && ws->full_ipv6) { + ret = tls_printf(ws->session, "X-CSTP-Split-Include-IP6: %s\r\n", ws->routes[i]); - } else { - ret = tls_printf(ws->session, + } else { + ret = tls_printf(ws->session, "X-CSTP-Split-Include: %s\r\n", ws->routes[i]); + } + SEND_ERR(ret); } - SEND_ERR(ret); } + ret = tls_printf(ws->session, "X-CSTP-Keepalive: %u\r\n", ws->config->keepalive); diff --git a/src/worker.h b/src/worker.h index 3fba4691..e69ea3d7 100644 --- a/src/worker.h +++ b/src/worker.h @@ -212,6 +212,7 @@ typedef struct worker_st { /* information on the tun device addresses and network */ struct vpn_st vinfo; + unsigned default_route; /* additional data - received per user or per group */ unsigned routes_size; @@ -253,6 +254,7 @@ void __attribute__ ((format(printf, 3, 4))) int complete_vpn_info(worker_st * ws, struct vpn_st* vinfo); +unsigned check_if_default_route(char **routes, unsigned routes_size); int send_tun_mtu(worker_st *ws, unsigned int mtu); int handle_worker_commands(struct worker_st *ws);