diff options
author | Kozlov Dmitry <xeb@mail.ru> | 2012-07-19 22:20:02 +0400 |
---|---|---|
committer | Kozlov Dmitry <xeb@mail.ru> | 2012-07-19 22:20:02 +0400 |
commit | 3c343b7902755f6110d89c9a87bf8c08ed30c705 (patch) | |
tree | a32dc70bf5660e1b79e2ba0b5f01f02e7c095806 | |
parent | 6fe9ea35fb1484c37aa5f7eb9b023780f986f1e8 (diff) | |
download | accel-ppp-xebd-3c343b7902755f6110d89c9a87bf8c08ed30c705.tar.gz accel-ppp-xebd-3c343b7902755f6110d89c9a87bf8c08ed30c705.zip |
radius: implemented Idle-Timeout
-rw-r--r-- | accel-pppd/include/ap_session.h | 1 | ||||
-rw-r--r-- | accel-pppd/radius/acct.c | 60 | ||||
-rw-r--r-- | accel-pppd/radius/backup.c | 8 | ||||
-rw-r--r-- | accel-pppd/radius/radius.c | 31 | ||||
-rw-r--r-- | accel-pppd/radius/radius_p.h | 6 |
5 files changed, 83 insertions, 23 deletions
diff --git a/accel-pppd/include/ap_session.h b/accel-pppd/include/ap_session.h index ac0704b..cc7153c 100644 --- a/accel-pppd/include/ap_session.h +++ b/accel-pppd/include/ap_session.h @@ -18,6 +18,7 @@ #define TERM_NAS_REBOOT 7 #define TERM_AUTH_ERROR 8 #define TERM_LOST_CARRIER 9 +#define TERM_IDLE_TIMEOUT 10 #define CTRL_TYPE_PPTP 1 #define CTRL_TYPE_L2TP 2 diff --git a/accel-pppd/radius/acct.c b/accel-pppd/radius/acct.c index 87ffd83..ab71c45 100644 --- a/accel-pppd/radius/acct.c +++ b/accel-pppd/radius/acct.c @@ -21,6 +21,33 @@ #define STAT_UPDATE_INTERVAL (10 * 60 * 1000) #define INTERIM_SAFE_TIME 10 +int rad_read_stats(struct radius_pd_t *rpd, struct rtnl_link_stats *stats) +{ + int r; + + if (iplink_get_stats(rpd->ses->ifindex, stats)) { + log_ppp_warn("radius: failed to get interface statistics\n"); + return -1; + } + + stats->rx_packets -= rpd->acct_rx_packets_i; + stats->tx_packets -= rpd->acct_tx_packets_i; + stats->rx_bytes -= rpd->acct_rx_bytes_i; + stats->tx_bytes -= rpd->acct_tx_bytes_i; + + r = stats->rx_bytes != rpd->acct_rx_bytes || stats->tx_bytes < rpd->acct_tx_bytes; + + if (stats->rx_bytes < rpd->acct_rx_bytes) + rpd->acct_input_gigawords++; + rpd->acct_rx_bytes = stats->rx_packets; + + if (stats->tx_bytes < rpd->acct_tx_bytes) + rpd->acct_output_gigawords++; + rpd->acct_tx_bytes = stats->tx_bytes; + + return r; +} + static int req_set_RA(struct rad_req_t *req, const char *secret) { MD5_CTX ctx; @@ -48,31 +75,15 @@ static void req_set_stat(struct rad_req_t *req, struct ap_session *ses) else time(&stop_time); - if (iplink_get_stats(ses->ifindex, &stats)) { - log_ppp_warn("radius: failed to get interface statistics\n"); - return; + if (rad_read_stats(rpd, &stats) > 0) { + rad_packet_change_int(req->pack, NULL, "Acct-Input-Octets", stats.rx_bytes); + rad_packet_change_int(req->pack, NULL, "Acct-Output-Octets", stats.tx_bytes); + rad_packet_change_int(req->pack, NULL, "Acct-Input-Packets", stats.rx_packets); + rad_packet_change_int(req->pack, NULL, "Acct-Output-Packets", stats.tx_packets); + rad_packet_change_int(req->pack, NULL, "Acct-Input-Gigawords", rpd->acct_input_gigawords); + rad_packet_change_int(req->pack, NULL, "Acct-Output-Gigawords", rpd->acct_output_gigawords); } - stats.rx_packets -= rpd->acct_rx_packets_i; - stats.tx_packets -= rpd->acct_tx_packets_i; - stats.rx_bytes -= rpd->acct_rx_bytes_i; - stats.tx_bytes -= rpd->acct_tx_bytes_i; - - if (stats.rx_bytes < rpd->acct_rx_bytes) - req->rpd->acct_input_gigawords++; - req->rpd->acct_rx_bytes = stats.rx_packets; - - if (stats.tx_bytes < rpd->acct_tx_bytes) - req->rpd->acct_output_gigawords++; - req->rpd->acct_tx_bytes = stats.tx_bytes; - - rad_packet_change_int(req->pack, NULL, "Acct-Input-Octets", stats.rx_bytes); - rad_packet_change_int(req->pack, NULL, "Acct-Output-Octets", stats.tx_bytes); - rad_packet_change_int(req->pack, NULL, "Acct-Input-Packets", stats.rx_packets); - rad_packet_change_int(req->pack, NULL, "Acct-Output-Packets", stats.tx_packets); - rad_packet_change_int(req->pack, NULL, "Acct-Input-Gigawords", rpd->acct_input_gigawords); - rad_packet_change_int(req->pack, NULL, "Acct-Output-Gigawords", rpd->acct_output_gigawords); - rad_packet_change_int(req->pack, NULL, "Acct-Session-Time", stop_time - ses->start_time); } @@ -416,6 +427,9 @@ void rad_acct_stop(struct radius_pd_t *rpd) case TERM_LOST_CARRIER: rad_packet_add_val(rpd->acct_req->pack, NULL, "Acct-Terminate-Cause", "Lost-Carrier"); break; + case TERM_IDLE_TIMEOUT: + rad_packet_add_val(rpd->acct_req->pack, NULL, "Acct-Terminate-Cause", "Idle-Timeout"); + break; } rad_packet_change_val(rpd->acct_req->pack, NULL, "Acct-Status-Type", "Stop"); req_set_stat(rpd->acct_req, rpd->ses); diff --git a/accel-pppd/radius/backup.c b/accel-pppd/radius/backup.c index 4c40ec6..a44a760 100644 --- a/accel-pppd/radius/backup.c +++ b/accel-pppd/radius/backup.c @@ -21,6 +21,7 @@ #define RAD_TAG_TERMINATION_ACTION 8 #define RAD_TAG_ACCT_SERVER_ADDR 9 #define RAD_TAG_ACCT_SERVER_PORT 10 +#define RAD_TAG_IDLE_TIMEOUT 11 #define add_tag(id, data, size) if (!backup_add_tag(m, id, 0, data, size)) return -1; @@ -30,6 +31,7 @@ static int session_save(struct ap_session *ses, struct backup_mod *m) { struct radius_pd_t *rpd = find_pd(ses); uint64_t session_timeout = ses->start_time + rpd->session_timeout.expire_tv.tv_sec; + uint32_t idle_timeout = rpd->idle_timeout.period / 1000; if (!rpd) return 0; @@ -42,6 +44,9 @@ static int session_save(struct ap_session *ses, struct backup_mod *m) if (rpd->session_timeout.tpd) add_tag(RAD_TAG_SESSION_TIMEOUT, &session_timeout, 8); + if (rpd->idle_timeout.tpd) + add_tag(RAD_TAG_IDLE_TIMEOUT, &idle_timeout, 4); + if (ses->ipv4 == &rpd->ipv4_addr) add_tag(RAD_TAG_IPV4_ADDR, NULL, 0); @@ -113,6 +118,9 @@ void radius_restore_session(struct ap_session *ses, struct radius_pd_t *rpd) case RAD_TAG_SESSION_TIMEOUT: rpd->session_timeout.expire_tv.tv_sec = *(uint64_t *)tag->data - ses->start_time; break; + case RAD_TAG_IDLE_TIMEOUT: + rpd->idle_timeout.period = (*(uint32_t *)tag->data) * 1000; + break; case RAD_TAG_IPV4_ADDR: ses->ipv4 = &rpd->ipv4_addr; restore_ipv4_addr(ses); diff --git a/accel-pppd/radius/radius.c b/accel-pppd/radius/radius.c index 048f736..f10b156 100644 --- a/accel-pppd/radius/radius.c +++ b/accel-pppd/radius/radius.c @@ -4,6 +4,7 @@ #include <string.h> #include <unistd.h> #include <arpa/inet.h> +#include <linux/if_link.h> #include "mempool.h" #include "events.h" @@ -94,6 +95,9 @@ int rad_proc_attrs(struct rad_req_t *req) case Session_Timeout: req->rpd->session_timeout.expire_tv.tv_sec = attr->val.integer; break; + case Idle_Timeout: + req->rpd->idle_timeout.period = attr->val.integer * 1000; + break; case Class: if (!req->rpd->attr_class) req->rpd->attr_class = _malloc(attr->len); @@ -227,6 +231,25 @@ static void session_timeout(struct triton_timer_t *t) ap_session_terminate(rpd->ses, TERM_SESSION_TIMEOUT, 0); } +static void idle_timeout(struct triton_timer_t *t) +{ + struct radius_pd_t *rpd = container_of(t, typeof(*rpd), idle_timeout); + struct rtnl_link_stats stats; + + if (rpd->ses->stop_time) + return; + + rad_read_stats(rpd, &stats); + + if (stats.rx_packets == rpd->acct_rx_packets && stats.tx_packets == rpd->acct_tx_packets) { + log_ppp_msg("radius: session timed out\n"); + ap_session_terminate(rpd->ses, TERM_IDLE_TIMEOUT, 0); + } else { + rpd->acct_rx_packets = stats.rx_packets; + rpd->acct_tx_packets = stats.tx_packets; + } +} + static void ses_starting(struct ap_session *ses) { struct radius_pd_t *rpd = mempool_alloc(rpd_pool); @@ -271,6 +294,11 @@ static void ses_acct_start(struct ap_session *ses) rpd->session_timeout.expire = session_timeout; triton_timer_add(ses->ctrl->ctx, &rpd->session_timeout, 0); } + + if (rpd->idle_timeout.period) { + rpd->idle_timeout.expire = idle_timeout; + triton_timer_add(ses->ctrl->ctx, &rpd->idle_timeout, 0); + } } static void ses_finishing(struct ap_session *ses) { @@ -303,6 +331,9 @@ static void ses_finished(struct ap_session *ses) if (rpd->session_timeout.tpd) triton_timer_del(&rpd->session_timeout); + + if (rpd->idle_timeout.tpd) + triton_timer_del(&rpd->idle_timeout); if (rpd->attr_class) _free(rpd->attr_class); diff --git a/accel-pppd/radius/radius_p.h b/accel-pppd/radius/radius_p.h index 383be7d..8a4d27a 100644 --- a/accel-pppd/radius/radius_p.h +++ b/accel-pppd/radius/radius_p.h @@ -27,6 +27,8 @@ struct radius_pd_t uint32_t acct_rx_bytes; uint32_t acct_tx_bytes; + uint32_t acct_rx_packets; + uint32_t acct_tx_packets; uint32_t acct_input_gigawords; uint32_t acct_output_gigawords; uint32_t acct_rx_packets_i; @@ -35,6 +37,7 @@ struct radius_pd_t uint32_t acct_tx_bytes_i; struct triton_timer_t session_timeout; + struct triton_timer_t idle_timeout; struct rad_packet_t *dm_coa_req; struct sockaddr_in dm_coa_addr; @@ -187,6 +190,9 @@ void rad_server_reply(struct rad_server_t *); void radius_restore_session(struct ap_session *ses, struct radius_pd_t *rpd); +struct rtnl_link_stats; +int rad_read_stats(struct radius_pd_t *rpd, struct rtnl_link_stats *stats); + struct stat_accm_t; struct stat_accm_t *stat_accm_create(unsigned int time); void stat_accm_free(struct stat_accm_t *); |