Replaced type from state for restriction
[platform/core/connectivity/stc-manager.git] / src / stc-restriction.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "stc-db.h"
18 #include "table-restrictions.h"
19 #include "stc-restriction.h"
20 #include "stc-manager-gdbus.h"
21 #include "stc-monitor.h"
22
23 #define RESTRICTION_DBUS_ERROR_NAME "net.stc.restriction.Error.Failed"
24
25 #define STC_RESTRICTION_DBUS_REPLY_ERROR(invocation, err_num) \
26         g_dbus_method_invocation_return_dbus_error((invocation), \
27                                                    RESTRICTION_DBUS_ERROR_NAME, \
28                                                    stc_err_strs[-(err_num)])
29
30 static const gchar *stc_err_strs[] = {
31         "ERROR_NONE",
32         "FAIL",
33         "DB_FAILED",
34         "OUT_OF_MEMORY",
35         "INVALID_PARAMETER",
36         "NO_DATA",
37         "ALREADY_DATA",
38         "UNINITIALIZED",
39         "PERMISSION_DENIED",
40         "NOTIMPL"
41 };
42
43 void __initialize_rstn_rule(table_restrictions_info *rule)
44 {
45         rule->app_id = NULL;
46         rule->ifname = NULL;
47         rule->iftype = STC_IFACE_ALL;
48         rule->rstn_type = STC_RSTN_TYPE_UNKNOWN;
49         rule->data_limit = 0;
50         rule->data_warn_limit = 0;
51         rule->roaming = STC_ROAMING_DISABLE;
52         rule->subscriber_id = NULL;
53 }
54
55 gboolean __validate_rstn_rule(table_restrictions_info *rule,
56                               enum traffic_restriction_type rstn_type)
57 {
58         __STC_LOG_FUNC_ENTER__;
59
60         if (rule == NULL) {
61                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
62                 return FALSE; //LCOV_EXCL_LINE
63         }
64
65         if (rstn_type <= RST_UNDEFINDED || rstn_type >= RST_MAX_VALUE) {
66                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
67                 return FALSE; //LCOV_EXCL_LINE
68         }
69
70         if (rule->iftype <= STC_IFACE_UNKNOWN ||
71             rule->iftype >= STC_IFACE_LAST_ELEM) {
72                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
73                 return FALSE; //LCOV_EXCL_LINE
74         }
75
76         if (rule->roaming >= STC_ROAMING_LAST_ELEM) {
77                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
78                 return FALSE; //LCOV_EXCL_LINE
79         }
80
81         if (rule->subscriber_id == NULL) {
82                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
83                 return FALSE; //LCOV_EXCL_LINE
84         }
85
86         if (rule->app_id == NULL) {
87                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
88                 return FALSE; //LCOV_EXCL_LINE
89         }
90
91         __STC_LOG_FUNC_EXIT__;
92         return TRUE;
93 }
94
95 void __stc_restriction_app_info_builder_add(GVariantBuilder *builder,
96                                             const table_restrictions_info *info)
97 {
98         __STC_LOG_FUNC_ENTER__;
99
100         if (!builder || !info) {
101                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
102                 return; //LCOV_EXCL_LINE
103         }
104
105         g_variant_builder_add(builder, "{sv}", "app_id",
106                               g_variant_new_string(info->app_id));
107
108         g_variant_builder_add(builder, "{sv}", "ifname",
109                               g_variant_new_string(info->ifname));
110
111         g_variant_builder_add(builder, "{sv}", "iftype",
112                               g_variant_new_uint16(info->iftype));
113
114         g_variant_builder_add(builder, "{sv}", "rstn_type",
115                               g_variant_new_uint16(info->rstn_type));
116
117         g_variant_builder_add(builder, "{sv}", "data_limit",
118                               g_variant_new_int64(info->data_limit));
119
120         g_variant_builder_add(builder, "{sv}", "data_warn_limit",
121                               g_variant_new_int64(info->data_warn_limit));
122
123         g_variant_builder_add(builder, "{sv}", "roaming",
124                               g_variant_new_uint16(info->roaming));
125
126         g_variant_builder_add(builder, "{sv}", "subscriber_id",
127                               g_variant_new_string(info->subscriber_id));
128
129         __STC_LOG_FUNC_EXIT__;
130 }
131
132 stc_cb_ret_e __table_restrictions_foreach_app_cb(const table_restrictions_info *info,
133                                                  void *user_data)
134 {
135         __STC_LOG_FUNC_ENTER__;
136         GVariantBuilder *builder = (GVariantBuilder *)user_data;
137         GVariantBuilder sub_builder;
138
139         if (!info || !builder) {
140                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
141                 return STC_CANCEL; //LCOV_EXCL_LINE
142         }
143
144         g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
145         __stc_restriction_app_info_builder_add(&sub_builder, info);
146
147         g_variant_builder_add_value(builder,
148                                     g_variant_builder_end(&sub_builder));
149
150         __STC_LOG_FUNC_EXIT__;
151         return STC_CONTINUE;
152 }
153
154 stc_cb_ret_e __table_restrictions_per_app_cb(const table_restrictions_info *info,
155                                              void *user_data)
156 {
157         __STC_LOG_FUNC_ENTER__;
158         GVariantBuilder *builder = (GVariantBuilder *)user_data;
159
160         if (!info || !builder) {
161                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
162                 return STC_CANCEL; //LCOV_EXCL_LINE
163         }
164
165         __stc_restriction_app_info_builder_add(builder, info);
166
167         __STC_LOG_FUNC_EXIT__;
168         return STC_CONTINUE;
169 }
170
171 static void __stc_extract_restriction_rule(const char *key, GVariant *value,
172                                            void *user_data)
173 {
174         __STC_LOG_FUNC_ENTER__;
175
176         table_restrictions_info *rule =
177                 (table_restrictions_info *) user_data;
178         if (rule == NULL) {
179                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
180                 return; //LCOV_EXCL_LINE
181         }
182
183         if (!g_strcmp0(key, "app_id")) {
184                 guint str_length;
185                 const gchar *str = g_variant_get_string(value, &str_length);
186                 rule->app_id = g_strdup(str);
187                 STC_LOGD("app_id: [%s]", (unsigned int) rule->app_id);
188
189         } else if (!g_strcmp0(key, "ifname")) {
190                 guint str_length;
191                 const gchar *str = g_variant_get_string(value, &str_length);
192                 rule->ifname = g_strdup(str);
193                 STC_LOGD("ifname: [%s]", rule->ifname);
194
195         } else if (!g_strcmp0(key, "iftype")) {
196                 rule->iftype = g_variant_get_uint16(value);
197                 STC_LOGD("iftype: [%u]", (unsigned int) rule->iftype);
198
199         } else if (!g_strcmp0(key, "data_limit")) {
200                 rule->data_limit = g_variant_get_int64(value);
201                 STC_LOGD("data_limit: [%lld]", rule->data_limit);
202
203         } else if (!g_strcmp0(key, "data_warn_limit")) {
204                 rule->data_warn_limit = g_variant_get_int64(value);
205                 STC_LOGD("data_warn_limit: [%lld]", rule->data_warn_limit);
206
207         } else if (!g_strcmp0(key, "roaming")) {
208                 rule->roaming = g_variant_get_uint16(value);
209                 STC_LOGD("roaming: [%u]", rule->roaming);
210
211         } else if (!g_strcmp0(key, "subscriber_id")) {
212                 guint str_length;
213                 const gchar *str = g_variant_get_string(value, &str_length);
214                 rule->subscriber_id = g_strdup(str);
215                 STC_LOGD("subscriber_id: [%s]", rule->subscriber_id);
216
217         } else {
218                 STC_LOGD("Unknown select rule"); //LCOV_EXCL_LINE
219         }
220
221         __STC_LOG_FUNC_EXIT__;
222 }
223
224 gboolean handle_restriction_set(StcRestriction *object,
225                                 GDBusMethodInvocation *invocation,
226                                 GVariant *parameters,
227                                 void *user_data)
228 {
229         __STC_LOG_FUNC_ENTER__;
230         GVariantIter *iter = NULL;
231         table_restrictions_info rule;
232
233         memset(&rule, 0, sizeof(table_restrictions_info));
234         __initialize_rstn_rule(&rule);
235
236         g_variant_get(parameters, "a{sv}", &iter);
237         if (iter != NULL) {
238                 stc_manager_gdbus_dict_foreach(iter,
239                                                __stc_extract_restriction_rule,
240                                                &rule);
241                 g_variant_iter_free(iter);
242         }
243
244         rule.rstn_type = STC_RSTN_TYPE_DROP;
245
246         if (__validate_rstn_rule(&rule, RST_SET) == FALSE) {
247                 STC_RESTRICTION_DBUS_REPLY_ERROR(invocation, //LCOV_EXCL_LINE
248                                                  STC_ERROR_INVALID_PARAMETER);
249                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
250                 return TRUE;
251         }
252
253         table_restrictions_update(&rule);
254         /* update restriction rule in runtime structure */
255         stc_monitor_rstns_tree_add(&rule);
256
257         STC_DBUS_REPLY_ERROR_NONE(invocation);
258         __STC_LOG_FUNC_EXIT__;
259         return TRUE;
260 }
261
262 gboolean handle_restriction_exclude(StcRestriction *object,
263                                     GDBusMethodInvocation *invocation,
264                                     GVariant *parameters,
265                                     void *user_data)
266 {
267         __STC_LOG_FUNC_ENTER__;
268         GVariantIter *iter = NULL;
269         table_restrictions_info rule;
270
271         memset(&rule, 0, sizeof(table_restrictions_info));
272         __initialize_rstn_rule(&rule);
273
274         g_variant_get(parameters, "a{sv}", &iter);
275         if (iter != NULL) {
276                 stc_manager_gdbus_dict_foreach(iter,
277                                                __stc_extract_restriction_rule,
278                                                &rule);
279                 g_variant_iter_free(iter);
280         }
281
282         rule.rstn_type = STC_RSTN_TYPE_ACCEPT;
283
284         if (__validate_rstn_rule(&rule, RST_EXCLUDE) == FALSE) {
285                 STC_RESTRICTION_DBUS_REPLY_ERROR(invocation, //LCOV_EXCL_LINE
286                                                  STC_ERROR_INVALID_PARAMETER);
287                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
288                 return TRUE;
289         }
290
291         table_restrictions_update(&rule);
292         /* update restriction rule in runtime structure */
293         stc_monitor_rstns_tree_add(&rule);
294
295         STC_DBUS_REPLY_ERROR_NONE(invocation);
296         __STC_LOG_FUNC_EXIT__;
297         return TRUE;
298 }
299
300 gboolean handle_restriction_unset(StcRestriction *object,
301                                    GDBusMethodInvocation *invocation,
302                                    GVariant *parameters,
303                                    void *user_data)
304 {
305         __STC_LOG_FUNC_ENTER__;
306         GVariantIter *iter = NULL;
307         table_restrictions_info rule;
308
309         memset(&rule, 0, sizeof(table_restrictions_info));
310         __initialize_rstn_rule(&rule);
311
312         g_variant_get(parameters, "a{sv}", &iter);
313         if (iter != NULL) {
314                 stc_manager_gdbus_dict_foreach(iter,
315                                                __stc_extract_restriction_rule,
316                                                &rule);
317                 g_variant_iter_free(iter);
318         }
319
320         if (__validate_rstn_rule(&rule, RST_UNSET) == FALSE) {
321                 STC_RESTRICTION_DBUS_REPLY_ERROR(invocation, //LCOV_EXCL_LINE
322                                                  STC_ERROR_INVALID_PARAMETER);
323                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
324                 return TRUE;
325         }
326
327         table_restrictions_delete(rule.app_id, rule.iftype, rule.subscriber_id);
328         /* remove restriction rule from runtime structure */
329         stc_monitor_rstns_tree_remove(&rule);
330
331         STC_DBUS_REPLY_ERROR_NONE(invocation);
332         __STC_LOG_FUNC_EXIT__;
333         return TRUE;
334 }
335
336 gboolean handle_restriction_get(StcRestriction *object,
337                                 GDBusMethodInvocation *invocation,
338                                 const gchar *app_id,
339                                 void *user_data)
340 {
341         __STC_LOG_FUNC_ENTER__;
342         GVariantBuilder *builder = NULL;
343         GVariant *return_parameters = NULL;
344         stc_error_e ret;
345
346         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
347
348         ret = table_restrictions_per_app(app_id,
349                                          __table_restrictions_per_app_cb,
350                                          builder);
351         if (ret < STC_ERROR_NONE) {
352                 g_variant_builder_unref(builder); //LCOV_EXCL_LINE
353                 STC_RESTRICTION_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
354                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
355                 return TRUE; //LCOV_EXCL_LINE
356         }
357
358         return_parameters = g_variant_new("(ia{sv})", STC_ERROR_NONE, builder);
359         g_variant_builder_unref(builder);
360
361         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
362         STC_DBUS_REPLY(invocation, return_parameters);
363         __STC_LOG_FUNC_EXIT__;
364         return TRUE;
365 }
366
367 gboolean handle_restriction_get_all(StcRestriction *object,
368                                     GDBusMethodInvocation *invocation,
369                                     void *user_data)
370 {
371         __STC_LOG_FUNC_ENTER__;
372         GVariantBuilder *builder = NULL;
373         GVariant *return_parameters = NULL;
374         stc_error_e ret;
375
376         builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
377
378         ret = table_restrictions_foreach(__table_restrictions_foreach_app_cb,
379                                          builder);
380         if (ret < STC_ERROR_NONE) {
381                 g_variant_builder_unref(builder); //LCOV_EXCL_LINE
382                 STC_RESTRICTION_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
383                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
384                 return TRUE; //LCOV_EXCL_LINE
385         }
386
387         return_parameters = g_variant_new("(iaa{sv})", STC_ERROR_NONE, builder);
388         g_variant_builder_unref(builder);
389
390         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
391         STC_DBUS_REPLY(invocation, return_parameters);
392         __STC_LOG_FUNC_EXIT__;
393         return TRUE;
394 }
395
396 gboolean handle_restriction_get_type(StcRestriction *object,
397                                       GDBusMethodInvocation *invocation,
398                                       const gchar *app_id,
399                                       int iftype,
400                                       void *user_data)
401 {
402         __STC_LOG_FUNC_ENTER__;
403         GVariant *return_parameters = NULL;
404         stc_rstn_type_e type = STC_RSTN_TYPE_UNKNOWN;
405         stc_error_e ret;
406
407         ret = table_restrictions_get_restriction_type(app_id, iftype, &type);
408         if (ret < STC_ERROR_NONE) {
409                 STC_RESTRICTION_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
410                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
411                 return TRUE;
412         }
413
414         return_parameters = g_variant_new("(ii)", STC_ERROR_NONE, type);
415         STC_DBUS_REPLY(invocation, return_parameters);
416         __STC_LOG_FUNC_EXIT__;
417         return TRUE;
418 }