summaryrefslogtreecommitdiff
path: root/accel-pppd/radius/backup.c
blob: 93ab3eb03d8a1e9fc906d4db111c1ff46ba5b007 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#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 RAD_TAG_IDLE_TIMEOUT               11


#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;
	uint32_t idle_timeout = rpd->idle_timeout.period / 1000;

	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 (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);

	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_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);
				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);