Add new iptables handle task
[rahunas] / src / rh-task-dbset.c
1 /**
2  * RahuNAS task dbset implementation 
3  * Author: Suriya  Soutmun <darksolar@gmail.com>
4  * Date:   2008-09-11
5  */
6
7 #include <stdlib.h>
8 #include <syslog.h>
9 #include <time.h>
10 #include <string.h>
11 #include <libgda/libgda.h>
12 #include "rahunasd.h"
13 #include "rh-task.h"
14 #include "rh-ipset.h"
15 #include "rh-utils.h"
16
17 struct dbset_row {
18   gchar *session_id;
19   gchar *vserver_id;
20   gchar *username;
21   gchar *ip;
22   gchar *mac;
23   time_t session_start;
24   time_t session_timeout;
25   unsigned short bandwidth_slot_id; 
26   long bandwidth_max_down;
27   long bandwidth_max_up;
28 };
29
30 gboolean get_errors (GdaConnection * connection)
31 {
32   GList *list;
33   GList *node;
34   GdaConnectionEvent *error;
35
36   list = (GList *) gda_connection_get_events(connection);
37
38   for (node = g_list_first(list); node != NULL; node = g_list_next(node)) {
39     error = (GdaConnectionEvent *) node->data;
40     logmsg(RH_LOG_NORMAL, "DB Error no: %d", 
41              gda_connection_event_get_code(error));
42     logmsg(RH_LOG_NORMAL, "DB Desc: %s", 
43              gda_connection_event_get_description(error));
44     logmsg(RH_LOG_NORMAL, "DB Source: %s", 
45              gda_connection_event_get_source(error));
46     logmsg(RH_LOG_NORMAL, "DB SQL State: %s", 
47              gda_connection_event_get_sqlstate(error));
48   }
49 }
50
51 gboolean *parse_dm_to_struct(GList **data_list, GdaDataModel *dm) {
52   gint  row_id;
53   gint  column_id;
54   GValue *value;
55   gchar  *str;
56   gchar  *title;
57   GdaNumeric *num;
58   struct dbset_row *row;
59   struct tm tm;
60   time_t time;
61
62   char tmp[80];
63
64   for (row_id = 0; row_id < gda_data_model_get_n_rows(dm); row_id++) {
65     row = (struct dbset_row *)g_malloc(sizeof(struct dbset_row));
66     if (row == NULL) {
67       /* Do implement the row list cleanup */
68     }
69
70     *data_list = g_list_append(*data_list, row); 
71
72     for (column_id = 0; column_id < gda_data_model_get_n_columns(dm); 
73            column_id++) {
74
75       title = gda_data_model_get_column_title(dm, column_id);
76       value = gda_data_model_get_value_at (dm, column_id, row_id);
77       str = gda_value_stringify(value);
78                
79       if (strncmp("session_id", title, 10) == 0) {
80         row->session_id = g_strdup(str);
81       } else if (strncmp("vserver_id", title, 10) == 0) {
82         row->vserver_id = g_strdup(str);
83       } else if (strncmp("username", title, 8) == 0) {
84         row->username = g_strdup(str);
85       } else if (strncmp("ip", title, 2) == 0) {
86         row->ip = g_strdup(str);
87       } else if (strncmp("mac", title, 3) == 0) {
88         row->mac = g_strdup(str);
89       } else if (strncmp("session_start", title, 13) == 0) {
90         strptime(str, "%s", &tm);
91         time = mktime(&tm);
92         memcpy(&row->session_start, &time, sizeof(time_t));
93       } else if (strncmp("session_timeout", title, 15) == 0) {
94         strptime(str, "%s", &tm);
95         time = mktime(&tm);
96         memcpy(&row->session_timeout, &time, sizeof(time_t));
97       } else if (strncmp("bandwidth_slot_id", title, 17) == 0) {
98         row->bandwidth_slot_id = atoi(str);
99       } else if (strncmp("bandwidth_max_down", title, 18) == 0) {
100         row->bandwidth_max_down = atol(str);
101       } else if (strncmp("bandwidth_max_up", title, 18) == 0) {
102         row->bandwidth_max_up = atol(str);
103       }
104     }
105   }
106   
107   return TRUE;
108 }
109
110 GList *execute_sql_command(GdaConnection *connection, const gchar *buffer)
111 {
112   GdaCommand *command;
113   GList *data_list = NULL;
114   GList *list;
115   GList *node;
116   GdaDataModel *dm;
117   gboolean errors = FALSE;
118
119
120   command = gda_command_new (buffer, GDA_COMMAND_TYPE_SQL,
121                              GDA_COMMAND_OPTION_STOP_ON_ERRORS);
122
123   list = gda_connection_execute_command (connection, command, NULL, NULL);
124   if (list != NULL) {
125     for (node = list; node != NULL; node = g_list_next(node)) {
126       if (GDA_IS_DATA_MODEL(node->data)) {
127         dm = (GdaDataModel *) node->data;
128         parse_dm_to_struct(&data_list, dm);
129         g_object_unref(dm);
130       } else {
131         get_errors (connection);
132         errors = TRUE;  
133       }
134     }
135   }
136
137   gda_command_free(command);
138   
139   return errors == TRUE ? NULL : data_list;
140 }
141
142 void execute_sql(GdaConnection *connection, const gchar *buffer)
143 {
144   GdaCommand *command;
145   
146   command = gda_command_new (buffer, GDA_COMMAND_TYPE_SQL,
147                              GDA_COMMAND_OPTION_STOP_ON_ERRORS);
148   gda_connection_execute_select_command (connection, command, NULL, NULL);
149
150   gda_command_free (command);
151 }
152
153 void list_datasource (void)
154 {
155   GList *ds_list;
156   GList *node;
157   GdaDataSourceInfo *info;
158
159   ds_list = gda_config_get_data_source_list();
160
161   for (node = g_list_first(ds_list); node != NULL; node = g_list_next(node)) {
162     info = (GdaDataSourceInfo *) node->data;
163
164     if (strncmp(info->name, PROGRAM, strlen(PROGRAM)) == 0) {
165       logmsg(RH_LOG_NORMAL, "Datasource: NAME: %s PROVIDER: %s",
166              info->name, info->provider);
167       logmsg(RH_LOG_NORMAL, "  CNC: %s", info->cnc_string);
168       logmsg(RH_LOG_NORMAL, "  DESC: %s", info->description);
169     }
170   }
171
172   gda_config_free_data_source_list(ds_list);
173 }
174
175 GdaConnection *get_connection(GdaClient *client)
176 {
177   return gda_client_open_connection (client, PROGRAM, NULL, NULL,
178                                      GDA_CONNECTION_OPTIONS_NONE, NULL);
179 }
180
181 void free_data_list(GList *data_list)
182 {
183   GList *node;
184   struct dbset_row *row;
185
186   for (node = g_list_first(data_list); node != NULL; 
187          node = g_list_next (node)) {
188     row = (struct dbset_row *) node->data;
189     g_free(row->session_id);
190     g_free(row->vserver_id);
191     g_free(row->username);
192     g_free(row->ip);
193     g_free(row->mac);
194   }
195   
196   g_list_free (data_list);  
197 }
198
199 gboolean restore_set(GList **data_list, struct vserver *vs)
200 {
201   GList *node = NULL;
202   struct dbset_row *row = NULL;
203   uint32_t id;
204   GList *member_node = NULL;
205   struct rahunas_member *member = NULL;
206   struct task_req req;
207   unsigned char ethernet[ETH_ALEN] = {0,0,0,0,0,0};
208   unsigned char max_try = 3;
209  
210   node = g_list_first(*data_list);
211
212   if (node == NULL)
213     return TRUE;
214
215   DP("Get data from DB if exist");
216
217   for (node; node != NULL; node = g_list_next(node)) {
218     row = (struct dbset_row *) node->data;
219
220     if (atoi(row->vserver_id) != vs->vserver_config->vserver_id)
221       continue;
222
223     id = iptoid(vs->v_map, row->ip);
224
225     if (id < 0)
226       continue;
227
228     req.id = id;
229     req.vserver_id = atoi(row->vserver_id);
230     req.username = row->username;
231     req.session_id = row->session_id;
232     parse_mac(row->mac, &ethernet);
233     memcpy(req.mac_address, &ethernet, ETH_ALEN);
234
235     req.session_start = row->session_start;
236     req.session_timeout = row->session_timeout;
237
238     req.bandwidth_slot_id = row->bandwidth_slot_id;
239     req.bandwidth_max_down = row->bandwidth_max_down; 
240     req.bandwidth_max_up = row->bandwidth_max_up;
241
242     rh_task_startsess(vs, &req);
243   }
244   return TRUE;
245 }
246
247 /* Start service task */
248 static int startservice ()
249 {
250   char ds_name[] = PROGRAM;
251   char ds_provider[] = "SQLite";
252   char ds_cnc_string[] = "DB_DIR=" RAHUNAS_CONF_DIR ";DB_NAME=" DB_NAME; 
253   char ds_desc[] = "RahuNAS DB Set";
254
255   logmsg(RH_LOG_NORMAL, "Task DBSET start..");
256    
257   gda_init(ds_name, RAHUNAS_VERSION, NULL, NULL);
258     
259   gda_config_save_data_source(ds_name, ds_provider, 
260                               ds_cnc_string, ds_desc,
261                               NULL, NULL, FALSE);
262    
263   list_datasource();
264
265   return 0;
266 }
267
268 /* Stop service task */
269 static int stopservice  ()
270 {
271   gda_config_remove_data_source (PROGRAM);
272   return 0;
273 }
274
275 /* Initialize */
276 static void init (struct vserver *vs)
277 {
278   GdaClient *client;
279   GdaConnection *connection;
280   GList *data_list;
281   GList *node;
282   struct dbset_row *row;
283   char select_cmd[256];
284
285   logmsg(RH_LOG_NORMAL, "[%s] Task DBSET initialize..",
286          vs->vserver_config->vserver_name);  
287
288   client = gda_client_new ();
289   connection = gda_client_open_connection (client, 
290                  PROGRAM, NULL, NULL,
291                  GDA_CONNECTION_OPTIONS_READ_ONLY, NULL);
292
293   sprintf(select_cmd, "SELECT * FROM dbset WHERE vserver_id='%d'",
294           vs->vserver_config->vserver_id);
295
296   DP("SQL: %s", select_cmd);
297
298   data_list = execute_sql_command(connection, select_cmd); 
299
300   restore_set(&data_list, vs);
301
302   free_data_list(data_list);
303
304   gda_client_close_all_connections (client);
305
306   g_object_unref(G_OBJECT(client));
307 }
308
309 /* Cleanup */
310 static void cleanup (struct vserver *vs)
311 {
312   /* Do nothing */
313 }
314
315 /* Start session task */
316 static int startsess (struct vserver *vs, struct task_req *req)
317 {
318   GdaClient *client;
319   GdaConnection *connection;
320   gint res;
321   char startsess_cmd[256];
322   char time_str[32];
323   char time_str2[32];
324   GList *member_node = NULL;
325   struct rahunas_member *member = NULL;
326
327   client = gda_client_new ();
328   connection = gda_client_open_connection (client, 
329                  PROGRAM, NULL, NULL,
330                  GDA_CONNECTION_OPTIONS_NONE, NULL);
331
332   strftime(&time_str, sizeof time_str, "%s", localtime(&req->session_start));
333   strftime(&time_str2, sizeof time_str2, "%s", 
334     localtime(&req->session_timeout));
335
336   member_node = member_get_node_by_id(vs, req->id);
337   if (member_node == NULL)
338     return (-1);
339
340   member = (struct rahunas_member *) member_node->data;
341
342   sprintf(startsess_cmd, "INSERT INTO dbset"
343          "(session_id,vserver_id,username,ip,mac,session_start,"
344          "session_timeout,bandwidth_slot_id,bandwidth_max_down,"
345          "bandwidth_max_up) "
346          "VALUES('%s','%d','%s','%s','%s',%s,%s,%u,%lu,%lu)",
347          req->session_id, 
348          vs->vserver_config->vserver_id, 
349          req->username, 
350          idtoip(vs->v_map, req->id), 
351          mac_tostring(req->mac_address), 
352          time_str, 
353          time_str2,
354          member->bandwidth_slot_id, 
355          req->bandwidth_max_down,
356          req->bandwidth_max_up);
357
358   DP("SQL: %s", startsess_cmd);
359
360   execute_sql(connection, startsess_cmd);
361
362   gda_client_close_all_connections (client);
363
364   g_object_unref(G_OBJECT(client)); 
365
366   return 0;
367 }
368
369 /* Stop session task */
370 static int stopsess (struct vserver *vs, struct task_req *req)
371 {
372   GdaClient *client;
373   GdaConnection *connection;
374   gint res;
375   char stopsess_cmd[256];
376   GList *member_node = NULL;
377   struct rahunas_member *member = NULL;
378
379   member_node = member_get_node_by_id(vs, req->id);
380   if (member_node == NULL)
381     return (-1);
382
383   member = (struct rahunas_member *) member_node->data;
384
385   client = gda_client_new ();
386   connection = gda_client_open_connection (client, 
387                  PROGRAM, NULL, NULL,
388                  GDA_CONNECTION_OPTIONS_NONE, NULL);
389
390   DP("Username  : %s", member->username);
391   DP("SessionID : %s", member->session_id);
392
393   sprintf(stopsess_cmd, "DELETE FROM dbset WHERE "
394          "session_id='%s' AND username='%s' AND vserver_id='%d'",
395          member->session_id, 
396          member->username,
397          vs->vserver_config->vserver_id);
398
399   DP("SQL: %s", stopsess_cmd);
400
401   execute_sql(connection, stopsess_cmd);
402
403   gda_client_close_all_connections (client);
404
405   g_object_unref(G_OBJECT(client)); 
406
407   return 0;
408 }
409
410 /* Commit start session task */
411 static int commitstartsess (struct vserver *vs, struct task_req *req)
412 {
413   /* Do nothing or need to implement */
414 }
415
416 /* Commit stop session task */
417 static int commitstopsess  (struct vserver *vs, struct task_req *req)
418 {
419   /* Do nothing or need to implement */
420 }
421
422 /* Rollback start session task */
423 static int rollbackstartsess (struct vserver *vs, struct task_req *req)
424 {
425   /* Do nothing or need to implement */
426 }
427
428 /* Rollback stop session task */
429 static int rollbackstopsess  (struct vserver *vs, struct task_req *req)
430 {
431   /* Do nothing or need to implement */
432 }
433
434 static struct task task_dbset = {
435   .taskname = "DBSET",
436   .taskprio = 10,
437   .init = &init,
438   .cleanup = &cleanup,
439   .startservice = &startservice,
440   .stopservice = &stopservice,
441   .startsess = &startsess,
442   .stopsess = &stopsess,
443   .commitstartsess = &commitstartsess,
444   .commitstopsess = &commitstopsess,
445   .rollbackstartsess = &rollbackstartsess,
446   .rollbackstopsess = &rollbackstopsess,
447 };
448
449 void rh_task_dbset_reg(struct main_server *ms) {
450   task_register(ms, &task_dbset);
451 }