diff options
author | Kozlov Dmitry <xeb@mail.ru> | 2012-07-10 18:58:53 +0400 |
---|---|---|
committer | Kozlov Dmitry <xeb@mail.ru> | 2012-07-10 18:58:53 +0400 |
commit | 80c32d237e01b1c05663ccfa34003d2f49aa7eee (patch) | |
tree | a49da21b5219e4bc89d9794918f054f3620cb140 /accel-pppd/radius/backup.c | |
parent | 64b5b693764c4f36870fd988ccbb53bcb188e74d (diff) | |
download | accel-ppp-80c32d237e01b1c05663ccfa34003d2f49aa7eee.tar.gz accel-ppp-80c32d237e01b1c05663ccfa34003d2f49aa7eee.zip |
initial session backup implementation
Diffstat (limited to 'accel-pppd/radius/backup.c')
-rw-r--r-- | accel-pppd/radius/backup.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/accel-pppd/radius/backup.c b/accel-pppd/radius/backup.c new file mode 100644 index 0000000..4c40ec6 --- /dev/null +++ b/accel-pppd/radius/backup.c @@ -0,0 +1,163 @@ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <netinet/in.h> +#include <net/ethernet.h> + +#include "log.h" +#include "memdebug.h" + +#include "backup.h" +#include "ap_session_backup.h" +#include "radius_p.h" + +#define RAD_TAG_INTERIM_INTERVAL 1 +#define RAD_TAG_SESSION_TIMEOUT 2 +#define RAD_TAG_IPV4_ADDR 3 +#define RAD_TAG_IPV6_ADDR 4 +#define RAD_TAG_IPV6_DP 5 +#define RAD_TAG_ATTR_CLASS 6 +#define RAD_TAG_ATTR_STATE 7 +#define RAD_TAG_TERMINATION_ACTION 8 +#define RAD_TAG_ACCT_SERVER_ADDR 9 +#define RAD_TAG_ACCT_SERVER_PORT 10 + + +#define add_tag(id, data, size) if (!backup_add_tag(m, id, 0, data, size)) return -1; +#define add_tag_int(id, data, size) if (!backup_add_tag(m, id, 1, data, size)) return -1; + +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; + + if (!rpd) + return 0; + + if (!rpd->authenticated) + return -2; + + add_tag(RAD_TAG_INTERIM_INTERVAL, &rpd->acct_interim_interval, 4); + + if (rpd->session_timeout.tpd) + add_tag(RAD_TAG_SESSION_TIMEOUT, &session_timeout, 8); + + if (ses->ipv4 == &rpd->ipv4_addr) + add_tag(RAD_TAG_IPV4_ADDR, NULL, 0); + + if (ses->ipv6 == &rpd->ipv6_addr) + add_tag(RAD_TAG_IPV6_ADDR, NULL, 0); + + /*if (rpd->ipv6_pd_assigned) { + + }*/ + + if (rpd->attr_class) + add_tag(RAD_TAG_ATTR_CLASS, rpd->attr_class, rpd->attr_class_len); + + if (rpd->attr_state) + add_tag(RAD_TAG_ATTR_CLASS, rpd->attr_state, rpd->attr_state_len); + + add_tag(RAD_TAG_TERMINATION_ACTION, &rpd->termination_action, 4); + + if (rpd->acct_req) { + add_tag(RAD_TAG_ACCT_SERVER_ADDR, &rpd->acct_req->server_addr, 4); + add_tag(RAD_TAG_ACCT_SERVER_PORT, &rpd->acct_req->server_port, 2); + } + + return 0; +} + +static int session_restore(struct ap_session *ses, struct backup_mod *m) +{ + return 0; +} + +static void restore_ipv4_addr(struct ap_session *ses) +{ + struct backup_mod *m = backup_find_mod(ses->backup, MODID_COMMON); + struct backup_tag *tag; + + list_for_each_entry(tag, &m->tag_list, entry) { + switch (tag->id) { + case SES_TAG_IPV4_ADDR: + ses->ipv4->addr = *(in_addr_t *)tag->data; + break; + case SES_TAG_IPV4_PEER_ADDR: + ses->ipv4->peer_addr = *(in_addr_t *)tag->data; + break; + } + } +} + +static void restore_ipv6_addr(struct ap_session *ses) +{ + +} + +void radius_restore_session(struct ap_session *ses, struct radius_pd_t *rpd) +{ + struct backup_mod *m = backup_find_mod(ses->backup, MODID_RADIUS); + struct backup_tag *tag; + in_addr_t acct_addr = 0; + int acct_port; + + if (!m) + return; + + list_for_each_entry(tag, &m->tag_list, entry) { + switch (tag->id) { + case RAD_TAG_INTERIM_INTERVAL: + rpd->acct_interim_interval = *(uint32_t *)tag->data; + break; + case RAD_TAG_SESSION_TIMEOUT: + rpd->session_timeout.expire_tv.tv_sec = *(uint64_t *)tag->data - ses->start_time; + break; + case RAD_TAG_IPV4_ADDR: + ses->ipv4 = &rpd->ipv4_addr; + restore_ipv4_addr(ses); + break; + case RAD_TAG_IPV6_ADDR: + restore_ipv6_addr(ses); + break; + case RAD_TAG_ATTR_CLASS: + rpd->attr_class = _malloc(tag->size); + memcpy(rpd->attr_class, tag->data, tag->size); + rpd->attr_class_len = tag->size; + break; + case RAD_TAG_ATTR_STATE: + rpd->attr_state = _malloc(tag->size); + memcpy(rpd->attr_state, tag->data, tag->size); + rpd->attr_state_len = tag->size; + break; + case RAD_TAG_TERMINATION_ACTION: + rpd->termination_action = *(uint32_t *)tag->data; + break; + case RAD_TAG_ACCT_SERVER_ADDR: + acct_addr = *(in_addr_t *)tag->data; + break; + case RAD_TAG_ACCT_SERVER_PORT: + acct_port = *(uint16_t *)tag->data; + break; + } + } + + if (acct_addr) + rpd->acct_req = rad_req_alloc2(rpd, CODE_ACCOUNTING_REQUEST, rpd->ses->username, acct_addr, acct_port); + + rpd->authenticated = 1; +} + +static struct backup_module mod = { + .id = MODID_RADIUS, + .save = session_save, + .restore = session_restore, +}; + +static void init(void) +{ + backup_register_module(&mod); +} + +DEFINE_INIT(100, init); + |