Cherry-picks the code from 0.1.x branch
[rahunas] / src / rh-task-memset.c
1 /**
2  * RahuNAS task memset implementation 
3  * Author: Neutron Soutmun <neo.neutron@gmail.com>
4  * Date:   2008-09-07
5  */
6
7 #include <stdlib.h>
8 #include <string.h>
9 #include <syslog.h>
10 #include <time.h>
11 #include "rahunasd.h"
12 #include "rh-radius.h"
13 #include "rh-task.h"
14 #include "rh-ipset.h"
15
16 GList *member_get_node_by_id(RHVServer *vs, uint32_t id)
17 {
18   GList *runner = g_list_first(vs->v_map->members);
19   struct rahunas_member *member = NULL;
20
21   while (runner != NULL) {
22     member = (struct rahunas_member *) runner->data;
23
24     if (member->id == id)
25       return runner;
26
27     runner = g_list_next(runner);
28   }
29
30   return NULL;
31 }
32
33 static gint
34 idcmp(gconstpointer a, gconstpointer b)
35 {
36   struct rahunas_member *rh_a = (struct rahunas_member *) a;
37   struct rahunas_member *rh_b = (struct rahunas_member *) b;
38
39   if (rh_a != NULL && rh_b != NULL)
40     return (rh_a->id - rh_b->id);
41
42   return -1;
43 }
44
45 /* Start service task */
46 static int startservice ()
47 {
48   /* Do nothing or need to implement */
49   return 0;
50 }
51
52 /* Stop service task */
53 static int stopservice  ()
54 {
55   /* Do nothing or need to implement */
56   return 0;
57 }
58
59 /* Initialize */
60 static void init (RHVServer *vs)
61 {
62   int size;
63
64   if (vs->vserver_config->init_flag == VS_RELOAD)
65     return;
66
67   logmsg(RH_LOG_NORMAL, "[%s] Task MEMSET initialize..",
68          vs->vserver_config->vserver_name);  
69
70   vs->v_map = (struct rahunas_map *)(rh_malloc(sizeof(struct rahunas_map)));
71   if (vs->v_map == NULL) {
72     logmsg(RH_LOG_ERROR, "[%s] Could not allocate memory...",
73            vs->vserver_config->vserver_name); 
74     exit(EXIT_FAILURE);
75   }
76
77   memset(vs->v_map, 0, sizeof(struct rahunas_map));
78
79   if (get_header_from_set(vs) < 0) {
80     syslog(LOG_ERR, "Could not fetch IPSET header");
81     exit(EXIT_FAILURE);
82   }
83 }
84
85 /* Cleanup */
86 static void cleanup (RHVServer *vs)
87 {
88   GList *runner = NULL;
89   GList *deleting = NULL;
90   struct rahunas_member *member = NULL;
91
92   if (vs->vserver_config->init_flag == VS_RELOAD)
93     return;
94
95   logmsg(RH_LOG_NORMAL, "[%s] Task MEMSET cleanup..",
96          vs->vserver_config->vserver_name);  
97
98   if (vs->v_map != NULL) {
99
100     runner = g_list_first(vs->v_map->members);
101
102     while (runner != NULL) {
103       member = (struct rahunas_member *) runner->data; 
104
105       DP("Cleanup IP: %s", idtoip(vs->v_map, member->id));
106
107       rh_free_member(member);
108       deleting = runner;
109       runner = g_list_next(runner);
110
111       vs->v_map->members = g_list_delete_link(vs->v_map->members, deleting);
112     }
113
114     g_list_free(vs->v_map->members);
115
116     rh_free((void **) &vs->v_map->members);
117     rh_free((void **) &vs->v_map);
118   }
119 }
120
121 /* Start session task */
122 static int startsess (RHVServer *vs, struct task_req *req)
123 {
124   uint32_t id = req->id;
125   GList *member_node = NULL;
126   struct rahunas_member *member = NULL;
127
128   member_node = member_get_node_by_id(vs, id);
129
130   if (member_node == NULL) {
131     DP("Create new member");
132     member = (struct rahunas_member *)rh_malloc(sizeof(struct rahunas_member));
133     if (member == NULL)
134       return (-1);
135
136     memset(member, 0, sizeof(struct rahunas_member));
137
138     vs->v_map->members = 
139         g_list_insert_sorted(vs->v_map->members, member, idcmp);
140
141   } else {
142     DP("Member already exists");
143     member = (struct rahunas_member *)member_node->data;
144   }
145
146   member->id = id; 
147
148   if (member->username && member->username != termstring)
149     free(member->username);
150
151   if (member->session_id && member->username != termstring)
152     free(member->session_id);
153
154   if (member->serviceclass_name && member->serviceclass_name != termstring)
155     free(member->serviceclass_name);
156
157   if (member->mapping_ip && member->mapping_ip != termstring)
158     free(member->mapping_ip);
159
160   member->username   = strdup(req->username);
161   if (!member->username)
162     member->username = strdup(termstring);
163
164   member->session_id = strdup(req->session_id);
165   if (!member->session_id)
166     member->session_id = strdup(termstring);
167
168   member->serviceclass_name    = NULL;
169   member->serviceclass_description = termstring;
170   member->serviceclass_slot_id = 0;
171   member->mapping_ip = termstring;
172
173   if (req->session_start == 0) {
174     time(&(req->session_start));
175   } 
176
177   memcpy(&member->session_start, &req->session_start, sizeof(time_t));
178
179   memcpy(&member->mac_address, &req->mac_address, ETH_ALEN);
180
181   memcpy(&member->session_timeout, &req->session_timeout, 
182          sizeof(time_t));
183   member->bandwidth_max_down = req->bandwidth_max_down;
184   member->bandwidth_max_up = req->bandwidth_max_up;
185  
186   DP("Session-Timeout %d", req->session_timeout);
187   DP("Bandwidth - Down: %lu, Up: %lu", req->bandwidth_max_down, 
188        req->bandwidth_max_up);
189
190   logmsg(RH_LOG_NORMAL, "[%s] Session Start, User: %s, IP: %s, "
191                         "Session ID: %s, MAC: %s",
192                         vs->vserver_config->vserver_name,
193                         member->username, 
194                         idtoip(vs->v_map, id), 
195                         member->session_id,
196                         mac_tostring(member->mac_address)); 
197   return 0;
198 }
199
200 /* Stop session task */
201 static int stopsess  (RHVServer *vs, struct task_req *req)
202 {
203   uint32_t id = req->id;
204   GList *member_node = NULL;
205   struct rahunas_member *member = NULL;
206   char cause[16] = "";
207
208   member_node = member_get_node_by_id(vs, id);
209   if (member_node == NULL)
210     return (-1);
211
212   member = (struct rahunas_member *)member_node->data;
213
214   switch (req->req_opt) {
215     case RH_RADIUS_TERM_IDLE_TIMEOUT :
216       strncpy(cause, "idle timeout", sizeof (cause));
217       break;
218     case RH_RADIUS_TERM_SESSION_TIMEOUT :
219       strncpy(cause, "session timeout", sizeof (cause));
220       break;
221     case RH_RADIUS_TERM_USER_REQUEST :
222       strncpy(cause, "user request", sizeof (cause));
223       break;
224     case RH_RADIUS_TERM_NAS_REBOOT :
225       strncpy(cause, "nas reboot", sizeof (cause));
226       break;
227     case RH_RADIUS_TERM_ADMIN_RESET :
228       strncpy(cause, "admin reset", sizeof (cause));
229       break;
230   }
231   if (!member->username)
232     member->username = strdup(termstring);
233
234   if (!member->session_id)
235     member->session_id = strdup(termstring);
236
237   logmsg(RH_LOG_NORMAL, "[%s] Session Stop (%s), User: %s, IP: %s, "
238                         "Session ID: %s, MAC: %s",
239                         vs->vserver_config->vserver_name,
240                         cause,
241                         member->username, 
242                         idtoip(vs->v_map, id), 
243                         member->session_id,
244                         mac_tostring(member->mac_address)); 
245
246   rh_free_member(member);   
247
248   vs->v_map->members = g_list_delete_link(vs->v_map->members, member_node);
249
250   return 0;
251 }
252
253 /* Commit start session task */
254 static int commitstartsess (RHVServer *vs, struct task_req *req)
255 {
256   /* Do nothing or need to implement */
257 }
258
259 /* Commit stop session task */
260 static int commitstopsess  (RHVServer *vs, struct task_req *req)
261 {
262   /* Do nothing or need to implement */
263 }
264
265 /* Rollback start session task */
266 static int rollbackstartsess (RHVServer *vs, struct task_req *req)
267 {
268   /* Do nothing or need to implement */
269 }
270
271 /* Rollback stop session task */
272 static int rollbackstopsess  (RHVServer *vs, struct task_req *req)
273 {
274   /* Do nothing or need to implement */
275 }
276
277 static struct task task_memset = {
278   .taskname = "MEMSET",
279   .taskprio = 40,
280   .init = &init,
281   .cleanup = &cleanup,
282   .startservice = &startservice,
283   .stopservice = &stopservice,
284   .startsess = &startsess,
285   .stopsess = &stopsess,
286   .commitstartsess = &commitstartsess,
287   .commitstopsess = &commitstopsess,
288   .rollbackstartsess = &rollbackstartsess,
289   .rollbackstopsess = &rollbackstopsess,
290 };
291
292 void rh_task_memset_reg(RHMainServer *ms) {
293   task_register(ms, &task_memset);
294 }