tizen 2.3 release
[kernel/api/system-resource.git] / src / network / restriction-handler.c
1 /*
2  * resourced
3  *
4  * Copyright (c) 2014 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-handler.c
22  *
23  * @desc Callback for working reset restrictions
24  *
25  * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
26  *
27  */
28
29 #include <data_usage.h>
30 #include <stdlib.h>
31 #include <net/if.h>
32
33 #include "const.h"
34 #include "iface.h"
35 #include "macro.h"
36 #include "net-cls-cgroup.h"
37 #include "trace.h"
38 #include "restriction-helper.h"
39 #include "datausage-restriction.h"
40 #include "restriction-handler.h"
41
42 struct restriction_context {
43         int ifindex;
44         list_restrictions_info *restrictions;
45 };
46
47 static gpointer _create_reset_restriction(
48         const resourced_restriction_info *info, const int ifindex)
49 {
50         resourced_iface_type iftype;
51         resourced_restriction_info *res_data;
52
53         iftype = get_iftype(ifindex);
54         if (info->iftype != iftype)
55                 return NULL;
56
57         res_data = (resourced_restriction_info *)
58                 malloc(sizeof(resourced_restriction_info));
59         if (!res_data) {
60                 _E("Malloc of resourced_restriction_info failed\n");
61                 return NULL;
62         }
63         res_data->app_id = strdup(info->app_id);
64         res_data->iftype = iftype;
65         res_data->rcv_limit = info->rcv_limit;
66         res_data->send_limit = info->send_limit;
67         res_data->rst_state = info->rst_state;
68         res_data->quota_id = info->quota_id;
69         res_data->roaming = info->roaming;
70         return res_data;
71 }
72
73 static resourced_cb_ret _restriction_iter(
74         const resourced_restriction_info *info, void *user_data)
75 {
76         struct restriction_context *context =
77                 (struct restriction_context *)(user_data);
78
79         if (!context) {
80                 _E("Please provide valid pointer!");
81                 return RESOURCED_CONTINUE;
82         }
83
84         _SI("we have restriction for appid %s and check it for ifindex %d\n",
85            info->app_id, context->ifindex);
86         gpointer data = _create_reset_restriction(info, context->ifindex);
87         if (data)
88                 context->restrictions = g_list_prepend(context->restrictions,
89                         data);
90         return RESOURCED_CONTINUE;
91 }
92
93 enum restriction_apply_type
94 {
95         KEEP_AS_IS,
96         UNSET,
97 };
98
99 struct apply_param
100 {
101         enum restriction_apply_type apply_type;
102 };
103
104 static void _reset_restrictions_iter(gpointer data, gpointer user_data)
105 {
106         resourced_restriction_info *arg = (resourced_restriction_info *)data;
107         struct apply_param *param = (struct apply_param *)user_data;
108
109         u_int32_t app_classid = RESOURCED_UNKNOWN_CLASSID;
110         resourced_net_restrictions rst = {0};
111         int error_code = RESOURCED_ERROR_NONE;
112         enum traffic_restriction_type rst_type;
113
114         ret_msg_if(!arg || !param, "Please provide valid pointer!");
115
116         rst.iftype = arg->iftype;
117         rst.send_limit = arg->send_limit;
118         rst.rcv_limit = arg->rcv_limit;
119         rst.roaming = arg->roaming;
120
121         if (param->apply_type == KEEP_AS_IS)
122                 rst_type = convert_to_restriction_type(arg->rst_state);
123         else if (param->apply_type == UNSET)
124                 rst_type = RST_UNSET;
125         else
126                 rst_type = RST_UNDEFINDED;
127
128         app_classid = get_classid_by_app_id(arg->app_id, false);
129
130         error_code = process_kernel_restriction(app_classid,
131                 &rst, rst_type);
132
133         ret_msg_if(error_code != RESOURCED_ERROR_NONE,
134                          "restriction type %d failed, error %d\n", rst_type,
135                          error_code);
136 }
137
138 static void _apply_restrictions(const list_restrictions_info *restrictions)
139 {
140         struct apply_param param = {.apply_type = KEEP_AS_IS};
141         if (!restrictions) {
142                 _D("No restrictions!");
143                 return;
144         }
145         g_list_foreach((GList *)restrictions, _reset_restrictions_iter, &param);
146 }
147
148 static void _reset_restrictions(const list_restrictions_info *restrictions)
149 {
150         struct apply_param param = {.apply_type = UNSET};
151         if (!restrictions) {
152                 _D("No restrictions!");
153                 return;
154         }
155         g_list_foreach((GList *)restrictions, _reset_restrictions_iter, &param);
156 }
157
158 static void _free_restriction_iter(gpointer data)
159 {
160         resourced_restriction_info *arg = (resourced_restriction_info *)data;
161         if (!arg) {
162                 _D("No restrictions!");
163                 return;
164         }
165         free((char *)arg->app_id);
166         return;
167 }
168
169 static void _free_reset_restrictions(list_restrictions_info *restrictions)
170 {
171         if (!restrictions) {
172                 _E("Plese provide valid pointer!");
173                 return;
174         }
175         g_list_free_full(restrictions, _free_restriction_iter);
176 }
177
178 static void process_on_iface_up(const int ifindex)
179 {
180         struct restriction_context context = {
181                 .restrictions = 0,
182                 .ifindex = ifindex,
183         };
184
185         restrictions_foreach(_restriction_iter, &context);
186         if (!context.restrictions) {
187                 _D("No restrictions!");
188                 return;
189         }
190         _apply_restrictions(context.restrictions);
191         _free_reset_restrictions(context.restrictions);
192 }
193
194 static void handle_on_iface_up(const int ifindex)
195 {
196         process_on_iface_up(ifindex);
197 }
198
199 static void handle_on_iface_down(const int ifindex)
200 {
201         struct restriction_context context = {
202                 .restrictions = 0,
203                 .ifindex = ifindex,
204         };
205
206         restrictions_foreach(_restriction_iter, &context);
207         if (!context.restrictions) {
208                 _D("No restrictions!");
209                 return;
210         }
211         _reset_restrictions(context.restrictions);
212         _free_reset_restrictions(context.restrictions);
213 }
214
215 static resourced_cb_ret roaming_restrictions_iter(
216         const resourced_restriction_info *info, void *user_data)
217 {
218         struct apply_param param = {.apply_type = KEEP_AS_IS};
219         _reset_restrictions_iter((gpointer)info, &param);
220         return RESOURCED_CONTINUE;
221 }
222
223 static void handle_roaming_change(void)
224 {
225         restrictions_foreach(roaming_restrictions_iter, NULL);
226 }
227
228 roaming_cb get_roaming_restriction_cb(void)
229 {
230         return handle_roaming_change;
231 }
232
233 iface_callback *create_restriction_callback(void)
234 {
235         iface_callback *ret_arg = (iface_callback *)
236                 malloc(sizeof(iface_callback));
237
238         if (!ret_arg) {
239                 _E("Malloc of iface_callback failed\n");
240                 return NULL;
241         }
242         ret_arg->handle_iface_up = handle_on_iface_up;
243         ret_arg->handle_iface_down = handle_on_iface_down;
244
245         return ret_arg;
246 }
247
248 void reactivate_restrictions(void)
249 {
250         int i;
251         struct if_nameindex *ids = if_nameindex();
252
253         ret_msg_if(ids == NULL,
254                          "Failed to initialize iftype table! errno: %d, %s",
255                          errno, strerror(errno));
256
257         for (i = 0; ids[i].if_index != 0; ++i) {
258                 if (!is_address_exists(ids[i].if_name))
259                         continue;
260                 process_on_iface_up(ids[i].if_index);
261         }
262
263         if_freenameindex(ids);
264 }