diff options
-rw-r--r-- | accel-pppd/accel-ppp.conf | 1 | ||||
-rw-r--r-- | accel-pppd/accel-ppp.conf.5 | 3 | ||||
-rw-r--r-- | accel-pppd/radius/acct.c | 7 | ||||
-rw-r--r-- | accel-pppd/radius/auth.c | 2 | ||||
-rw-r--r-- | accel-pppd/radius/radius_p.h | 19 | ||||
-rw-r--r-- | accel-pppd/radius/req.c | 22 | ||||
-rw-r--r-- | accel-pppd/radius/serv.c | 170 |
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, §->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) |