tizen 2.3 release
[kernel/api/system-resource.git] / src / network / restriction.c
1 /*
2  * resourced
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 /**
21  * @file restriction.c
22  * @desc Implementation of the network restriction
23  */
24
25 #include <sqlite3.h>
26 #include <resourced.h>
27 #include <data_usage.h>
28 #include <rd-network.h>
29
30 #include "cgroup.h"             /*get_classid_by_pkg_name */
31 #include "const.h"
32 #include "database.h"
33 #include "datausage-restriction.h"
34 #include "edbus-handler.h"
35 #include "macro.h"
36 #include "netlink-restriction.h"
37 #include "restriction-helper.h"
38 #include "tethering-restriction.h"
39 #include "trace.h"
40
41 #define SELECT_RESTRICTIONS "SELECT binpath, rcv_limit, " \
42         "send_limit, iftype, rst_state, quota_id, roaming FROM restrictions"
43
44 #define SELECT_RESTRICTION_STATE "SELECT rst_state FROM restrictions " \
45         "WHERE binpath = ? AND iftype = ?"
46
47 static sqlite3_stmt *datausage_restriction_select;
48 static sqlite3_stmt *restriction_get_state_stmt;
49
50 static int init_datausage_restriction(sqlite3 *db)
51 {
52         int rc;
53         if (datausage_restriction_select)
54                 return SQLITE_OK;
55
56         rc = sqlite3_prepare_v2(db, SELECT_RESTRICTIONS, -1 ,
57                                     &datausage_restriction_select, NULL);
58         if (rc != SQLITE_OK) {
59                 _E("can not prepare datausage_restriction_select\n");
60                 datausage_restriction_select = NULL;
61                 return rc;
62         }
63         return rc;
64 }
65
66 static void serialize_restriction(const char *appid,
67                                   const enum traffic_restriction_type rst_type,
68                                   const resourced_net_restrictions *rst,
69                                   char *params[])
70 {
71         params[0] = (char *)appid;
72         params[1] = (char *)rst_type;
73         params[2] = (char *)rst->rs_type;
74         params[3] = (char *)rst->iftype;
75         params[4] = (char *)rst->send_limit;
76         params[5] = (char *)rst->rcv_limit;
77         params[6] = (char *)rst->snd_warning_limit;
78         params[7] = (char *)rst->rcv_warning_limit;
79         params[8] = (char *)rst->roaming;
80 }
81
82 static resourced_ret_c process_restriction(
83         const char *app_id, const resourced_net_restrictions *rst,
84         const enum traffic_restriction_type rst_type)
85 {
86         DBusError err;
87         DBusMessage *msg;
88         char *params[9];
89         int i = 0, ret;
90         resourced_ret_c ret_val;
91
92         ret = check_restriction_arguments(app_id, rst, rst_type);
93         ret_value_msg_if(ret != RESOURCED_ERROR_NONE,
94                          RESOURCED_ERROR_INVALID_PARAMETER,
95                          "Invalid restriction arguments\n");
96
97         serialize_restriction(app_id, rst_type, rst, params);
98
99         do {
100                 msg = dbus_method_sync(BUS_NAME, RESOURCED_PATH_NETWORK,
101                                        RESOURCED_INTERFACE_NETWORK,
102                                        RESOURCED_NETWORK_PROCESS_RESTRICTION,
103                                        "sdddddddd", params);
104                 if (msg)
105                         break;
106                 _E("Re-try to sync DBUS message, err_count : %d", i);
107         } while (i++ < RETRY_MAX);
108
109         if (!msg) {
110                 _E("Failed to sync DBUS message.");
111                 return RESOURCED_ERROR_FAIL;
112         }
113
114         dbus_error_init(&err);
115
116         ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &ret_val,
117                                     DBUS_TYPE_INVALID);
118
119         if (ret == FALSE) {
120                 _E("no message : [%s:%s]\n", err.name, err.message);
121                 ret_val = RESOURCED_ERROR_FAIL;
122         }
123
124         dbus_message_unref(msg);
125         dbus_error_free(&err);
126
127         return ret_val;
128 }
129
130 API resourced_ret_c restrictions_foreach(
131         resourced_restriction_cb restriction_cb, void *user_data)
132 {
133         resourced_restriction_info data;
134         int rc;
135         resourced_ret_c error_code = NETWORK_ERROR_NONE;
136
137         libresourced_db_initialize_once();
138         if (init_datausage_restriction(resourced_get_database()) != SQLITE_OK) {
139                 _D("Failed to initialize data usage restriction statement: %s\n",
140                    sqlite3_errmsg(resourced_get_database()));
141                 return RESOURCED_ERROR_DB_FAILED;
142         }
143
144         do {
145                 rc = sqlite3_step(datausage_restriction_select);
146                 switch (rc) {
147                 case SQLITE_DONE:
148                         break;
149                 case SQLITE_ROW:
150                         data.app_id = (char *)sqlite3_column_text(
151                                 datausage_restriction_select, 0);
152                         data.iftype = (resourced_iface_type)sqlite3_column_int(
153                                 datausage_restriction_select, 3);
154                         data.rcv_limit = sqlite3_column_int(
155                                 datausage_restriction_select, 1);
156                         data.send_limit = sqlite3_column_int(
157                                 datausage_restriction_select, 2);
158                         data.rst_state =
159                                 (resourced_restriction_state)sqlite3_column_int(
160                                         datausage_restriction_select, 4);
161                         data.quota_id = sqlite3_column_int(
162                                 datausage_restriction_select, 5);
163                         data.roaming = sqlite3_column_int(
164                                 datausage_restriction_select, 6);
165
166                         if (restriction_cb(&data, user_data) == RESOURCED_CANCEL)
167                                 rc = SQLITE_DONE;
168                         break;
169                 case SQLITE_ERROR:
170                 default:
171                         _E("Failed to enumerate restrictions: %s\n",
172                                 sqlite3_errmsg(resourced_get_database()));
173
174                         error_code = RESOURCED_ERROR_DB_FAILED;
175                 }
176         } while (rc == SQLITE_ROW);
177
178         sqlite3_reset(datausage_restriction_select);
179         return error_code;
180 }
181
182 API resourced_ret_c set_net_restriction(const char *app_id,
183                                         const resourced_net_restrictions *rst)
184 {
185         return process_restriction(app_id, rst, RST_SET);
186 }
187
188 API resourced_ret_c remove_restriction(const char *app_id)
189 {
190         return remove_restriction_by_iftype(app_id, RESOURCED_IFACE_ALL);
191 }
192
193 API resourced_ret_c remove_restriction_by_iftype(
194         const char *app_id, const resourced_iface_type iftype)
195 {
196         resourced_net_restrictions rst = { 0 };
197
198         rst.iftype = iftype;
199         return process_restriction(app_id, &rst, RST_UNSET);
200 }
201
202 API resourced_ret_c exclude_restriction(const char *app_id)
203 {
204         return exclude_restriction_by_iftype(app_id, RESOURCED_IFACE_ALL);
205 }
206
207 API resourced_ret_c exclude_restriction_by_iftype(
208         const char *app_id, const resourced_iface_type iftype)
209 {
210         resourced_net_restrictions rst = { 0 };
211
212         rst.iftype = iftype;
213         return process_restriction(app_id, &rst, RST_EXCLUDE);
214 }
215
216 API resourced_ret_c set_net_exclusion(const char *app_id,
217                         const resourced_net_restrictions *rst)
218 {
219         return process_restriction(app_id, rst, RST_EXCLUDE);
220 }
221
222 void finalize_datausage_restriction(void)
223 {
224         if (datausage_restriction_select) {
225                 sqlite3_finalize(datausage_restriction_select);
226                 datausage_restriction_select = NULL;
227         }
228 }
229
230 static int init_get_rst_statement(sqlite3* db)
231 {
232         int rc;
233
234         rc = sqlite3_prepare_v2(db, SELECT_RESTRICTION_STATE, -1 ,
235                                     &restriction_get_state_stmt, NULL);
236         if (rc != SQLITE_OK) {
237                 _E("can not prepare restriction_get_state: %d\n", rc);
238                 restriction_get_state_stmt = NULL;
239                 return NETWORK_ERROR_DB_FAILED;
240         }
241         return rc;
242 }
243
244 API resourced_ret_c get_restriction_state(const char *pkg_id,
245         resourced_iface_type iftype, resourced_restriction_state *state)
246 {
247
248         int error_code = RESOURCED_ERROR_NONE;
249         sqlite3 *db;
250
251         if (state == NULL) {
252                 _E("Please provide valid argument!");
253                 return RESOURCED_ERROR_INVALID_PARAMETER;
254         }
255
256         db = resourced_get_database();
257
258         if (db == NULL) {
259                 _E("Can't get database.");
260                 return RESOURCED_ERROR_DB_FAILED;
261         }
262
263         execute_once {
264                 error_code = init_get_rst_statement(db);
265                 if (error_code != RESOURCED_ERROR_NONE)
266                         return error_code;
267         }
268
269         *state = RESOURCED_RESTRICTION_UNKNOWN;
270         sqlite3_reset(restriction_get_state_stmt);
271         DB_ACTION(sqlite3_bind_text(restriction_get_state_stmt, 1, pkg_id, -1,
272                 SQLITE_STATIC));
273         DB_ACTION(sqlite3_bind_int(restriction_get_state_stmt, 2, iftype));
274
275         error_code = sqlite3_step(restriction_get_state_stmt);
276         switch (error_code) {
277         case SQLITE_DONE:
278                 break;
279         case SQLITE_ROW:
280                 *state = (network_restriction_state)sqlite3_column_int(
281                         restriction_get_state_stmt, 0);
282                 break;
283         case SQLITE_ERROR:
284         default:
285                 _E("Can't perform sql query: %s \n%s",
286                         SELECT_RESTRICTION_STATE, sqlite3_errmsg(db));
287                 error_code = RESOURCED_ERROR_DB_FAILED;
288         }
289
290 handle_error:
291
292         sqlite3_reset(restriction_get_state_stmt);
293         return error_code;
294 }
295