diff options
author | Kozlov Dmitry <xeb@mail.ru> | 2012-08-13 13:35:06 +0400 |
---|---|---|
committer | Kozlov Dmitry <xeb@mail.ru> | 2012-08-13 13:35:06 +0400 |
commit | 846f19f490b662c16a118f9807b3adcffc486694 (patch) | |
tree | f96ca5d03096f32250c30c16a246fc0649408c1f | |
parent | e278acfec8bf86ce442acf7d753dd3992e6d87a8 (diff) | |
download | accel-ppp-846f19f490b662c16a118f9807b3adcffc486694.tar.gz accel-ppp-846f19f490b662c16a118f9807b3adcffc486694.zip |
ipoe: implements l4-redirect-on-rejects
-rw-r--r-- | accel-pppd/accel-ppp.conf | 8 | ||||
-rw-r--r-- | accel-pppd/accel-ppp.conf.5 | 5 | ||||
-rw-r--r-- | accel-pppd/ctrl/CMakeLists.txt | 5 | ||||
-rw-r--r-- | accel-pppd/ctrl/ipoe/ipoe.c | 149 |
4 files changed, 158 insertions, 9 deletions
diff --git a/accel-pppd/accel-ppp.conf b/accel-pppd/accel-ppp.conf index 0199f058..2e159de8 100644 --- a/accel-pppd/accel-ppp.conf +++ b/accel-pppd/accel-ppp.conf @@ -41,6 +41,7 @@ lease-time=600 max-lease-time=3600 #unit-cache=1000 l4-redirect-table=4 +#l4-redirect-on-reject=300 shared=0 ifcfg=1 mode=L2 @@ -185,13 +186,6 @@ down-limiter=tbf #leaf-qdisc=sfq perturb 10 verbose=1 -#tbf is obsolete, use shaper module -#[tbf] -#attr=Filter-Id -#down-burst-factor=0.1 -#up-burst-factor=1.0 -#latency=50 - [cli] telnet=127.0.0.1:2000 tcp=127.0.0.1:2001 diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5 index 82dd84a8..36299ff2 100644 --- a/accel-pppd/accel-ppp.conf.5 +++ b/accel-pppd/accel-ppp.conf.5 @@ -209,6 +209,11 @@ This should reduce kernel-level interface creation/deletion rate lack. Specifies number of table. If L4-Redirect radius attribute is received and it's value is not 0 or '0' then accel-ppp will add following rule: ip rule add from client_ip table .B n .TP +.BI "l4-redirect-on-reject=" n +If specified then if radius rejects access 'ip rule add from ip_addr table l4-redirect-table' rule will be created for time +.B n +seconds. +.TP .BI "shared=" 0|1 Specifies default value for per-interface .B shared diff --git a/accel-pppd/ctrl/CMakeLists.txt b/accel-pppd/ctrl/CMakeLists.txt index 9b6a11d6..91d5b36e 100644 --- a/accel-pppd/ctrl/CMakeLists.txt +++ b/accel-pppd/ctrl/CMakeLists.txt @@ -2,3 +2,8 @@ ADD_SUBDIRECTORY(pptp) ADD_SUBDIRECTORY(pppoe) ADD_SUBDIRECTORY(l2tp) ADD_SUBDIRECTORY(ipoe) + +if (OPENVPN) + ADD_SUBDIRECTORY(openvpn) +endif (OPENVPN) + diff --git a/accel-pppd/ctrl/ipoe/ipoe.c b/accel-pppd/ctrl/ipoe/ipoe.c index 9d6acc1c..1ddec374 100644 --- a/accel-pppd/ctrl/ipoe/ipoe.c +++ b/accel-pppd/ctrl/ipoe/ipoe.c @@ -59,6 +59,7 @@ static int conf_attr_dhcp_mask; static int conf_attr_l4_redirect; #endif static int conf_l4_redirect_table; +static int conf_l4_redirect_on_reject; static const char *conf_relay; #ifdef USE_LUA @@ -98,11 +99,24 @@ struct unit_cache int ifindex; }; +struct l4_redirect +{ + struct list_head entry; + int ifindex; + in_addr_t addr; + time_t timeout; +}; + static pthread_mutex_t uc_lock = PTHREAD_MUTEX_INITIALIZER; static LIST_HEAD(uc_list); static int uc_size; static mempool_t uc_pool; +static pthread_rwlock_t l4_list_lock = PTHREAD_RWLOCK_INITIALIZER; +static LIST_HEAD(l4_redirect_list); +static struct triton_timer_t l4_redirect_timer; +static struct triton_context_t l4_redirect_ctx; + static void ipoe_session_finished(struct ap_session *s); static void ipoe_drop_sessions(struct ipoe_serv *serv, struct ipoe_session *skip); static void ipoe_serv_close(struct triton_context_t *ctx); @@ -198,6 +212,87 @@ static void ipoe_session_set_username(struct ipoe_session *ses) ses->ses.username = _strdup(ses->ses.ifname); } +static void l4_redirect_list_add(in_addr_t addr, int ifindex) +{ + struct l4_redirect *n = _malloc(sizeof(*n)); + struct timespec ts; + + if (!n) + return; + + clock_gettime(CLOCK_MONOTONIC, &ts); + + memset(n, 0, sizeof(*n)); + n->addr = addr; + n->ifindex = ifindex; + n->timeout = ts.tv_sec + conf_l4_redirect_on_reject; + + ipoe_nl_modify(ifindex, addr, 1, NULL, NULL); + iprule_add(addr, conf_l4_redirect_table); + + pthread_rwlock_wrlock(&l4_list_lock); + + list_add_tail(&n->entry, &l4_redirect_list); + + if (!l4_redirect_timer.tpd) + triton_timer_add(&l4_redirect_ctx, &l4_redirect_timer, 0); + + pthread_rwlock_unlock(&l4_list_lock); +} + +static int l4_redirect_list_check(in_addr_t addr) +{ + struct l4_redirect *n; + + pthread_rwlock_rdlock(&l4_list_lock); + list_for_each_entry(n, &l4_redirect_list, entry) { + if (n->addr == addr) { + pthread_rwlock_unlock(&l4_list_lock); + return 1; + } + } + pthread_rwlock_unlock(&l4_list_lock); + return 0; +} + +static void l4_redirect_list_timer(struct triton_timer_t *t) +{ + struct l4_redirect *n; + struct timespec ts; + struct unit_cache *uc; + + clock_gettime(CLOCK_MONOTONIC, &ts); + + pthread_rwlock_wrlock(&l4_list_lock); + while (!list_empty(&l4_redirect_list)) { + n = list_entry(l4_redirect_list.next, typeof(*n), entry); + if (ts.tv_sec > n->timeout) { + list_del(&n->entry); + pthread_rwlock_unlock(&l4_list_lock); + iprule_del(n->addr, conf_l4_redirect_table); + + if (uc_size < conf_unit_cache && ipoe_nl_modify(n->ifindex, 0, 0, "", NULL)) { + uc = mempool_alloc(uc_pool); + uc->ifindex = n->ifindex; + pthread_mutex_lock(&uc_lock); + list_add_tail(&uc->entry, &uc_list); + ++uc_size; + pthread_mutex_unlock(&uc_lock); + } else + ipoe_nl_delete(n->ifindex); + + _free(n); + pthread_rwlock_wrlock(&l4_list_lock); + } else + break; + } + + if (list_empty(&l4_redirect_list) && l4_redirect_timer.tpd) + triton_timer_del(&l4_redirect_timer); + + pthread_rwlock_unlock(&l4_list_lock); +} + static void ipoe_change_l4_redirect(struct ipoe_session *ses, int del) { in_addr_t addr; @@ -296,6 +391,10 @@ static void ipoe_session_start(struct ipoe_session *ses) if (r == PWDB_DENIED) { if (conf_ppp_verbose) log_ppp_warn("authentication failed\n"); + if (conf_l4_redirect_on_reject && !ses->dhcpv4_request && ses->ifindex != -1) { + l4_redirect_list_add(ses->yiaddr, ses->ifindex); + ses->ifindex = -1; + } ap_session_terminate(&ses->ses, TERM_AUTH_ERROR, 0); return; } @@ -897,7 +996,10 @@ static struct ipoe_session *ipoe_session_create_up(struct ipoe_serv *serv, struc if (ap_shutdown) return NULL; - + + if (l4_redirect_list_check(iph->saddr)) + return NULL; + ses = mempool_alloc(ses_pool); if (!ses) { log_emerg("out of memery\n"); @@ -1088,6 +1190,26 @@ static void ipoe_serv_close(struct triton_context_t *ctx) _free(serv); } +static void l4_redirect_ctx_close(struct triton_context_t *ctx) +{ + struct l4_redirect *n; + + pthread_rwlock_wrlock(&l4_list_lock); + while (!list_empty(&l4_redirect_list)) { + n = list_entry(l4_redirect_list.next, typeof(*n), entry); + list_del(&n->entry); + iprule_del(n->addr, conf_l4_redirect_table); + ipoe_nl_delete(n->ifindex); + _free(n); + } + pthread_rwlock_unlock(&l4_list_lock); + + if (l4_redirect_timer.tpd) + triton_timer_del(&l4_redirect_timer); + + triton_context_unregister(&l4_redirect_ctx); +} + static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, void *client) { cli_send(client, "ipoe:\r\n"); @@ -1534,7 +1656,19 @@ static void load_config(void) if (opt) conf_l4_redirect_table = atoi(opt); else - conf_l4_redirect_table = 0; + conf_l4_redirect_table = 1; + + opt = conf_get_opt("ipoe", "l4-redirect-on-reject"); + if (opt) { + conf_l4_redirect_on_reject = atoi(opt); + } else + conf_l4_redirect_on_reject = 0; + + if (conf_l4_redirect_on_reject) { + l4_redirect_timer.period = conf_l4_redirect_on_reject / 10 * 1000; + if (l4_redirect_timer.tpd) + triton_timer_mod(&l4_redirect_timer, 0); + } opt = conf_get_opt("ipoe", "shared"); if (opt) @@ -1585,11 +1719,22 @@ static void load_config(void) load_local_nets(s); } +static struct triton_context_t l4_redirect_ctx = { + .close = l4_redirect_ctx_close, +}; + +static struct triton_timer_t l4_redirect_timer = { + .expire = l4_redirect_list_timer, +}; + static void ipoe_init(void) { ses_pool = mempool_create(sizeof(struct ipoe_session)); uc_pool = mempool_create(sizeof(struct unit_cache)); + triton_context_register(&l4_redirect_ctx, NULL); + triton_context_wakeup(&l4_redirect_ctx); + load_config(); cli_register_simple_cmd2(show_stat_exec, NULL, 2, "show", "stat"); |