diff options
author | Kozlov Dmitry <xeb@mail.ru> | 2011-12-27 14:59:07 +0400 |
---|---|---|
committer | Kozlov Dmitry <xeb@mail.ru> | 2011-12-27 14:59:07 +0400 |
commit | b2f9d7066553be2b74b048fcf65417eaadb44c60 (patch) | |
tree | 1a53dfc7e5046bf1e7885481fe5683ea605b59f6 | |
parent | 89d62818266b6b7f6e0f99542b0fb795f0768107 (diff) | |
download | accel-ppp-b2f9d7066553be2b74b048fcf65417eaadb44c60.tar.gz accel-ppp-b2f9d7066553be2b74b048fcf65417eaadb44c60.zip |
radius: implemented simultaneous requests limiting
-rw-r--r-- | accel-pppd/accel-ppp.conf | 3 | ||||
-rw-r--r-- | accel-pppd/accel-ppp.conf.5 | 11 | ||||
-rw-r--r-- | accel-pppd/radius/acct.c | 20 | ||||
-rw-r--r-- | accel-pppd/radius/auth.c | 10 | ||||
-rw-r--r-- | accel-pppd/radius/radius.c | 5 | ||||
-rw-r--r-- | accel-pppd/radius/radius_p.h | 10 | ||||
-rw-r--r-- | accel-pppd/radius/req.c | 3 | ||||
-rw-r--r-- | accel-pppd/radius/serv.c | 192 |
8 files changed, 175 insertions, 79 deletions
diff --git a/accel-pppd/accel-ppp.conf b/accel-pppd/accel-ppp.conf index 7219ba3..b6427c2 100644 --- a/accel-pppd/accel-ppp.conf +++ b/accel-pppd/accel-ppp.conf @@ -85,7 +85,8 @@ nas-ip-address=127.0.0.1 gw-ip-address=192.168.100.1 #auth-server=127.0.0.1:1812,testing123 (obsolete) #acct-server=127.0.0.1:1813,testing123 (obsolete) -server=127.0.0.1,testing123 +#server=127.0.0.1,testing123 (obsolete) +server=127.0.0.1,testing123,auth-port=1812,acct-port=1813,req-limit=0,fail-time=0 dae-server=127.0.0.1:3799,testing123 verbose=1 #timeout=3 diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5 index 955f167..4274965 100644 --- a/accel-pppd/accel-ppp.conf.5 +++ b/accel-pppd/accel-ppp.conf.5 @@ -311,8 +311,15 @@ Specifies IP address, port and secret of authentication RADIUS server. (obsolete .BI "acct-server=" x.x.x.x:port,secret Specifies IP address, port and secret of accounting RADIUS server. (obsolete) .TP -.BI "server=" address,secret[,auth-port[,acct-port]] -Specifies IP address, ports and secret of RADIUS server. +.BI "server=" address,secret[,auth-port=1812][,acct-port=1813][,req-limit=0][,fail-time=0] +Specifies IP address, secret, ports of RADIUS server. +.br +.B req-limit +- number of simultaneous requests to server (0 - unlimited). +.br +.B fail-time +- if server doesn't responds mark it as unavailable for this time (sec). +.br If you want to specify only authentication or accounting server then set auth-port/acct-port to zero. You may specify multiple radius servers. .TP diff --git a/accel-pppd/radius/acct.c b/accel-pppd/radius/acct.c index e627474..76ad329 100644 --- a/accel-pppd/radius/acct.c +++ b/accel-pppd/radius/acct.c @@ -185,7 +185,7 @@ 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, req->serv->acct_secret); + req_set_RA(req, req->serv->secret); } __rad_req_send(req); @@ -214,7 +214,7 @@ 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, rpd->acct_req->serv->acct_secret); + req_set_RA(rpd->acct_req, rpd->acct_req->serv->secret); __rad_req_send(rpd->acct_req); @@ -254,7 +254,7 @@ int rad_acct_start(struct radius_pd_t *rpd) time(&rpd->acct_timestamp); - if (req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret)) + if (req_set_RA(rpd->acct_req, rpd->acct_req->serv->secret)) goto out_err; while (1) { @@ -264,7 +264,7 @@ int rad_acct_start(struct radius_pd_t *rpd) 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)) + if (req_set_RA(rpd->acct_req, rpd->acct_req->serv->secret)) goto out_err; continue; } @@ -273,7 +273,7 @@ int rad_acct_start(struct radius_pd_t *rpd) 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)) + if (req_set_RA(rpd->acct_req, rpd->acct_req->serv->secret)) goto out_err; } @@ -319,7 +319,7 @@ int rad_acct_start(struct radius_pd_t *rpd) 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)) + if (req_set_RA(rpd->acct_req, rpd->acct_req->serv->secret)) goto out_err; } @@ -393,7 +393,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, rpd->acct_req->serv->acct_secret); + req_set_RA(rpd->acct_req, rpd->acct_req->serv->secret); /// !!! rad_req_add_val(rpd->acct_req, "Acct-Terminate-Cause", ""); if (rpd->acct_req->reply) { @@ -410,7 +410,7 @@ void rad_acct_stop(struct radius_pd_t *rpd) log_ppp_warn("radius:acct_stop: no servers available\n"); break; } - req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret); + req_set_RA(rpd->acct_req, rpd->acct_req->serv->secret); continue; } @@ -419,7 +419,7 @@ void rad_acct_stop(struct radius_pd_t *rpd) 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)) + if (req_set_RA(rpd->acct_req, rpd->acct_req->serv->secret)) break; } if (rad_req_send(rpd->acct_req, conf_verbose)) @@ -458,7 +458,7 @@ void rad_acct_stop(struct radius_pd_t *rpd) log_ppp_warn("radius:acct_stop: no servers available\n"); break; } - req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret); + req_set_RA(rpd->acct_req, rpd->acct_req->serv->secret); } rad_req_free(rpd->acct_req); diff --git a/accel-pppd/radius/auth.c b/accel-pppd/radius/auth.c index becddf6..3e5d281 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, req->serv->auth_secret, strlen(req->serv->auth_secret)); + MD5_Update(&md5_ctx, req->serv->secret, strlen(req->serv->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, req->serv->auth_secret, strlen(req->serv->auth_secret)); + MD5_Update(&md5_ctx, req->serv->secret, strlen(req->serv->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, req->serv->auth_secret, strlen(req->serv->auth_secret)); + MD5_Update(&md5_ctx, req->serv->secret, strlen(req->serv->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, req->serv->auth_secret, strlen(req->serv->auth_secret)); + MD5_Update(&md5_ctx, req->serv->secret, strlen(req->serv->secret)); MD5_Update(&md5_ctx, attr->val.octets + 2, 16); MD5_Final(md5, &md5_ctx); @@ -229,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, req->serv->auth_secret, req->RA, &epasswd_len); + epasswd = encrypt_password(passwd, req->serv->secret, req->RA, &epasswd_len); if (!epasswd) goto out; diff --git a/accel-pppd/radius/radius.c b/accel-pppd/radius/radius.c index 370572a..c24522d 100644 --- a/accel-pppd/radius/radius.c +++ b/accel-pppd/radius/radius.c @@ -43,6 +43,7 @@ int conf_acct_interim_interval; int conf_accounting; int conf_fail_time; +int conf_req_limit; static LIST_HEAD(sessions); static pthread_rwlock_t sessions_lock = PTHREAD_RWLOCK_INITIALIZER; @@ -535,6 +536,10 @@ static int load_config(void) if (opt) conf_fail_time = atoi(opt); + opt = conf_get_opt("radius", "req-limit"); + if (opt) + conf_fail_time = atoi(opt); + return 0; } diff --git a/accel-pppd/radius/radius_p.h b/accel-pppd/radius/radius_p.h index e038aa8..7422bbf 100644 --- a/accel-pppd/radius/radius_p.h +++ b/accel-pppd/radius/radius_p.h @@ -70,14 +70,13 @@ struct rad_server_t { struct list_head entry; int id; - in_addr_t auth_addr; + in_addr_t addr; + char *secret; int auth_port; - char *auth_secret; - in_addr_t acct_addr; int acct_port; - char *acct_secret; - int max_req_cnt; + int req_limit; int req_cnt; + int queue_cnt; struct list_head req_queue; int client_cnt[2]; time_t fail_time; @@ -133,6 +132,7 @@ extern int conf_dm_coa_port; extern int conf_acct_interim_interval; extern int conf_accounting; extern int conf_fail_time; +extern int conf_req_limit; int rad_check_nas_pack(struct rad_packet_t *pack); struct radius_pd_t *rad_find_session(const char *sessionid, const char *username, int port_id, in_addr_t ipaddr, const char *csid); diff --git a/accel-pppd/radius/req.c b/accel-pppd/radius/req.c index 387cdd1..ed69846 100644 --- a/accel-pppd/radius/req.c +++ b/accel-pppd/radius/req.c @@ -40,7 +40,7 @@ struct rad_req_t *rad_req_alloc(struct radius_pd_t *rpd, int code, const char *u if (!req->serv) goto out_err; - req->server_addr = req->serv->auth_addr; + req->server_addr = req->serv->addr; req->server_port = req->serv->auth_port; while (1) { @@ -111,7 +111,6 @@ int rad_req_acct_fill(struct rad_req_t *req) { struct ipv6db_addr_t *a; - req->server_addr = req->serv->acct_addr; req->server_port = req->serv->acct_port; memset(req->RA, 0, sizeof(req->RA)); diff --git a/accel-pppd/radius/serv.c b/accel-pppd/radius/serv.c index 6c28324..30219f7 100644 --- a/accel-pppd/radius/serv.c +++ b/accel-pppd/radius/serv.c @@ -38,9 +38,9 @@ static struct rad_server_t *__rad_server_get(int type, struct rad_server_t *excl if (s->fail_time && ts.tv_sec < s->fail_time) continue; - if (type == RAD_SERV_AUTH && !s->auth_addr) + if (type == RAD_SERV_AUTH && !s->auth_port) continue; - else if (type == RAD_SERV_ACCT && !s->acct_addr) + else if (type == RAD_SERV_ACCT && !s->acct_port) continue; if (!s0) { @@ -85,7 +85,7 @@ int rad_server_req_enter(struct rad_req_t *req) if (ts.tv_sec < req->serv->fail_time) return -1; - if (!req->serv->max_req_cnt) + if (!req->serv->req_limit) return 0; pthread_mutex_lock(&req->serv->lock); @@ -95,13 +95,15 @@ int rad_server_req_enter(struct rad_req_t *req) return -1; } - if (req->serv->req_cnt >= req->serv->max_req_cnt) { + if (req->serv->req_cnt >= req->serv->req_limit) { list_add_tail(&req->entry, &req->serv->req_queue); + req->serv->queue_cnt++; pthread_mutex_unlock(&req->serv->lock); triton_context_schedule(); pthread_mutex_lock(&req->serv->lock); + req->serv->queue_cnt--; if (ts.tv_sec < req->serv->fail_time || req->serv->need_free) { pthread_mutex_unlock(&req->serv->lock); return -1; @@ -118,12 +120,12 @@ void rad_server_req_exit(struct rad_req_t *req) { struct rad_req_t *r = NULL; - if (!req->serv->max_req_cnt) + if (!req->serv->req_limit) return; pthread_mutex_lock(&req->serv->lock); req->serv->req_cnt--; - if (req->serv->req_cnt < req->serv->max_req_cnt && !list_empty(&req->serv->req_queue)) { + if (req->serv->req_cnt < req->serv->req_limit && !list_empty(&req->serv->req_queue)) { r = list_entry(req->serv->req_queue.next, typeof(*r), entry); list_del(&r->entry); } @@ -152,13 +154,11 @@ int rad_server_realloc(struct rad_req_t *req) req->hnd.fd = -1; } - if (req->type == RAD_SERV_ACCT) { - req->server_addr = req->serv->acct_addr; + req->server_addr = req->serv->addr; + if (req->type == RAD_SERV_ACCT) req->server_port = req->serv->acct_port; - } else { - req->server_addr = req->serv->auth_addr; + else req->server_port = req->serv->auth_port; - } return 0; } @@ -207,7 +207,7 @@ static void show_stat(struct rad_server_t *s, void *client) char addr[17]; struct timespec ts; - u_inet_ntoa(s->auth_addr ? s->auth_addr : s->acct_addr, addr); + u_inet_ntoa(s->addr, addr); clock_gettime(CLOCK_MONOTONIC, &ts); cli_sendv(client, "radius(%i, %s):\r\n", s->id, addr); @@ -220,8 +220,11 @@ static void show_stat(struct rad_server_t *s, void *client) cli_sendv(client, " fail count: %lu\r\n", s->stat_fail_cnt); } + + cli_sendv(client, " request count: %lu\r\n", s->req_cnt); + cli_sendv(client, " queue length: %lu\r\n", s->queue_cnt); - if (s->auth_addr) { + if (s->auth_port) { cli_sendv(client, " auth sent: %lu\r\n", s->stat_auth_sent); cli_sendv(client, " auth lost(total/5m/1m): %lu/%lu/%lu\r\n", s->stat_auth_lost, stat_accm_get_cnt(s->stat_auth_lost_5m), stat_accm_get_cnt(s->stat_auth_lost_1m)); @@ -229,7 +232,7 @@ static void show_stat(struct rad_server_t *s, void *client) stat_accm_get_avg(s->stat_auth_query_5m), stat_accm_get_avg(s->stat_auth_query_1m)); } - if (s->acct_addr) { + if (s->acct_port) { cli_sendv(client, " acct sent: %lu\r\n", s->stat_acct_sent); cli_sendv(client, " acct lost(total/5m/1m): %lu/%lu/%lu\r\n", s->stat_acct_lost, stat_accm_get_cnt(s->stat_acct_lost_5m), stat_accm_get_cnt(s->stat_acct_lost_1m)); @@ -259,8 +262,9 @@ static void __add_server(struct rad_server_t *s) struct rad_server_t *s1; list_for_each_entry(s1, &serv_list, entry) { - if (s1->auth_addr == s->auth_addr && s1->acct_addr == s->acct_addr) { - s1->conf_fail_time = conf_fail_time; + if (s1->addr == s->addr && s1->auth_port == s->auth_port && s1->acct_port == s->acct_port) { + s1->conf_fail_time = s->conf_fail_time; + s1->req_limit = s->req_limit; s1->need_free = 0; _free(s); return; @@ -270,7 +274,6 @@ static void __add_server(struct rad_server_t *s) s->id = ++num; INIT_LIST_HEAD(&s->req_queue); pthread_mutex_init(&s->lock, NULL); - s->conf_fail_time = conf_fail_time; list_add_tail(&s->entry, &serv_list); s->stat_auth_lost_1m = stat_accm_create(60); @@ -334,12 +337,8 @@ static int parse_server_old(const char *opt, in_addr_t *addr, int *port, char ** return -1; } - p1 = _strdup(p2 + 1); - p2 = *secret; - *secret = p1; - if (p2) - _free(p2); - + *secret = _strdup(p2 + 1); + _free(str); return 0; @@ -348,37 +347,59 @@ static int parse_server_old(const char *opt, in_addr_t *addr, int *port, char ** static void add_server_old(void) { const char *opt; - struct rad_server_t *s = _malloc(sizeof(*s)); - - memset(s, 0, sizeof(*s)); + in_addr_t auth_addr = 0; + int auth_port; + char *auth_secret; + in_addr_t acct_addr = 0; + int acct_port; + char *acct_secret; + struct rad_server_t *s; opt = conf_get_opt("radius", "auth-server"); if (opt) { - if (parse_server_old(opt, &s->auth_addr, &s->auth_port, &s->auth_secret)) { + if (parse_server_old(opt, &auth_addr, &auth_port, &auth_secret)) { log_emerg("radius: failed to parse 'auth-server'\n"); - goto out; + return; } - } + } else + return; opt = conf_get_opt("radius", "acct-server"); if (opt) { - if (parse_server_old(opt, &s->acct_addr, &s->acct_port, &s->acct_secret)) { + if (parse_server_old(opt, &acct_addr, &acct_port, &acct_secret)) { log_emerg("radius: failed to parse 'acct-server'\n"); - goto out; + return; } conf_accounting = 1; } - if (s->auth_addr || s->acct_addr) { + s = _malloc(sizeof(*s)); + memset(s, 0, sizeof(*s)); + s->addr = auth_addr; + s->secret = auth_secret; + s->auth_port = auth_port; + s->conf_fail_time = conf_fail_time; + + if (auth_addr == acct_addr && !strcmp(auth_secret, acct_secret)) { + s->acct_port = acct_port; __add_server(s); return; } + + __add_server(s); -out: - _free(s); + if (acct_addr) { + s = _malloc(sizeof(*s)); + memset(s, 0, sizeof(*s)); + s->addr = acct_addr; + s->secret = acct_secret; + s->acct_port = acct_port; + s->conf_fail_time = conf_fail_time; + __add_server(s); + } } -static int parse_server(const char *_opt, struct rad_server_t *s) +static int parse_server1(const char *_opt, struct rad_server_t *s) { char *opt = _strdup(_opt); char *ptr1, *ptr2, *ptr3, *endptr; @@ -400,7 +421,7 @@ static int parse_server(const char *_opt, struct rad_server_t *s) if (ptr3) *ptr3 = 0; - s->auth_addr = s->acct_addr = inet_addr(opt); + s->addr = inet_addr(opt); if (ptr2) { if (ptr2[1]) { @@ -408,8 +429,6 @@ static int parse_server(const char *_opt, struct rad_server_t *s) if (*endptr) goto out; } - if (!s->auth_port) - s->auth_addr = 0; } else s->auth_port = 1812; @@ -419,21 +438,73 @@ static int parse_server(const char *_opt, struct rad_server_t *s) if (*endptr) goto out; } - if (!s->acct_port) - s->acct_addr = 0; } else s->acct_port = 1813; - if (!s->auth_addr && !s->acct_addr) + s->secret = _strdup(ptr1 + 1); + s->conf_fail_time = conf_fail_time; + + return 0; + +out: + _free(opt); + + return -1; +} + +static int parse_server2(const char *_opt, struct rad_server_t *s) +{ + char *opt = _strdup(_opt); + char *ptr1, *ptr2, *ptr3, *endptr; + + ptr1 = strchr(opt, ','); + if (!ptr1) goto out; + + ptr2 = strchr(ptr1 + 1, ','); + + *ptr1 = 0; + + s->addr = inet_addr(opt); + + ptr3 = strstr(ptr2, ",auth-port="); + if (ptr3) { + s->auth_port = strtol(ptr3 + 11, &endptr, 10); + if (*endptr != ',' && *endptr != 0) + goto out; + } else + s->auth_port = 1812; + + ptr3 = strstr(ptr2, ",acct-port="); + if (ptr3) { + s->acct_port = strtol(ptr3 + 11, &endptr, 10); + if (*endptr != ',' && *endptr != 0) + goto out; + } else + s->acct_port = 1813; + + ptr3 = strstr(ptr2, ",req-limit="); + if (ptr3) { + s->req_limit = strtol(ptr3 + 11, &endptr, 10); + if (*endptr != ',' && *endptr != 0) + goto out; + } else + s->req_limit = conf_req_limit; + + ptr3 = strstr(ptr2, ",fail-time="); + if (ptr3) { + s->conf_fail_time = strtol(ptr3 + 11, &endptr, 10); + if (*endptr != ',' && *endptr != 0) + goto out; + } else + s->conf_fail_time = conf_fail_time; + + if (ptr2) + *ptr2 = 0; - if (s->auth_addr) - s->auth_secret = _strdup(ptr1 + 1); + s->secret = _strdup(ptr1 + 1); - if (s->acct_addr) { - s->acct_secret = _strdup(ptr1 + 1); - conf_accounting = 1; - } + _free(opt); return 0; @@ -449,12 +520,17 @@ static void add_server(const char *opt) memset(s, 0, sizeof(*s)); - if (parse_server(opt, s)) { - log_emerg("radius: failed to parse '%s'\n", opt); - _free(s); - return; - } + if (!parse_server1(opt,s)) + goto add; + + if (!parse_server2(opt,s)) + goto add; + log_emerg("radius: failed to parse '%s'\n", opt); + _free(s); + return; + +add: __add_server(s); } @@ -490,12 +566,20 @@ static void load_config(void) __free_server(s); } } + + add_server_old(); + + conf_accounting = 0; + list_for_each_entry(s, &serv_list, entry) { + if (s->acct_port) { + conf_accounting = 1; + break; + } + } } static void init(void) { - add_server_old(); - load_config(); triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); |