4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * @file set-restriction.c
22 * @desc Implementation of the set network restriction body
27 #include <resourced.h>
32 #include "module-data.h"
33 #include "net-cls-cgroup.h"
34 #include "netlink-restriction.h"
36 #include "restriction-helper.h"
37 #include "datausage-restriction.h"
41 #include "tethering-restriction.h"
43 #define SET_NET_RESTRICTIONS "REPLACE INTO restrictions " \
44 "(binpath, rcv_limit, send_limit, iftype, rst_state, "\
45 " quota_id, roaming) " \
46 "VALUES (?, ?, ?, ?, ?, ?, ?)"
48 #define GET_NET_RESTRICTION "SELECT rcv_limit, send_limit, " \
49 " rst_state, quota_id FROM restrictions " \
50 "WHERE binpath = ? AND iftype = ?"
52 #define RESET_RESTRICTIONS "DELETE FROM restrictions " \
53 "WHERE binpath=? AND iftype=?"
55 static sqlite3_stmt *update_rst_stm;
56 static sqlite3_stmt *reset_rst_stm;
58 static resourced_ret_c init_reset_rst(void)
60 resourced_ret_c error_code = RESOURCED_ERROR_NONE;
64 DB_ACTION(sqlite3_prepare_v2
65 (resourced_get_database(), RESET_RESTRICTIONS, -1,
66 &reset_rst_stm, NULL));
71 _E("Failed to initialize %s", RESET_RESTRICTIONS);
75 static resourced_ret_c reset_restriction_db(const char *app_id,
76 const resourced_iface_type iftype)
78 resourced_ret_c error_code = init_reset_rst();
80 ret_value_if(error_code != RESOURCED_ERROR_NONE, error_code);
82 DB_ACTION(sqlite3_bind_text(reset_rst_stm, 1, app_id, -1, SQLITE_TRANSIENT));
83 DB_ACTION(sqlite3_bind_int(reset_rst_stm, 2, iftype));
85 if (sqlite3_step(reset_rst_stm) != SQLITE_DONE)
86 error_code = RESOURCED_ERROR_DB_FAILED;
90 sqlite3_reset(reset_rst_stm);
91 if (error_code == RESOURCED_ERROR_DB_FAILED)
92 _E("Failed to remove restrictions by network interface %s\n",
93 sqlite3_errmsg(resourced_get_database()));
98 static resourced_ret_c init_update_rest_stmt(void)
100 resourced_ret_c error_code = RESOURCED_ERROR_NONE;
104 DB_ACTION(sqlite3_prepare_v2
105 (resourced_get_database(), SET_NET_RESTRICTIONS, -1,
106 &update_rst_stm, NULL));
110 _E("Failed to initialize %s", SET_NET_RESTRICTIONS);
114 resourced_ret_c update_restriction_db(
115 const char *app_id, const resourced_iface_type iftype,
116 const int rcv_limit, const int snd_limit,
117 const resourced_restriction_state rst_state,
119 const resourced_roaming_type roaming)
121 resourced_ret_c error_code = RESOURCED_ERROR_NONE;
123 if (rst_state == RESOURCED_RESTRICTION_REMOVED)
124 return reset_restriction_db(app_id, iftype);
126 error_code = init_update_rest_stmt();
127 ret_value_if(error_code != RESOURCED_ERROR_NONE, error_code);
129 DB_ACTION(sqlite3_bind_text(update_rst_stm, 1, app_id, -1, SQLITE_TRANSIENT));
130 DB_ACTION(sqlite3_bind_int64(update_rst_stm, 2, rcv_limit));
131 DB_ACTION(sqlite3_bind_int64(update_rst_stm, 3, snd_limit));
132 DB_ACTION(sqlite3_bind_int(update_rst_stm, 4, iftype));
133 DB_ACTION(sqlite3_bind_int(update_rst_stm, 5, rst_state));
134 DB_ACTION(sqlite3_bind_int(update_rst_stm, 6, quota_id));
135 DB_ACTION(sqlite3_bind_int(update_rst_stm, 7, roaming));
137 if (sqlite3_step(update_rst_stm) != SQLITE_DONE)
138 error_code = RESOURCED_ERROR_DB_FAILED;
142 sqlite3_reset(update_rst_stm);
143 if (error_code == RESOURCED_ERROR_DB_FAILED)
144 _E("Failed to set network restriction: %s\n",
145 sqlite3_errmsg(resourced_get_database()));
150 resourced_ret_c get_restriction_info(const char *app_id,
151 const resourced_iface_type iftype,
152 resourced_restriction_info *rst)
155 resourced_ret_c error_code = RESOURCED_ERROR_NONE;
157 sqlite3_stmt *stm = NULL;
159 ret_value_msg_if(rst == NULL, RESOURCED_ERROR_INVALID_PARAMETER,
160 "Please provide valid restriction argument!");
162 ret_value_msg_if(app_id == NULL, RESOURCED_ERROR_INVALID_PARAMETER,
163 "Please provide valid app_id argument!");
165 _SD("%s, %d", app_id, iftype);
167 DB_ACTION(sqlite3_prepare_v2
168 (resourced_get_database(), GET_NET_RESTRICTION, -1, &stm, NULL));
170 DB_ACTION(sqlite3_bind_text(stm, 1, app_id, -1, SQLITE_TRANSIENT));
171 DB_ACTION(sqlite3_bind_int(stm, 2, iftype));
174 rc = sqlite3_step(stm);
177 rst->rcv_limit = sqlite3_column_int(stm, 0);
178 rst->send_limit = sqlite3_column_int64(stm, 1);
179 rst->rst_state = sqlite3_column_int(stm, 2);
180 rst->quota_id = sqlite3_column_int(stm, 3);
187 error_code = RESOURCED_ERROR_DB_FAILED;
190 } while (rc == SQLITE_ROW);
197 sqlite3_finalize(stm);
199 if (error_code == RESOURCED_ERROR_DB_FAILED)
200 _E("Failed to get network restriction's quota id: %s\n",
201 sqlite3_errmsg(resourced_get_database()));
206 static bool check_roaming(const resourced_net_restrictions *rst)
208 resourced_roaming_type roaming;
209 ret_value_msg_if(rst == NULL, false,
210 "Invalid net_restriction pointer, please provide valid argument");
212 roaming = get_roaming();
213 _D("roaming %d rst->roaming %d", roaming, rst->roaming);
214 if (roaming == RESOURCED_ROAMING_UNKNOWN ||
215 rst->roaming == RESOURCED_ROAMING_UNKNOWN) {
218 return rst->roaming != roaming;
221 static void process_net_block_state(const enum
222 traffic_restriction_type rst_type)
224 struct shared_modules_data *m_data = get_shared_modules_data();
227 set_daemon_net_block_state(rst_type, m_data->carg);
229 _E("shared modules data is empty");
232 resourced_ret_c process_kernel_restriction(
233 const u_int32_t classid,
234 const resourced_net_restrictions *rst,
235 const enum traffic_restriction_type rst_type)
237 int ret = RESOURCED_ERROR_NONE;
239 ret_value_secure_msg_if(!classid, RESOURCED_ERROR_INVALID_PARAMETER,
240 "Can not determine classid for package %u.\n"
241 "Probably package was not joined to performance "
242 "monitoring\n", classid);
244 if (rst_type == RST_EXCLUDE && check_roaming(rst)) {
245 _D("Restriction not applied: rst->roaming %d", rst->roaming);
246 return RESOURCED_ERROR_NONE;
249 /* TODO check, and think how to implement it
250 * in unified way, maybe also block FORWARD chain in
251 * send_net_restriction */
252 if (classid == RESOURCED_ALL_APP_CLASSID ||
253 classid == RESOURCED_TETHERING_APP_CLASSID)
254 ret = apply_tethering_restriction(rst_type);
255 if (classid != RESOURCED_TETHERING_APP_CLASSID &&
256 ret == RESOURCED_ERROR_NONE)
257 ret = send_net_restriction(rst_type, classid,
261 rst->snd_warning_limit,
262 rst->rcv_warning_limit);
263 ret_value_msg_if(ret < 0, RESOURCED_ERROR_FAIL,
264 "Restriction, type %d falied, return code %d\n",
267 return RESOURCED_ERROR_NONE;
270 resourced_ret_c proc_keep_restriction(
271 const char *app_id, const int quota_id,
272 const resourced_net_restrictions *rst,
273 const enum traffic_restriction_type rst_type)
275 u_int32_t app_classid = 0;
276 resourced_iface_type store_iftype;
277 resourced_restriction_state rst_state;
278 int ret = check_restriction_arguments(app_id, rst, rst_type);
279 ret_value_msg_if(ret != RESOURCED_ERROR_NONE,
280 RESOURCED_ERROR_INVALID_PARAMETER,
281 "Invalid restriction arguments\n");
283 app_classid = get_classid_by_app_id(app_id, rst_type != RST_UNSET);
284 ret = process_kernel_restriction(app_classid, rst, rst_type);
285 ret_value_msg_if(ret != RESOURCED_ERROR_NONE, ret,
286 "Can't keep restriction.");
288 store_iftype = get_store_iftype(app_classid, rst->iftype);
289 rst_state = convert_to_restriction_state(rst_type);
290 _SD("restriction: app_id %s, iftype %d, state %d, type %d\n", app_id,
291 store_iftype, rst_state, rst_type);
293 if (!strcmp(app_id, RESOURCED_ALL_APP) &&
294 rst->iftype == RESOURCED_IFACE_ALL)
295 process_net_block_state(rst_type);
297 return update_restriction_db(app_id, store_iftype,
298 rst->rcv_limit, rst->send_limit,
299 rst_state, quota_id, rst->roaming);
302 resourced_ret_c remove_restriction_local(const char *app_id,
303 const resourced_iface_type iftype)
305 resourced_net_restrictions rst = { 0 };
308 return proc_keep_restriction(app_id, NONE_QUOTA_ID, &rst,
312 resourced_ret_c exclude_restriction_local(const char *app_id,
314 const resourced_iface_type iftype)
316 resourced_net_restrictions rst = { 0 };
319 return proc_keep_restriction(app_id, quota_id, &rst, RST_EXCLUDE);