diff options
author | Kozlov Dmitry <dima@server> | 2011-06-22 10:25:53 +0400 |
---|---|---|
committer | Kozlov Dmitry <dima@server> | 2011-06-22 10:25:53 +0400 |
commit | 852f842d6521c5c260d24cf23a0e5a317cf25a0b (patch) | |
tree | a3ee3c141c49d9e3811d586ae3735c2c21c3d4f2 /accel-pppd/radius | |
parent | 05ad71a30740f1cca95e9f47a8a56c65b03402ed (diff) | |
download | accel-ppp-852f842d6521c5c260d24cf23a0e5a317cf25a0b.tar.gz accel-ppp-852f842d6521c5c260d24cf23a0e5a317cf25a0b.zip |
temp
Diffstat (limited to 'accel-pppd/radius')
-rw-r--r-- | accel-pppd/radius/CMakeLists.txt | 1 | ||||
-rw-r--r-- | accel-pppd/radius/acct.c | 221 | ||||
-rw-r--r-- | accel-pppd/radius/auth.c | 91 | ||||
-rw-r--r-- | accel-pppd/radius/radius.c | 8 | ||||
-rw-r--r-- | accel-pppd/radius/radius_p.h | 37 | ||||
-rw-r--r-- | accel-pppd/radius/req.c | 14 |
6 files changed, 251 insertions, 121 deletions
diff --git a/accel-pppd/radius/CMakeLists.txt b/accel-pppd/radius/CMakeLists.txt index d85d60c8..0c1789ef 100644 --- a/accel-pppd/radius/CMakeLists.txt +++ b/accel-pppd/radius/CMakeLists.txt @@ -5,6 +5,7 @@ SET(sources packet.c auth.c acct.c + serv.c dm_coa.c radius.c ) diff --git a/accel-pppd/radius/acct.c b/accel-pppd/radius/acct.c index 31ab298f..2657fb36 100644 --- a/accel-pppd/radius/acct.c +++ b/accel-pppd/radius/acct.c @@ -116,6 +116,30 @@ static int rad_acct_read(struct triton_md_handler_t *h) return 0; } +static void __rad_req_send(struct rad_req_t *req) +{ + while (1) { + + if (rad_server_req_enter(req)) { + if (rad_server_realloc(req, 1)) { + log_ppp_warn("radius:acct: no servers available, terminating session...\n"); + if (conf_acct_timeout) { + ppp_terminate(req->rpd->ppp, TERM_NAS_ERROR, 0); + return; + } + break; + } + continue; + } + + rad_req_send(req, conf_interim_verbose); + + rad_server_req_exit(req); + + break; + } +} + static void rad_acct_timeout(struct triton_timer_t *t) { struct rad_req_t *req = container_of(t, typeof(*req), timeout); @@ -130,9 +154,13 @@ static void rad_acct_timeout(struct triton_timer_t *t) dt = ts - req->rpd->acct_timestamp; if (dt > conf_acct_timeout) { - log_ppp_warn("radius:acct: no response, terminating session...\n"); - ppp_terminate(req->rpd->ppp, TERM_NAS_ERROR, 0); - return; + rad_server_fail(req->serv); + if (rad_server_realloc(req, 1)) { + log_ppp_warn("radius:acct: no servers available, terminating session...\n"); + ppp_terminate(req->rpd->ppp, TERM_NAS_ERROR, 0); + return; + } + time(&req->rpd->acct_timestamp); } if (dt > conf_acct_timeout / 2) { req->timeout.period += 1000; @@ -147,10 +175,11 @@ static void rad_acct_timeout(struct triton_timer_t *t) if (conf_acct_delay_time) { req->pack->id++; rad_packet_change_int(req->pack, NULL, "Acct-Delay-Time", dt); - req_set_RA(req, conf_acct_secret); + req_set_RA(req, req->serv->acct_secret); } - rad_req_send(req, conf_interim_verbose); + __rad_req_send(req); + __sync_add_and_fetch(&stat_interim_sent, 1); } @@ -175,8 +204,10 @@ static void rad_acct_interim_update(struct triton_timer_t *t) rad_packet_change_val(rpd->acct_req->pack, NULL, "Acct-Status-Type", "Interim-Update"); if (conf_acct_delay_time) rad_packet_change_int(rpd->acct_req->pack, NULL, "Acct-Delay-Time", 0); - req_set_RA(rpd->acct_req, conf_acct_secret); - rad_req_send(rpd->acct_req, conf_interim_verbose); + req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret); + + __rad_req_send(rpd->acct_req); + __sync_add_and_fetch(&stat_interim_sent, 1); if (conf_acct_timeout) { rpd->acct_req->timeout.period = conf_timeout * 1000; @@ -189,8 +220,8 @@ int rad_acct_start(struct radius_pd_t *rpd) int i; time_t ts; unsigned int dt; - - if (!conf_acct_secret) + + if (!rpd->acct_req->serv) return 0; rpd->acct_req = rad_req_alloc(rpd, CODE_ACCOUNTING_REQUEST, rpd->ppp->username); @@ -216,50 +247,75 @@ int rad_acct_start(struct radius_pd_t *rpd) time(&rpd->acct_timestamp); - if (req_set_RA(rpd->acct_req, conf_acct_secret)) + if (req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret)) goto out_err; - for (i = 0; i < conf_max_try; i++) { - if (conf_acct_delay_time) { - time(&ts); - rad_packet_change_int(rpd->acct_req->pack, NULL, "Acct-Delay-Time", ts - rpd->acct_timestamp); - if (req_set_RA(rpd->acct_req, conf_acct_secret)) + while (1) { + + if (rad_server_req_enter(rpd->acct_req)) { + if (rad_server_realloc(rpd->acct_req, 1)) { + log_ppp_warn("radius:acct_start: no servers available\n"); goto out_err; + } + if (req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret)) + goto out_err; + continue; } - if (rad_req_send(rpd->acct_req, conf_verbose)) - goto out_err; - __sync_add_and_fetch(&stat_acct_sent, 1); - rad_req_wait(rpd->acct_req, conf_timeout); - if (!rpd->acct_req->reply) { - if (conf_acct_delay_time) + + for (i = 0; i < conf_max_try; i++) { + if (conf_acct_delay_time) { + time(&ts); + rad_packet_change_int(rpd->acct_req->pack, NULL, "Acct-Delay-Time", ts - rpd->acct_timestamp); + if (req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret)) + goto out_err; + } + + if (rad_req_send(rpd->acct_req, conf_verbose)) + goto out_err; + + __sync_add_and_fetch(&stat_acct_sent, 1); + + rad_req_wait(rpd->acct_req, conf_timeout); + + if (!rpd->acct_req->reply) { + if (conf_acct_delay_time) + rpd->acct_req->pack->id++; + __sync_add_and_fetch(&stat_acct_lost, 1); + stat_accm_add(stat_acct_lost_1m, 1); + stat_accm_add(stat_acct_lost_5m, 1); + continue; + } + + dt = (rpd->acct_req->reply->tv.tv_sec - rpd->acct_req->pack->tv.tv_sec) * 1000 + + (rpd->acct_req->reply->tv.tv_usec - rpd->acct_req->pack->tv.tv_usec) / 1000; + stat_accm_add(stat_acct_query_1m, dt); + stat_accm_add(stat_acct_query_5m, dt); + + 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(&stat_acct_lost, 1); - stat_accm_add(stat_acct_lost_1m, 1); - stat_accm_add(stat_acct_lost_5m, 1); - continue; + __sync_add_and_fetch(&stat_acct_lost, 1); + stat_accm_add(stat_acct_lost_1m, 1); + stat_accm_add(stat_acct_lost_5m, 1); + } else + break; } - dt = (rpd->acct_req->reply->tv.tv_sec - rpd->acct_req->pack->tv.tv_sec) * 1000 + - (rpd->acct_req->reply->tv.tv_usec - rpd->acct_req->pack->tv.tv_usec) / 1000; - stat_accm_add(stat_acct_query_1m, dt); - stat_accm_add(stat_acct_query_5m, dt); + rad_server_req_exit(rpd->acct_req); - 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(&stat_acct_lost, 1); - stat_accm_add(stat_acct_lost_1m, 1); - stat_accm_add(stat_acct_lost_5m, 1); + if (!rpd->acct_req->reply) { + rad_server_fail(rpd->acct_req->serv); + if (rad_server_realloc(rpd->acct_req, 1)) { + log_ppp_warn("radius:acct_start: no servers available\n"); + goto out_err; + } + if (req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret)) + goto out_err; } else break; } - if (!rpd->acct_req->reply) { - log_ppp_warn("radius:acct_start: no response\n"); - goto out_err; - } - rpd->acct_req->hnd.read = rad_acct_read; triton_md_register_handler(rpd->ppp->ctrl->ctx, &rpd->acct_req->hnd); @@ -290,7 +346,7 @@ void rad_acct_stop(struct radius_pd_t *rpd) time_t ts; unsigned int dt; - if (!conf_acct_secret) + if (!rpd->acct_req->serv) return; if (rpd->acct_interim_timer.tpd) @@ -330,7 +386,7 @@ void rad_acct_stop(struct radius_pd_t *rpd) } rad_packet_change_val(rpd->acct_req->pack, NULL, "Acct-Status-Type", "Stop"); req_set_stat(rpd->acct_req, rpd->ppp); - req_set_RA(rpd->acct_req, conf_acct_secret); + req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret); /// !!! rad_req_add_val(rpd->acct_req, "Acct-Terminate-Cause", ""); if (rpd->acct_req->reply) { @@ -340,41 +396,62 @@ void rad_acct_stop(struct radius_pd_t *rpd) time(&rpd->acct_timestamp); - for(i = 0; i < conf_max_try; i++) { - if (conf_acct_delay_time) { - time(&ts); - rad_packet_change_int(rpd->acct_req->pack, NULL, "Acct-Delay-Time", ts - rpd->acct_timestamp); - rpd->acct_req->pack->id++; - if (req_set_RA(rpd->acct_req, conf_acct_secret)) + while (1) { + + if (rad_server_req_enter(rpd->acct_req)) { + if (rad_server_realloc(rpd->acct_req, 1)) { + log_ppp_warn("radius:acct_stop: no servers available\n"); break; - } - if (rad_req_send(rpd->acct_req, conf_verbose)) - break; - __sync_add_and_fetch(&stat_acct_sent, 1); - rad_req_wait(rpd->acct_req, conf_timeout); - if (!rpd->acct_req->reply) { - __sync_add_and_fetch(&stat_acct_lost, 1); - stat_accm_add(stat_acct_lost_1m, 1); - stat_accm_add(stat_acct_lost_5m, 1); + } + req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret); continue; } - dt = (rpd->acct_req->reply->tv.tv_sec - rpd->acct_req->pack->tv.tv_sec) * 1000 + - (rpd->acct_req->reply->tv.tv_usec - rpd->acct_req->pack->tv.tv_usec) / 1000; - stat_accm_add(stat_acct_query_1m, dt); - stat_accm_add(stat_acct_query_5m, dt); + for(i = 0; i < conf_max_try; i++) { + if (conf_acct_delay_time) { + time(&ts); + rad_packet_change_int(rpd->acct_req->pack, NULL, "Acct-Delay-Time", ts - rpd->acct_timestamp); + rpd->acct_req->pack->id++; + if (req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret)) + break; + } + if (rad_req_send(rpd->acct_req, conf_verbose)) + break; + __sync_add_and_fetch(&stat_acct_sent, 1); + rad_req_wait(rpd->acct_req, conf_timeout); + if (!rpd->acct_req->reply) { + __sync_add_and_fetch(&stat_acct_lost, 1); + stat_accm_add(stat_acct_lost_1m, 1); + stat_accm_add(stat_acct_lost_5m, 1); + continue; + } + + dt = (rpd->acct_req->reply->tv.tv_sec - rpd->acct_req->pack->tv.tv_sec) * 1000 + + (rpd->acct_req->reply->tv.tv_usec - rpd->acct_req->pack->tv.tv_usec) / 1000; + stat_accm_add(stat_acct_query_1m, dt); + stat_accm_add(stat_acct_query_5m, dt); + + 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; + __sync_add_and_fetch(&stat_acct_lost, 1); + stat_accm_add(stat_acct_lost_1m, 1); + stat_accm_add(stat_acct_lost_5m, 1); + } else + break; + } - 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; - __sync_add_and_fetch(&stat_acct_lost, 1); - stat_accm_add(stat_acct_lost_1m, 1); - stat_accm_add(stat_acct_lost_5m, 1); - } else - break; + rad_server_req_exit(rpd->acct_req); + + if (!rpd->acct_req->reply) { + rad_server_fail(rpd->acct_req->serv); + if (rad_server_realloc(rpd->acct_req, 1)) { + log_ppp_warn("radius:acct_stop: no servers available\n"); + break; + } + req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret); + } } - if (!rpd->acct_req->reply) - log_ppp_warn("radius:acct_stop: no response\n"); rad_req_free(rpd->acct_req); rpd->acct_req = NULL; diff --git a/accel-pppd/radius/auth.c b/accel-pppd/radius/auth.c index 99e6e16d..849dcebe 100644 --- a/accel-pppd/radius/auth.c +++ b/accel-pppd/radius/auth.c @@ -30,7 +30,7 @@ static int decrypt_chap_mppe_keys(struct rad_req_t *req, struct rad_attr_t *attr memcpy(plain, attr->val.octets, 32); MD5_Init(&md5_ctx); - MD5_Update(&md5_ctx, conf_auth_secret, strlen(conf_auth_secret)); + MD5_Update(&md5_ctx, req->serv->auth_secret, strlen(req->serv->auth_secret)); MD5_Update(&md5_ctx, req->pack->buf + 4, 16); MD5_Final(md5, &md5_ctx); @@ -38,7 +38,7 @@ static int decrypt_chap_mppe_keys(struct rad_req_t *req, struct rad_attr_t *attr plain[i] ^= md5[i]; MD5_Init(&md5_ctx); - MD5_Update(&md5_ctx, conf_auth_secret, strlen(conf_auth_secret)); + MD5_Update(&md5_ctx, req->serv->auth_secret, strlen(req->serv->auth_secret)); MD5_Update(&md5_ctx, attr->val.octets, 16); MD5_Final(md5, &md5_ctx); @@ -74,7 +74,7 @@ static int decrypt_mppe_key(struct rad_req_t *req, struct rad_attr_t *attr, uint } MD5_Init(&md5_ctx); - MD5_Update(&md5_ctx, conf_auth_secret, strlen(conf_auth_secret)); + MD5_Update(&md5_ctx, req->serv->auth_secret, strlen(req->serv->auth_secret)); MD5_Update(&md5_ctx, req->pack->buf + 4, 16); MD5_Update(&md5_ctx, attr->val.octets, 2); MD5_Final(md5, &md5_ctx); @@ -90,7 +90,7 @@ static int decrypt_mppe_key(struct rad_req_t *req, struct rad_attr_t *attr, uint } MD5_Init(&md5_ctx); - MD5_Update(&md5_ctx, conf_auth_secret, strlen(conf_auth_secret)); + MD5_Update(&md5_ctx, req->serv->auth_secret, strlen(req->serv->auth_secret)); MD5_Update(&md5_ctx, attr->val.octets + 2, 16); MD5_Final(md5, &md5_ctx); @@ -145,42 +145,71 @@ static uint8_t* encrypt_password(const char *passwd, const char *secret, const u static int rad_auth_send(struct rad_req_t *req) { int i; - struct timeval tv; + struct timeval tv, tv2; unsigned int dt; + int timeout; - for(i = 0; i < conf_max_try; i++) { - __sync_add_and_fetch(&stat_auth_sent, 1); - gettimeofday(&tv, NULL); - if (rad_req_send(req, conf_verbose)) - goto out; + while (1) { + if (rad_server_req_enter(req)) { + if (rad_server_realloc(req, 0)) { + log_ppp_warn("radius: no available servers\n"); + break; + } + continue; + } - rad_req_wait(req, conf_timeout); + for(i = 0; i < conf_max_try; i++) { + __sync_add_and_fetch(&stat_auth_sent, 1); + gettimeofday(&tv, NULL); + if (rad_req_send(req, conf_verbose)) + goto out; - if (req->reply) { - if (req->reply->id != req->pack->id) { - __sync_add_and_fetch(&stat_auth_lost, 1); - stat_accm_add(stat_auth_lost_1m, 1); - stat_accm_add(stat_auth_lost_5m, 1); - rad_packet_free(req->reply); - req->reply = NULL; - } else { + timeout = conf_timeout; + + while (timeout > 0) { + + rad_req_wait(req, timeout); + + if (req->reply) { + if (req->reply->id != req->pack->id) { + rad_packet_free(req->reply); + req->reply = NULL; + gettimeofday(&tv2, NULL); + timeout = conf_timeout - ((tv2.tv_sec - tv.tv_sec) * 1000 + (tv2.tv_usec - tv.tv_usec) / 1000); + } else + break; + } else + break; + } + + if (req->reply) { dt = (req->reply->tv.tv_sec - tv.tv_sec) * 1000 + (req->reply->tv.tv_usec - tv.tv_usec) / 1000; stat_accm_add(stat_auth_query_1m, dt); stat_accm_add(stat_auth_query_5m, dt); break; + } else { + __sync_add_and_fetch(&stat_auth_lost, 1); + stat_accm_add(stat_auth_lost_1m, 1); + stat_accm_add(stat_auth_lost_5m, 1); } - } else - __sync_add_and_fetch(&stat_auth_lost, 1); - stat_accm_add(stat_auth_lost_1m, 1); - stat_accm_add(stat_auth_lost_5m, 1); - } + } + + rad_server_req_exit(req); - if (!req->reply) - log_ppp_warn("radius:auth: no response\n"); - else if (req->reply->code == CODE_ACCESS_ACCEPT) { - if (rad_proc_attrs(req)) - return PWDB_DENIED; - return PWDB_SUCCESS; + if (!req->reply) { + rad_server_fail(req->serv); + if (rad_server_realloc(req, 0)) { + log_ppp_warn("radius: no available servers\n"); + break; + } + } else { + if (req->reply->code == CODE_ACCESS_ACCEPT) { + if (rad_proc_attrs(req)) + return PWDB_DENIED; + return PWDB_SUCCESS; + } else + break; + } } out: @@ -200,7 +229,7 @@ int rad_auth_pap(struct radius_pd_t *rpd, const char *username, va_list args) if (!req) return PWDB_DENIED; - epasswd = encrypt_password(passwd, conf_auth_secret, req->RA, &epasswd_len); + epasswd = encrypt_password(passwd, req->serv->auth_secret, req->RA, &epasswd_len); if (!epasswd) goto out; diff --git a/accel-pppd/radius/radius.c b/accel-pppd/radius/radius.c index 5663af99..a6c5b93d 100644 --- a/accel-pppd/radius/radius.c +++ b/accel-pppd/radius/radius.c @@ -34,14 +34,6 @@ in_addr_t conf_bind; int conf_verbose; int conf_interim_verbose; -in_addr_t conf_auth_server; -int conf_auth_server_port = 1812; -char *conf_auth_secret; - -in_addr_t conf_acct_server; -int conf_acct_server_port = 1813; -char *conf_acct_secret; - in_addr_t conf_dm_coa_server; int conf_dm_coa_port = 3799; char *conf_dm_coa_secret; diff --git a/accel-pppd/radius/radius_p.h b/accel-pppd/radius/radius_p.h index 929fe8e6..6ee130f1 100644 --- a/accel-pppd/radius/radius_p.h +++ b/accel-pppd/radius/radius_p.h @@ -10,6 +10,8 @@ #include "ppp.h" #include "ipdb.h" +struct rad_server_t; + struct radius_pd_t { struct list_head entry; @@ -46,16 +48,37 @@ struct radius_pd_t struct rad_req_t { + struct list_head entry; struct triton_context_t ctx; struct triton_md_handler_t hnd; struct triton_timer_t timeout; uint8_t RA[16]; struct rad_packet_t *pack; struct rad_packet_t *reply; + + struct radius_pd_t *rpd; + struct rad_server_t *serv; + in_addr_t server_addr; int server_port; +}; - struct radius_pd_t *rpd; +struct rad_server_t +{ + struct list_head entry; + in_addr_t auth_addr; + int auth_port; + char *auth_secret; + in_addr_t acct_addr; + int acct_port; + char *acct_secret; + int max_req_cnt; + int req_cnt; + struct list_head req_queue; + int client_cnt; + time_t fail_time; + int conf_fail_time; + pthread_mutex_t lock; }; @@ -70,11 +93,6 @@ extern in_addr_t conf_nas_ip_address; extern in_addr_t conf_bind; extern in_addr_t conf_gw_ip_address; extern in_addr_t conf_auth_server; -extern char *conf_auth_secret; -extern int conf_auth_server_port; -extern in_addr_t conf_acct_server; -extern char *conf_acct_secret; -extern int conf_acct_server_port; extern char *conf_dm_coa_secret; extern int conf_sid_in_auth; extern int conf_require_nas_ident; @@ -122,6 +140,13 @@ int rad_packet_send(struct rad_packet_t *pck, int fd, struct sockaddr_in *addr); void dm_coa_cancel(struct radius_pd_t *pd); +struct rad_server_t *rad_server_get(); +void rad_server_put(struct rad_server_t *); +int rad_server_req_enter(struct rad_req_t *); +void rad_server_req_exit(struct rad_req_t *); +int rad_server_realloc(struct rad_req_t *, int); +void rad_server_fail(struct rad_server_t *); + struct stat_accm_t; struct stat_accm_t *stat_accm_create(unsigned int time); void stat_accm_add(struct stat_accm_t *, unsigned int); diff --git a/accel-pppd/radius/req.c b/accel-pppd/radius/req.c index 7b865038..a5861112 100644 --- a/accel-pppd/radius/req.c +++ b/accel-pppd/radius/req.c @@ -32,8 +32,12 @@ struct rad_req_t *rad_req_alloc(struct radius_pd_t *rpd, int code, const char *u req->hnd.fd = -1; req->ctx.before_switch = log_switch; - req->server_addr = conf_auth_server; - req->server_port = conf_auth_server_port; + req->serv = rad_server_get(); + if (!req->serv) + goto out_err; + + req->server_addr = req->serv->auth_addr; + req->server_port = req->serv->auth_port; while (1) { if (read(urandom_fd, req->RA, 16) != 16) { @@ -97,8 +101,8 @@ out_err: int rad_req_acct_fill(struct rad_req_t *req) { - req->server_addr = conf_acct_server; - req->server_port = conf_acct_server_port; + req->server_addr = req->serv->acct_addr; + req->server_port = req->serv->acct_port; memset(req->RA, 0, sizeof(req->RA)); @@ -132,6 +136,8 @@ int rad_req_acct_fill(struct rad_req_t *req) void rad_req_free(struct rad_req_t *req) { + if (req->serv) + rad_server_put(req->serv); if (req->hnd.fd >= 0 ) close(req->hnd.fd); if (req->pack) |