summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKozlov Dmitry <xeb@mail.ru>2012-07-19 22:20:02 +0400
committerKozlov Dmitry <xeb@mail.ru>2012-07-19 22:20:02 +0400
commit3c343b7902755f6110d89c9a87bf8c08ed30c705 (patch)
treea32dc70bf5660e1b79e2ba0b5f01f02e7c095806
parent6fe9ea35fb1484c37aa5f7eb9b023780f986f1e8 (diff)
downloadaccel-ppp-xebd-3c343b7902755f6110d89c9a87bf8c08ed30c705.tar.gz
accel-ppp-xebd-3c343b7902755f6110d89c9a87bf8c08ed30c705.zip
radius: implemented Idle-Timeout
-rw-r--r--accel-pppd/include/ap_session.h1
-rw-r--r--accel-pppd/radius/acct.c60
-rw-r--r--accel-pppd/radius/backup.c8
-rw-r--r--accel-pppd/radius/radius.c31
-rw-r--r--accel-pppd/radius/radius_p.h6
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 *);