summaryrefslogtreecommitdiff
path: root/accel-pptpd/ctrl/pppoe
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pptpd/ctrl/pppoe')
-rw-r--r--accel-pptpd/ctrl/pppoe/CMakeLists.txt1
-rw-r--r--accel-pptpd/ctrl/pppoe/cli.c16
-rw-r--r--accel-pptpd/ctrl/pppoe/dpado.c162
-rw-r--r--accel-pptpd/ctrl/pppoe/pppoe.c23
-rw-r--r--accel-pptpd/ctrl/pppoe/pppoe.h11
5 files changed, 188 insertions, 25 deletions
diff --git a/accel-pptpd/ctrl/pppoe/CMakeLists.txt b/accel-pptpd/ctrl/pppoe/CMakeLists.txt
index e29cbf7..6e70e4c 100644
--- a/accel-pptpd/ctrl/pppoe/CMakeLists.txt
+++ b/accel-pptpd/ctrl/pppoe/CMakeLists.txt
@@ -3,6 +3,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
ADD_LIBRARY(pppoe SHARED
pppoe.c
mac_filter.c
+ dpado.c
cli.c
)
diff --git a/accel-pptpd/ctrl/pppoe/cli.c b/accel-pptpd/ctrl/pppoe/cli.c
index c3088aa..7a62952 100644
--- a/accel-pptpd/ctrl/pppoe/cli.c
+++ b/accel-pptpd/ctrl/pppoe/cli.c
@@ -77,7 +77,7 @@ static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt,
static void set_verbose_help(char * const *f, int f_cnt, void *cli)
{
cli_send(cli, "pppoe set verbose <n> - set verbosity of pppoe logging\r\n");
- cli_send(cli, "pppoe set PADO-delay <delay> - set PADO delay (ms)\r\n");
+ cli_send(cli, "pppoe set PADO-delay <delay[,delay1:count1[,delay2:count2[,...]]]> - set PADO delays (ms)\r\n");
cli_send(cli, "pppoe set Service-Name <name> - set Service-Name to respond\r\n");
cli_send(cli, "pppoe set Service-Name * - respond with client's Service-Name\r\n");
cli_send(cli, "pppoe set AC-Name <name> - set AC-Name tag value\r\n");
@@ -102,7 +102,7 @@ static int show_pado_delay_exec(const char *cmd, char * const *f, int f_cnt, voi
if (f_cnt != 3)
return CLI_CMD_SYNTAX;
- cli_sendv(cli, "%i\r\n", conf_pado_delay);
+ cli_sendv(cli, "%s\r\n", conf_pado_delay);
return CLI_CMD_OK;
}
@@ -147,18 +147,12 @@ static int set_verbose_exec(const char *cmd, char * const *f, int f_cnt, void *c
static int set_pado_delay_exec(const char *cmd, char * const *f, int f_cnt, void *cli)
{
- char *endptr;
- int d;
-
if (f_cnt != 4)
return CLI_CMD_SYNTAX;
-
- d = strtol(f[3], &endptr, 10);
- if (*endptr || d < 0)
+
+ if (dpado_parse(f[3]))
return CLI_CMD_INVAL;
-
- conf_pado_delay = d;
-
+
return CLI_CMD_OK;
}
diff --git a/accel-pptpd/ctrl/pppoe/dpado.c b/accel-pptpd/ctrl/pppoe/dpado.c
new file mode 100644
index 0000000..765803c
--- /dev/null
+++ b/accel-pptpd/ctrl/pppoe/dpado.c
@@ -0,0 +1,162 @@
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <errno.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <net/ethernet.h>
+
+#include "list.h"
+#include "cli.h"
+#include "triton.h"
+#include "log.h"
+#include "memdebug.h"
+
+#include "pppoe.h"
+
+struct dpado_range_t
+{
+ struct list_head entry;
+ unsigned int conn_cnt;
+ int pado_delay;
+};
+
+static pthread_mutex_t dpado_range_lock = PTHREAD_MUTEX_INITIALIZER;
+static LIST_HEAD(dpado_range_list);
+static struct dpado_range_t *dpado_range_next;
+static struct dpado_range_t *dpado_range_prev;
+int pado_delay;
+
+void dpado_check_next(int conn_cnt)
+{
+ pthread_mutex_lock(&dpado_range_lock);
+ if (dpado_range_next && conn_cnt == dpado_range_next->conn_cnt) {
+ pado_delay = dpado_range_next->pado_delay;
+ dpado_range_prev = dpado_range_next;
+ if (dpado_range_next->entry.next != &dpado_range_list)
+ dpado_range_next = list_entry(dpado_range_next->entry.next, typeof(*dpado_range_next), entry);
+ else
+ dpado_range_next = NULL;
+ printf("active=%i, prev=%i:%i, next=%i:%i, pado_delay=%i\n", stat_active,
+ dpado_range_prev?dpado_range_prev->pado_delay:0,dpado_range_prev?dpado_range_prev->conn_cnt:0,
+ dpado_range_next?dpado_range_next->pado_delay:0,dpado_range_next?dpado_range_next->conn_cnt:0,
+ pado_delay);
+ }
+ pthread_mutex_unlock(&dpado_range_lock);
+}
+
+void dpado_check_prev(int conn_cnt)
+{
+ pthread_mutex_lock(&dpado_range_lock);
+ if (dpado_range_prev && conn_cnt == dpado_range_prev->conn_cnt) {
+ dpado_range_next = dpado_range_prev;
+ dpado_range_prev = list_entry(dpado_range_prev->entry.prev, typeof(*dpado_range_prev), entry);
+ pado_delay = dpado_range_prev->pado_delay;
+ printf("active=%i, prev=%i:%i, next=%i:%i, pado_delay=%i\n", stat_active,
+ dpado_range_prev?dpado_range_prev->pado_delay:0,dpado_range_prev?dpado_range_prev->conn_cnt:0,
+ dpado_range_next?dpado_range_next->pado_delay:0,dpado_range_next?dpado_range_next->conn_cnt:0,
+ pado_delay);
+ }
+ pthread_mutex_unlock(&dpado_range_lock);
+}
+
+static void strip(char *str)
+{
+ char *ptr = str;
+ char *endptr = strchr(str, 0);
+ while (1) {
+ ptr = strchr(ptr, ' ');
+ if (ptr)
+ memmove(ptr, ptr + 1, endptr - ptr - 1);
+ else
+ break;
+ }
+}
+
+int dpado_parse(const char *str)
+{
+ char *str1 = _strdup(str);
+ char *ptr1, *ptr2, *ptr3, *endptr;
+ LIST_HEAD(range_list);
+ struct dpado_range_t *r;
+
+ strip(str1);
+
+ ptr1 = str1;
+
+ while (1) {
+ ptr2 = strchr(ptr1, ',');
+ if (ptr2)
+ *ptr2 = 0;
+ ptr3 = strchr(ptr1, ':');
+ if (ptr3)
+ *ptr3 = 0;
+
+ r = _malloc(sizeof(*r));
+ memset(r, 0, sizeof(*r));
+
+ r->pado_delay = strtol(ptr1, &endptr, 10);
+ if (*endptr)
+ goto out_err;
+
+ if (list_empty(&range_list))
+ r->conn_cnt = INT_MAX;
+ else {
+ if (!ptr3)
+ goto out_err;
+ r->conn_cnt = strtol(ptr3 + 1, &endptr, 10);
+ if (*endptr)
+ goto out_err;
+ }
+
+ list_add_tail(&r->entry, &range_list);
+ printf("parsed range: %i:%i\n", r->pado_delay, r->conn_cnt);
+
+ if (!ptr2)
+ break;
+
+ ptr1 = ptr2 + 1;
+ }
+
+ pthread_mutex_lock(&dpado_range_lock);
+ while (!list_empty(&dpado_range_list)) {
+ r = list_entry(dpado_range_list.next, typeof(*r), entry);
+ list_del(&r->entry);
+ _free(r);
+ }
+
+ dpado_range_next = NULL;
+ dpado_range_prev = NULL;
+
+ while (!list_empty(&range_list)) {
+ r = list_entry(range_list.next, typeof(*r), entry);
+ list_del(&r->entry);
+ list_add_tail(&r->entry, &dpado_range_list);
+
+ if (!dpado_range_prev || stat_active >= r->conn_cnt)
+ dpado_range_prev = r;
+ else if (!dpado_range_next)
+ dpado_range_next = r;
+ }
+
+ pado_delay = dpado_range_prev->pado_delay;
+
+ if (conf_pado_delay)
+ _free(conf_pado_delay);
+ conf_pado_delay = _strdup(str);
+ printf("active=%i, prev=%i:%i, next=%i:%i, pado_delay=%i\n", stat_active,
+ dpado_range_prev?dpado_range_prev->pado_delay:0,dpado_range_prev?dpado_range_prev->conn_cnt:0,
+ dpado_range_next?dpado_range_next->pado_delay:0,dpado_range_next?dpado_range_next->conn_cnt:0,
+ pado_delay);
+
+ pthread_mutex_unlock(&dpado_range_lock);
+
+ _free(str1);
+ return 0;
+
+out_err:
+ _free(str1);
+ log_emerg("pppoe: pado_delay: invalid format\n");
+ return -1;
+}
+
diff --git a/accel-pptpd/ctrl/pppoe/pppoe.c b/accel-pptpd/ctrl/pppoe/pppoe.c
index 57342ba..89525bc 100644
--- a/accel-pptpd/ctrl/pppoe/pppoe.c
+++ b/accel-pptpd/ctrl/pppoe/pppoe.c
@@ -59,16 +59,16 @@ struct delayed_pado_t
int conf_verbose;
char *conf_service_name;
char *conf_ac_name;
-int conf_pado_delay;
int conf_ifname_in_sid;
+char *conf_pado_delay;
static int shutdown_soft;
static mempool_t conn_pool;
static mempool_t pado_pool;
-uint32_t stat_active;
-uint32_t stat_delayed_pado;
+unsigned int stat_active;
+unsigned int stat_delayed_pado;
pthread_rwlock_t serv_lock = PTHREAD_RWLOCK_INITIALIZER;
LIST_HEAD(serv_list);
@@ -83,7 +83,7 @@ static int init_secret(struct pppoe_serv_t *serv);
static void disconnect(struct pppoe_conn_t *conn)
{
if (conn->ppp_started) {
- __sync_sub_and_fetch(&stat_active, 1);
+ dpado_check_prev(__sync_fetch_and_sub(&stat_active, 1));
conn->ppp_started = 0;
ppp_terminate(&conn->ppp, TERM_USER_REQUEST, 1);
}
@@ -132,7 +132,7 @@ static void ppp_finished(struct ppp_t *ppp)
log_ppp_debug("pppoe: ppp finished\n");
if (conn->ppp_started) {
- __sync_sub_and_fetch(&stat_active, 1);
+ dpado_check_prev(__sync_fetch_and_sub(&stat_active, 1));
conn->ppp_started = 0;
triton_context_call(&conn->ctx, (triton_event_func)disconnect, conn);
}
@@ -270,9 +270,10 @@ static void connect_channel(struct pppoe_conn_t *conn)
if (establish_ppp(&conn->ppp))
goto out_err_close;
- __sync_add_and_fetch(&stat_active, 1);
conn->ppp_started = 1;
+ dpado_check_next(__sync_add_and_fetch(&stat_active, 1));
+
return;
out_err_close:
@@ -647,7 +648,7 @@ static void pppoe_recv_PADI(struct pppoe_serv_t *serv, uint8_t *pack, int size)
int n, service_match = 0;
struct delayed_pado_t *pado;
- if (shutdown_soft)
+ if (shutdown_soft || pado_delay == -1)
return;
if (hdr->sid) {
@@ -692,7 +693,7 @@ static void pppoe_recv_PADI(struct pppoe_serv_t *serv, uint8_t *pack, int size)
return;
}
- if (conf_pado_delay) {
+ if (pado_delay) {
list_for_each_entry(pado, &serv->pado_list, entry) {
if (memcmp(pado->addr, ethhdr->h_source, ETH_ALEN))
continue;
@@ -721,7 +722,7 @@ static void pppoe_recv_PADI(struct pppoe_serv_t *serv, uint8_t *pack, int size)
}
pado->timer.expire = pado_timer;
- pado->timer.period = conf_pado_delay;
+ pado->timer.period = pado_delay;
triton_timer_add(&serv->ctx, &pado->timer, 0);
@@ -1202,8 +1203,8 @@ static void __init pppoe_init(void)
if (opt->val && strlen(opt->val))
conf_service_name = _strdup(opt->val);
} else if (!strcmp(opt->name, "pado-delay") || !strcmp(opt->name, "PADO-delay")) {
- if (opt->val && atoi(opt->val) > 0)
- conf_pado_delay = atoi(opt->val);
+ if (dpado_parse(opt->val))
+ _exit(EXIT_FAILURE);
} else if (!strcmp(opt->name, "ifname-in-sid")) {
if (!opt->val)
continue;
diff --git a/accel-pptpd/ctrl/pppoe/pppoe.h b/accel-pptpd/ctrl/pppoe/pppoe.h
index 5db3a49..323715d 100644
--- a/accel-pptpd/ctrl/pppoe/pppoe.h
+++ b/accel-pptpd/ctrl/pppoe/pppoe.h
@@ -85,10 +85,10 @@ struct pppoe_serv_t
extern int conf_verbose;
extern char *conf_service_name;
extern char *conf_ac_name;
-extern int conf_pado_delay;
+extern char *conf_pado_delay;
-extern uint32_t stat_active;
-extern uint32_t stat_delayed_pado;
+extern unsigned int stat_active;
+extern unsigned int stat_delayed_pado;
extern pthread_rwlock_t serv_lock;
extern struct list_head serv_list;
@@ -97,5 +97,10 @@ int mac_filter_check(const uint8_t *addr);
void pppoe_server_start(const char *intf, void *client);
void pppoe_server_stop(const char *intf);
+extern int pado_delay;
+void dpado_check_next(int conn_cnt);
+void dpado_check_prev(int conn_cnt);
+int dpado_parse(const char *str);
+
#endif