Add tethering client data limitation
[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 = -1;
50         rule->data_warn_limit = -1;
51         rule->monthly_limit = -1;
52         rule->weekly_limit = -1;
53         rule->daily_limit = -1;
54         rule->roaming = STC_ROAMING_DISABLE;
55         rule->subscriber_id = NULL;
56 }
57
58 gboolean __validate_rstn_rule(table_restrictions_info *rule)
59 {
60         __STC_LOG_FUNC_ENTER__;
61
62         if (rule == NULL) {
63                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
64                 return FALSE; //LCOV_EXCL_LINE
65         }
66
67         if (rule->iftype <= STC_IFACE_UNKNOWN ||
68             rule->iftype >= STC_IFACE_LAST_ELEM) {
69                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
70                 return FALSE; //LCOV_EXCL_LINE
71         }
72
73         if (rule->roaming >= STC_ROAMING_LAST_ELEM) {
74                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
75                 return FALSE; //LCOV_EXCL_LINE
76         }
77
78         if (rule->subscriber_id == NULL) {
79                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
80                 return FALSE; //LCOV_EXCL_LINE
81         }
82
83         if (rule->app_id == NULL) {
84                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
85                 return FALSE; //LCOV_EXCL_LINE
86         }
87
88         __STC_LOG_FUNC_EXIT__;
89         return TRUE;
90 }
91
92 void __stc_restriction_app_info_builder_add(GVariantBuilder *builder,
93                                             const table_restrictions_info *info)
94 {
95         __STC_LOG_FUNC_ENTER__;
96
97         if (!builder || !info) {
98                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
99                 return; //LCOV_EXCL_LINE
100         }
101
102         g_variant_builder_add(builder, "{sv}", "app_id",
103                               g_variant_new_string(info->app_id));
104
105         g_variant_builder_add(builder, "{sv}", "ifname",
106                               g_variant_new_string(info->ifname));
107
108         g_variant_builder_add(builder, "{sv}", "iftype",
109                               g_variant_new_uint16(info->iftype));
110
111         g_variant_builder_add(builder, "{sv}", "rstn_type",
112                               g_variant_new_uint16(info->rstn_type));
113
114         g_variant_builder_add(builder, "{sv}", "data_limit",
115                               g_variant_new_int64(info->data_limit));
116
117         g_variant_builder_add(builder, "{sv}", "data_warn_limit",
118                               g_variant_new_int64(info->data_warn_limit));
119
120         g_variant_builder_add(builder, "{sv}", "month_start_date",
121                               g_variant_new_int32(info->month_start_date));
122
123         g_variant_builder_add(builder, "{sv}", "monthly_limit",
124                               g_variant_new_int64(info->monthly_limit));
125
126         g_variant_builder_add(builder, "{sv}", "weekly_limit",
127                               g_variant_new_int64(info->weekly_limit));
128
129         g_variant_builder_add(builder, "{sv}", "daily_limit",
130                               g_variant_new_int64(info->daily_limit));
131
132         g_variant_builder_add(builder, "{sv}", "roaming",
133                               g_variant_new_uint16(info->roaming));
134
135         g_variant_builder_add(builder, "{sv}", "subscriber_id",
136                               g_variant_new_string(info->subscriber_id));
137
138         __STC_LOG_FUNC_EXIT__;
139 }
140
141 stc_cb_ret_e __table_restrictions_foreach_app_cb(const table_restrictions_info *info,
142                                                  void *user_data)
143 {
144         __STC_LOG_FUNC_ENTER__;
145         GVariantBuilder *builder = (GVariantBuilder *)user_data;
146         GVariantBuilder sub_builder;
147
148         if (!info || !builder) {
149                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
150                 return STC_CANCEL; //LCOV_EXCL_LINE
151         }
152
153         g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
154         __stc_restriction_app_info_builder_add(&sub_builder, info);
155
156         g_variant_builder_add_value(builder,
157                                     g_variant_builder_end(&sub_builder));
158
159         __STC_LOG_FUNC_EXIT__;
160         return STC_CONTINUE;
161 }
162
163 stc_cb_ret_e __table_restrictions_per_app_cb(const table_restrictions_info *info,
164                                              void *user_data)
165 {
166         __STC_LOG_FUNC_ENTER__;
167         GVariantBuilder *builder = (GVariantBuilder *)user_data;
168
169         if (!info || !builder) {
170                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
171                 return STC_CANCEL; //LCOV_EXCL_LINE
172         }
173
174         __stc_restriction_app_info_builder_add(builder, info);
175
176         __STC_LOG_FUNC_EXIT__;
177         return STC_CONTINUE;
178 }
179
180 static void __stc_extract_restriction_rule(const char *key, GVariant *value,
181                                            void *user_data)
182 {
183         table_restrictions_info *rule =
184                 (table_restrictions_info *) user_data;
185         if (rule == NULL) {
186                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
187                 return; //LCOV_EXCL_LINE
188         }
189
190         if (!g_strcmp0(key, "app_id")) {
191                 guint str_length;
192                 const gchar *str = g_variant_get_string(value, &str_length);
193                 rule->app_id = g_strdup(str);
194                 STC_LOGD("app_id: [%s]", rule->app_id);
195
196         } else if (!g_strcmp0(key, "ifname")) {
197                 guint str_length;
198                 const gchar *str = g_variant_get_string(value, &str_length);
199                 rule->ifname = g_strdup(str);
200                 STC_LOGD("ifname: [%s]", rule->ifname);
201
202         } else if (!g_strcmp0(key, "iftype")) {
203                 rule->iftype = g_variant_get_uint16(value);
204                 STC_LOGD("iftype: [%u]", (unsigned int) rule->iftype);
205
206         } else if (!g_strcmp0(key, "data_limit")) {
207                 rule->data_limit = g_variant_get_int64(value);
208                 STC_LOGD("data_limit: [%lld]", rule->data_limit);
209
210         } else if (!g_strcmp0(key, "data_warn_limit")) {
211                 rule->data_warn_limit = g_variant_get_int64(value);
212                 STC_LOGD("data_warn_limit: [%lld]", rule->data_warn_limit);
213
214         } else if (!g_strcmp0(key, "month_start_date")) {
215                 rule->month_start_date = g_variant_get_int32(value);
216                 STC_LOGD("month_start_date: [%d]", rule->month_start_date);
217
218         } else if (!g_strcmp0(key, "monthly_limit")) {
219                 rule->monthly_limit = g_variant_get_int64(value);
220                 STC_LOGD("monthly_limit: [%lld]", rule->monthly_limit);
221
222         } else if (!g_strcmp0(key, "weekly_limit")) {
223                 rule->weekly_limit = g_variant_get_int64(value);
224                 STC_LOGD("weekly_limit: [%lld]", rule->weekly_limit);
225
226         } else if (!g_strcmp0(key, "daily_limit")) {
227                 rule->daily_limit = g_variant_get_int64(value);
228                 STC_LOGD("daily_limit: [%lld]", rule->daily_limit);
229
230         } else if (!g_strcmp0(key, "roaming")) {
231                 rule->roaming = g_variant_get_uint16(value);
232                 STC_LOGD("roaming: [%u]", rule->roaming);
233
234         } else if (!g_strcmp0(key, "subscriber_id")) {
235                 guint str_length;
236                 const gchar *str = g_variant_get_string(value, &str_length);
237                 rule->subscriber_id = g_strdup(str);
238                 STC_LOGD("subscriber_id: [%s]", rule->subscriber_id);
239
240         } else if (!g_strcmp0(key, "rstn_type")) {
241                 rule->rstn_type = g_variant_get_uint16(value);
242                 STC_LOGD("type: [%u]", (unsigned int) rule->rstn_type);
243
244         } else if (!g_strcmp0(key, "mac")) {
245                 guint str_length;
246                 const gchar *str = g_variant_get_string(value, &str_length);
247                 rule->mac = g_strdup(str);
248                 STC_LOGD("mac: [%s]", rule->mac);
249
250         } else {
251                 STC_LOGD("Unknown select rule"); //LCOV_EXCL_LINE
252         }
253 }
254
255 gboolean handle_restriction_set(StcRestriction *object,
256                                 GDBusMethodInvocation *invocation,
257                                 GVariant *parameters,
258                                 void *user_data)
259 {
260         __STC_LOG_FUNC_ENTER__;
261         GVariantIter *iter = NULL;
262         table_restrictions_info rule;
263
264         memset(&rule, 0, sizeof(table_restrictions_info));
265         __initialize_rstn_rule(&rule);
266
267         g_variant_get(parameters, "a{sv}", &iter);
268         if (iter != NULL) {
269                 stc_manager_gdbus_dict_foreach(iter,
270                                                __stc_extract_restriction_rule,
271                                                &rule);
272                 g_variant_iter_free(iter);
273         }
274
275         if (__validate_rstn_rule(&rule) == FALSE) {
276                 STC_RESTRICTION_DBUS_REPLY_ERROR(invocation, //LCOV_EXCL_LINE
277                                                  STC_ERROR_INVALID_PARAMETER);
278                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
279                 return TRUE;
280         }
281
282         table_restrictions_update(&rule);
283         /* update restriction rule in runtime structure */
284         stc_monitor_rstns_tree_add(&rule);
285
286         STC_DBUS_REPLY_ERROR_NONE(invocation);
287         __STC_LOG_FUNC_EXIT__;
288         return TRUE;
289 }
290
291 gboolean handle_restriction_unset(StcRestriction *object,
292                                    GDBusMethodInvocation *invocation,
293                                    GVariant *parameters,
294                                    void *user_data)
295 {
296         __STC_LOG_FUNC_ENTER__;
297         GVariantIter *iter = NULL;
298         table_restrictions_info rule;
299
300         memset(&rule, 0, sizeof(table_restrictions_info));
301         __initialize_rstn_rule(&rule);
302
303         g_variant_get(parameters, "a{sv}", &iter);
304         if (iter != NULL) {
305                 stc_manager_gdbus_dict_foreach(iter,
306                                                __stc_extract_restriction_rule,
307                                                &rule);
308                 g_variant_iter_free(iter);
309         }
310
311         if (__validate_rstn_rule(&rule) == FALSE) {
312                 STC_RESTRICTION_DBUS_REPLY_ERROR(invocation, //LCOV_EXCL_LINE
313                                                  STC_ERROR_INVALID_PARAMETER);
314                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
315                 return TRUE;
316         }
317
318         table_restrictions_delete(rule.app_id, rule.iftype, rule.subscriber_id);
319         /* remove restriction rule from runtime structure */
320         stc_monitor_rstns_tree_remove(&rule);
321
322         STC_DBUS_REPLY_ERROR_NONE(invocation);
323         __STC_LOG_FUNC_EXIT__;
324         return TRUE;
325 }
326
327 gboolean handle_restriction_get(StcRestriction *object,
328                                 GDBusMethodInvocation *invocation,
329                                 const gchar *app_id,
330                                 void *user_data)
331 {
332         __STC_LOG_FUNC_ENTER__;
333         GVariantBuilder *builder = NULL;
334         GVariant *return_parameters = NULL;
335         stc_error_e ret;
336
337         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
338
339         ret = table_restrictions_per_app(app_id,
340                                          __table_restrictions_per_app_cb,
341                                          builder);
342         if (ret < STC_ERROR_NONE) {
343                 g_variant_builder_unref(builder); //LCOV_EXCL_LINE
344                 STC_RESTRICTION_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
345                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
346                 return TRUE; //LCOV_EXCL_LINE
347         }
348
349         return_parameters = g_variant_new("(ia{sv})", STC_ERROR_NONE, builder);
350         g_variant_builder_unref(builder);
351
352         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
353         STC_DBUS_REPLY(invocation, return_parameters);
354         __STC_LOG_FUNC_EXIT__;
355         return TRUE;
356 }
357
358 gboolean handle_restriction_get_all(StcRestriction *object,
359                                     GDBusMethodInvocation *invocation,
360                                     void *user_data)
361 {
362         __STC_LOG_FUNC_ENTER__;
363         GVariantBuilder *builder = NULL;
364         GVariant *return_parameters = NULL;
365         stc_error_e ret;
366
367         builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
368
369         ret = table_restrictions_foreach(__table_restrictions_foreach_app_cb,
370                                          builder);
371         if (ret < STC_ERROR_NONE) {
372                 g_variant_builder_unref(builder); //LCOV_EXCL_LINE
373                 STC_RESTRICTION_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
374                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
375                 return TRUE; //LCOV_EXCL_LINE
376         }
377
378         return_parameters = g_variant_new("(iaa{sv})", STC_ERROR_NONE, builder);
379         g_variant_builder_unref(builder);
380
381         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
382         STC_DBUS_REPLY(invocation, return_parameters);
383         __STC_LOG_FUNC_EXIT__;
384         return TRUE;
385 }
386
387 gboolean handle_restriction_get_type(StcRestriction *object,
388                                       GDBusMethodInvocation *invocation,
389                                       const gchar *app_id,
390                                       int iftype,
391                                       void *user_data)
392 {
393         __STC_LOG_FUNC_ENTER__;
394         GVariant *return_parameters = NULL;
395         stc_rstn_type_e type = STC_RSTN_TYPE_UNKNOWN;
396         stc_error_e ret;
397
398         ret = table_restrictions_get_restriction_type(app_id, iftype, &type);
399         if (ret < STC_ERROR_NONE) {
400                 STC_RESTRICTION_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
401                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
402                 return TRUE;
403         }
404
405         return_parameters = g_variant_new("(ii)", STC_ERROR_NONE, type);
406         STC_DBUS_REPLY(invocation, return_parameters);
407         __STC_LOG_FUNC_EXIT__;
408         return TRUE;
409 }