summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--accel-pppd/accel-ppp.conf1
-rw-r--r--accel-pppd/accel-ppp.conf.53
-rw-r--r--accel-pppd/radius/acct.c7
-rw-r--r--accel-pppd/radius/auth.c2
-rw-r--r--accel-pppd/radius/radius_p.h19
-rw-r--r--accel-pppd/radius/req.c22
-rw-r--r--accel-pppd/radius/serv.c170
7 files changed, 198 insertions, 26 deletions
diff --git a/accel-pppd/accel-ppp.conf b/accel-pppd/accel-ppp.conf
index 62ac2328..f8cc66de 100644
--- a/accel-pppd/accel-ppp.conf
+++ b/accel-pppd/accel-ppp.conf
@@ -133,6 +133,7 @@ verbose=1
#max-try=3
#acct-timeout=120
#acct-delay-time=0
+#acct-on=0
[client-ip-range]
10.0.0.0/8
diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5
index 9f7740a3..cb6156ac 100644
--- a/accel-pppd/accel-ppp.conf.5
+++ b/accel-pppd/accel-ppp.conf.5
@@ -532,6 +532,9 @@ Specifies whether radius client should include Acct-Delay-Time attribute to acco
.TP
.BI "default-realm=" realm
Append specified realm to username.
+.TP
+.BI "acct-on=" 0|1
+Specifies whether radius client should send Account-Request with Acct-Status-Type=Account-On on startup and Acct-Status-Type=Account-Off on shutdown.
.SH [log]
.br
Configuration of log and log_file modules.
diff --git a/accel-pppd/radius/acct.c b/accel-pppd/radius/acct.c
index d6a84dea..49c47fb3 100644
--- a/accel-pppd/radius/acct.c
+++ b/accel-pppd/radius/acct.c
@@ -124,7 +124,7 @@ static void __rad_req_send(struct rad_req_t *req)
continue;
}
- rad_req_send(req, conf_interim_verbose);
+ rad_req_send(req, conf_interim_verbose ? log_ppp_info2 : NULL);
if (!req->hnd.tpd) {
triton_md_register_handler(req->rpd->ses->ctrl->ctx, &req->hnd);
triton_md_enable_handler(&req->hnd, MD_MODE_READ);
@@ -280,7 +280,7 @@ int rad_acct_start(struct radius_pd_t *rpd)
goto out_err;
}
- if (rad_req_send(rpd->acct_req, conf_verbose))
+ if (rad_req_send(rpd->acct_req, conf_verbose ? log_ppp_info1 : NULL))
goto out_err;
__sync_add_and_fetch(&rpd->acct_req->serv->stat_acct_sent, 1);
@@ -304,7 +304,6 @@ int rad_acct_start(struct radius_pd_t *rpd)
if (rpd->acct_req->reply->id != rpd->acct_req->pack->id || rpd->acct_req->reply->code != CODE_ACCOUNTING_RESPONSE) {
rad_packet_free(rpd->acct_req->reply);
rpd->acct_req->reply = NULL;
- rpd->acct_req->pack->id++;
__sync_add_and_fetch(&rpd->acct_req->serv->stat_acct_lost, 1);
stat_accm_add(rpd->acct_req->serv->stat_acct_lost_1m, 1);
stat_accm_add(rpd->acct_req->serv->stat_acct_lost_5m, 1);
@@ -431,7 +430,7 @@ void rad_acct_stop(struct radius_pd_t *rpd)
if (req_set_RA(rpd->acct_req, rpd->acct_req->serv->secret))
break;
}
- if (rad_req_send(rpd->acct_req, conf_verbose))
+ if (rad_req_send(rpd->acct_req, conf_verbose ? log_ppp_info1 : NULL))
break;
__sync_add_and_fetch(&rpd->acct_req->serv->stat_acct_sent, 1);
rad_req_wait(rpd->acct_req, conf_timeout);
diff --git a/accel-pppd/radius/auth.c b/accel-pppd/radius/auth.c
index dafc8d63..37b72915 100644
--- a/accel-pppd/radius/auth.c
+++ b/accel-pppd/radius/auth.c
@@ -161,7 +161,7 @@ static int rad_auth_send(struct rad_req_t *req)
for(i = 0; i < conf_max_try; i++) {
__sync_add_and_fetch(&req->serv->stat_auth_sent, 1);
clock_gettime(CLOCK_MONOTONIC, &tv);
- if (rad_req_send(req, conf_verbose))
+ if (rad_req_send(req, conf_verbose ? log_ppp_info1 : NULL))
goto out;
timeout = conf_timeout;
diff --git a/accel-pppd/radius/radius_p.h b/accel-pppd/radius/radius_p.h
index 4a17202f..29a971fb 100644
--- a/accel-pppd/radius/radius_p.h
+++ b/accel-pppd/radius/radius_p.h
@@ -12,8 +12,7 @@
struct rad_server_t;
-struct radius_pd_t
-{
+struct radius_pd_t {
struct list_head entry;
struct ap_private pd;
struct ap_session *ses;
@@ -46,8 +45,7 @@ struct radius_pd_t
struct list_head plugin_list;
};
-struct rad_req_t
-{
+struct rad_req_t {
struct list_head entry;
struct triton_context_t ctx;
struct triton_md_handler_t hnd;
@@ -58,15 +56,19 @@ struct rad_req_t
struct radius_pd_t *rpd;
struct rad_server_t *serv;
+ struct triton_context_t *wait_ctx;
in_addr_t server_addr;
int server_port;
int type;
+
+ void (*log)(const char *fmt, ...);
};
-struct rad_server_t
-{
+struct rad_server_t {
struct list_head entry;
+ struct triton_context_t ctx;
+ struct triton_timer_t timer;
int id;
in_addr_t addr;
char *secret;
@@ -105,7 +107,10 @@ struct rad_server_t
struct stat_accm_t *stat_interim_query_1m;
struct stat_accm_t *stat_interim_query_5m;
+ int starting:1;
+ int acct_on:1;
int need_free:1;
+ int need_close:1;
};
#define RAD_SERV_AUTH 0
@@ -143,7 +148,7 @@ struct rad_req_t *rad_req_alloc(struct radius_pd_t *rpd, int code, const char *u
struct rad_req_t *rad_req_alloc2(struct radius_pd_t *rpd, int code, const char *username, in_addr_t addr, int port);
int rad_req_acct_fill(struct rad_req_t *);
void rad_req_free(struct rad_req_t *);
-int rad_req_send(struct rad_req_t *, int verbose);
+int rad_req_send(struct rad_req_t *req, void (*log)(const char *fmt, ...));
int rad_req_wait(struct rad_req_t *, int);
struct radius_pd_t *find_pd(struct ap_session *ses);
diff --git a/accel-pppd/radius/req.c b/accel-pppd/radius/req.c
index 8fc65dba..3224134f 100644
--- a/accel-pppd/radius/req.c
+++ b/accel-pppd/radius/req.c
@@ -60,6 +60,9 @@ static struct rad_req_t *__rad_req_alloc(struct radius_pd_t *rpd, int code, cons
break;
}
+ if (conf_verbose)
+ req->log = log_ppp_info1;
+
req->pack = rad_packet_alloc(code);
if (!req->pack)
goto out_err;
@@ -253,7 +256,7 @@ out_err:
return -1;
}
-int rad_req_send(struct rad_req_t *req, int verbose)
+int rad_req_send(struct rad_req_t *req, void (*log)(const char *fmt, ...))
{
if (req->hnd.fd == -1 && make_socket(req))
return -1;
@@ -261,9 +264,9 @@ int rad_req_send(struct rad_req_t *req, int verbose)
if (!req->pack->buf && rad_packet_build(req->pack, req->RA))
goto out_err;
- if (verbose) {
- log_ppp_info1("send ");
- rad_packet_print(req->pack, req->serv, log_ppp_info1);
+ if (log) {
+ log("send ");
+ rad_packet_print(req->pack, req->serv, log);
}
rad_packet_send(req->pack, req->hnd.fd, NULL);
@@ -278,7 +281,7 @@ out_err:
static void req_wakeup(struct rad_req_t *req)
{
- struct triton_context_t *ctx = req->rpd->ses->ctrl->ctx;
+ struct triton_context_t *ctx = req->wait_ctx;
if (req->timeout.tpd)
triton_timer_del(&req->timeout);
triton_md_unregister_handler(&req->hnd);
@@ -317,10 +320,11 @@ static void rad_req_timeout(struct triton_timer_t *t)
int rad_req_wait(struct rad_req_t *req, int timeout)
{
+ req->wait_ctx = triton_context_self();
req->hnd.read = rad_req_read;
req->timeout.expire = rad_req_timeout;
- triton_context_register(&req->ctx, req->rpd->ses);
+ triton_context_register(&req->ctx, req->rpd ? req->rpd->ses : NULL);
triton_context_set_priority(&req->ctx, 1);
triton_md_register_handler(&req->ctx, &req->hnd);
triton_md_enable_handler(&req->hnd, MD_MODE_READ);
@@ -332,9 +336,9 @@ int rad_req_wait(struct rad_req_t *req, int timeout)
triton_context_schedule();
- if (conf_verbose && req->reply) {
- log_ppp_info1("recv ");
- rad_packet_print(req->reply, req->serv, log_ppp_info1);
+ if (req->log && req->reply) {
+ req->log("recv ");
+ rad_packet_print(req->reply, req->serv, req->log);
}
return 0;
}
diff --git a/accel-pppd/radius/serv.c b/accel-pppd/radius/serv.c
index ff354e54..c7b19166 100644
--- a/accel-pppd/radius/serv.c
+++ b/accel-pppd/radius/serv.c
@@ -15,14 +15,20 @@
#include "events.h"
#include "cli.h"
#include "utils.h"
+
+#include "crypto.h"
+
#include "radius_p.h"
#include "memdebug.h"
+static int conf_acct_on;
+
static int num;
static LIST_HEAD(serv_list);
static void __free_server(struct rad_server_t *);
+static void serv_ctx_close(struct triton_context_t *);
static struct rad_server_t *__rad_server_get(int type, struct rad_server_t *exclude, in_addr_t addr, int port)
{
@@ -85,15 +91,19 @@ void rad_server_put(struct rad_server_t *s, int type)
{
__sync_sub_and_fetch(&s->client_cnt[type], 1);
- if (s->need_free && !s->client_cnt[0] && !s->client_cnt[1])
- __free_server(s);
+ if ((s->need_free || s->need_close) && !s->client_cnt[0] && !s->client_cnt[1]) {
+ if (s->need_close)
+ triton_context_call(&s->ctx, (triton_event_func)serv_ctx_close, &s->ctx);
+ else
+ __free_server(s);
+ }
}
int rad_server_req_enter(struct rad_req_t *req)
{
struct timespec ts;
- if (req->serv->need_free)
+ if (req->serv->need_free || req->serv->starting)
return -1;
clock_gettime(CLOCK_MONOTONIC, &ts);
@@ -217,6 +227,127 @@ void rad_server_reply(struct rad_server_t *s)
s->timeout_cnt = 0;
}
+static int req_set_RA(struct rad_req_t *req, const char *secret)
+{
+ MD5_CTX ctx;
+
+ if (rad_packet_build(req->pack, req->RA))
+ return -1;
+
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, req->pack->buf, req->pack->len);
+ MD5_Update(&ctx, secret, strlen(secret));
+ MD5_Final(req->pack->buf + 4, &ctx);
+
+ return 0;
+}
+
+static void send_acct_on(struct rad_server_t *s)
+{
+ struct rad_req_t *req = _malloc(sizeof(*req));
+ int i;
+
+ if (!req)
+ goto out_err;
+
+ memset(req, 0, sizeof(*req));
+ req->hnd.fd = -1;
+ req->type = RAD_SERV_ACCT;
+ req->server_addr = s->addr;
+ req->server_port = s->acct_port;
+ req->serv = s;
+ __sync_add_and_fetch(&s->client_cnt[req->type], 1);
+ if (conf_verbose)
+ req->log = log_info1;
+
+ req->pack = rad_packet_alloc(CODE_ACCOUNTING_REQUEST);
+ if (!req->pack)
+ goto out_err;
+
+ if (rad_packet_add_val(req->pack, NULL, "Acct-Status-Type", s->starting ? "Accounting-On" : "Accounting-Off"))
+ goto out_err;
+
+ if (conf_nas_identifier)
+ if (rad_packet_add_str(req->pack, NULL, "NAS-Identifier", conf_nas_identifier))
+ goto out_err;
+
+ if (conf_nas_ip_address)
+ if (rad_packet_add_ipaddr(req->pack, NULL, "NAS-IP-Address", conf_nas_ip_address))
+ goto out_err;
+
+ if (req_set_RA(req, s->secret))
+ goto out_err;
+
+ for (i = 0; i < conf_max_try; i++) {
+ if (rad_req_send(req, conf_verbose ? log_info1 : NULL))
+ goto out_err;
+
+ rad_req_wait(req, conf_timeout);
+
+ if (!s->starting)
+ break;
+
+ if (!req->reply)
+ continue;
+
+ if (req->reply->id == req->pack->id && req->reply->code == CODE_ACCOUNTING_RESPONSE) {
+ s->starting = 0;
+ s->acct_on = 1;
+ break;
+ }
+
+ rad_packet_free(req->reply);
+ req->reply = NULL;
+ }
+
+ if (!s->starting) {
+ if (s->timer.tpd)
+ triton_timer_del(&s->timer);
+
+ if (!s->acct_on)
+ triton_context_unregister(&s->ctx);
+
+ rad_req_free(req);
+
+ return;
+ }
+
+out_err:
+ if (req)
+ rad_req_free(req);
+
+ if (s->timer.tpd)
+ triton_timer_mod(&s->timer, 0);
+ else
+ triton_timer_add(&s->ctx, &s->timer, 0);
+}
+
+static void restart_acct_on(struct triton_timer_t *t)
+{
+ struct rad_server_t *s = container_of(t, typeof(*s), timer);
+
+ send_acct_on(s);
+}
+
+static void serv_ctx_close(struct triton_context_t *ctx)
+{
+ struct rad_server_t *s = container_of(ctx, typeof(*s), ctx);
+
+ if (s->timer.tpd)
+ triton_timer_del(&s->timer);
+
+ s->need_close = 1;
+
+ if (!s->client_cnt[0] && !s->client_cnt[1]) {
+ if (s->acct_on) {
+ s->acct_on = 0;
+ s->starting = 0;
+ s->need_close = 0;
+ send_acct_on(s);
+ } else
+ triton_context_unregister(ctx);
+ }
+}
static void show_stat(struct rad_server_t *s, void *client)
{
@@ -291,6 +422,7 @@ static void __add_server(struct rad_server_t *s)
INIT_LIST_HEAD(&s->req_queue);
pthread_mutex_init(&s->lock, NULL);
list_add_tail(&s->entry, &serv_list);
+ s->starting = conf_acct_on;
s->stat_auth_lost_1m = stat_accm_create(60);
s->stat_auth_lost_5m = stat_accm_create(5 * 60);
@@ -557,9 +689,16 @@ static void load_config(void)
struct rad_server_t *s;
struct rad_req_t *r;
struct list_head *pos, *n;
+ const char *opt1;
list_for_each_entry(s, &serv_list, entry)
s->need_free = 1;
+
+ opt1 = conf_get_opt("radius", "acct-on");
+ if (opt1)
+ conf_acct_on = atoi(opt1);
+ else
+ conf_acct_on = 0;
list_for_each_entry(opt, &sect->items, entry) {
if (strcmp(opt->name, "server"))
@@ -578,8 +717,12 @@ static void load_config(void)
triton_context_wakeup(r->rpd->ses->ctrl->ctx);
}
- if (!s->client_cnt[0] && !s->client_cnt[1])
- __free_server(s);
+ if (!s->client_cnt[0] && !s->client_cnt[1]) {
+ if (s->acct_on)
+ triton_context_call(&s->ctx, (triton_event_func)serv_ctx_close, &s->ctx);
+ else
+ __free_server(s);
+ }
}
}
@@ -592,6 +735,23 @@ static void load_config(void)
break;
}
}
+
+ list_for_each_entry(s, &serv_list, entry) {
+ if (s->starting) {
+ if (!conf_accounting || !s->acct_port)
+ s->starting = 0;
+ else {
+ s->ctx.close = serv_ctx_close;
+ s->timer.expire = restart_acct_on;
+ s->timer.expire_tv.tv_sec = 10;
+
+ triton_context_register(&s->ctx, NULL);
+ triton_context_set_priority(&s->ctx, 1);
+ triton_context_call(&s->ctx, (triton_event_func)send_acct_on, s);
+ triton_context_wakeup(&s->ctx);
+ }
+ }
+ }
}
static void init(void)