236169b8884c0df73105d5a11e29cef801c0627b
[platform/core/connectivity/stc-manager.git] / src / stc-firewall.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-firewall.h"
19 #include "helper-firewall.h"
20 #include "stc-firewall.h"
21 #include "stc-manager-gdbus.h"
22
23 #define IDENTIFIER_LEN     512
24
25 #define LOCK_NAME          "admin"
26
27 #define CHAIN_NAME         "chain"
28 #define CHAIN_TARGET       "target"
29 #define CHAIN_PRIORITY     "priority"
30
31 #define RULE_CHAIN         "chain"
32 #define RULE_DIRECTION     "direction"
33 #define RULE_SIPTYPE       "s_ip_type"
34 #define RULE_DIPTYPE       "d_ip_type"
35 #define RULE_SPORTTYPE     "s_port_type"
36 #define RULE_DPORTTYPE     "d_port_type"
37 #define RULE_PROTOCOL      "protocol"
38 #define RULE_FAMILY        "family"
39 #define RULE_SIP1          "s_ip1"
40 #define RULE_SIP2          "s_ip2"
41 #define RULE_DIP1          "d_ip1"
42 #define RULE_DIP2          "d_ip2"
43 #define RULE_SPORT1        "s_port1"
44 #define RULE_SPORT2        "s_port2"
45 #define RULE_DPORT1        "d_port1"
46 #define RULE_DPORT2        "d_port2"
47 #define RULE_IFNAME        "ifname"
48 #define RULE_TARGET        "target"
49 #define RULE_IDENTIFIER    "identifier"
50 #define RULE_KEY           "key"
51
52 #define RULE_TARGET_ACCEPT "ACCEPT"
53 #define RULE_TARGET_DROP   "DROP"
54 #define RULE_TARGET_LOG    "LOG"
55
56 #define FIREWALL_DBUS_ERROR_NAME "net.stc.firewall.Error.Failed"
57
58 #define STC_FIREWALL_DBUS_REPLY_ERROR(invocation, err_num) \
59         g_dbus_method_invocation_return_dbus_error((invocation), \
60                                                    FIREWALL_DBUS_ERROR_NAME, \
61                                                    stc_err_strs[-(err_num)])
62
63 #define STC_FIREWALL_CHECK_LOCK_STATE(invocation) do { \
64         if (g_lock_state == FIREWALL_LOCKED) { \
65                 STC_LOGD("Firewall is locked");  \
66                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, \
67                                                 STC_ERROR_PERMISSION_DENIED); \
68                 __STC_LOG_FUNC_EXIT__; \
69                 return TRUE; \
70         } \
71 } while (0)
72
73 static const gchar *stc_err_strs[] = {
74         "ERROR_NONE",
75         "FAIL",
76         "DB_FAILED",
77         "OUT_OF_MEMORY",
78         "INVALID_PARAMETER",
79         "NO_DATA",
80         "ALREADY_DATA",
81         "UNINITIALIZED",
82         "PERMISSION_DENIED",
83         "NOTIMPL"
84 };
85
86 static GHashTable *g_firewalls = NULL;
87 static int g_lock_state = FIREWALL_UNKONWN;
88 static uint g_chain_priority = 0;
89
90 static void __fw_rule_copy(firewall_rule_s *rule,
91                                 const firewall_rule_s *info)
92 {
93         if (info->chain) {
94                 FREE(rule->chain);
95                 rule->chain = g_strdup(info->chain);
96         }
97
98         rule->direction = info->direction;
99         rule->s_ip_type = info->s_ip_type;
100         rule->d_ip_type = info->d_ip_type;
101         rule->s_port_type = info->s_port_type;
102         rule->d_port_type = info->d_port_type;
103         rule->protocol = info->protocol;
104         rule->family = info->family;
105
106         rule->s_ip1 = info->s_ip1;
107         rule->s_ip2 = info->s_ip2;
108         rule->d_ip1 = info->d_ip1;
109         rule->d_ip2 = info->d_ip2;
110
111         rule->s_port1 = info->s_port1;
112         rule->s_port2 = info->s_port2;
113         rule->d_port1 = info->d_port1;
114         rule->d_port2 = info->d_port2;
115
116         if (info->ifname) {
117                 FREE(rule->ifname);
118                 rule->ifname = g_strdup(info->ifname);
119         }
120
121         rule->target = info->target;
122
123         if (info->target_str) {
124                 FREE(rule->target_str);
125                 rule->target_str = g_strdup(info->target_str);
126         }
127
128         if (info->identifier) {
129                 FREE(rule->identifier);
130                 rule->identifier = g_strdup(info->identifier);
131         }
132
133         rule->key = info->key;
134 }
135
136 static void __fw_rule_make_key(firewall_rule_s *rule,
137                                 firewall_rule_s *info)
138 {
139         GString *str;
140
141         if (!rule->chain)
142                 return;
143
144         str = g_string_sized_new(IDENTIFIER_LEN);
145         if (!str)
146                 return;
147
148         g_string_append_printf(str, "%s", rule->chain);
149
150         g_string_append_printf(str, "_%u%u%u%u%u%u%u", rule->direction,
151                 rule->s_ip_type, rule->d_ip_type, rule->s_port_type,
152                 rule->d_port_type, rule->protocol, rule->family);
153
154         if (rule->family == STC_FW_FAMILY_V4) {
155                 g_string_append_printf(str, "_");
156                 g_string_append_printf(str, "%08x", rule->s_ip1.Ipv4.s_addr);
157                 g_string_append_printf(str, "%08x", rule->s_ip2.Ipv4.s_addr);
158
159                 g_string_append_printf(str, "_");
160                 g_string_append_printf(str, "%08x", rule->d_ip1.Ipv4.s_addr);
161                 g_string_append_printf(str, "%08x", rule->d_ip2.Ipv4.s_addr);
162         } else if (rule->family == STC_FW_FAMILY_V6) {
163                 g_string_append_printf(str, "_");
164                 g_string_append_printf(str, "%08x", rule->s_ip1.Ipv6.s6_addr32[0]);
165                 g_string_append_printf(str, "%08x", rule->s_ip1.Ipv6.s6_addr32[1]);
166                 g_string_append_printf(str, "%08x", rule->s_ip1.Ipv6.s6_addr32[2]);
167                 g_string_append_printf(str, "%08x", rule->s_ip1.Ipv6.s6_addr32[3]);
168                 g_string_append_printf(str, "%08x", rule->s_ip2.Ipv6.s6_addr32[0]);
169                 g_string_append_printf(str, "%08x", rule->s_ip2.Ipv6.s6_addr32[1]);
170                 g_string_append_printf(str, "%08x", rule->s_ip2.Ipv6.s6_addr32[2]);
171                 g_string_append_printf(str, "%08x", rule->s_ip2.Ipv6.s6_addr32[3]);
172
173                 g_string_append_printf(str, "_");
174                 g_string_append_printf(str, "%08x", rule->d_ip1.Ipv6.s6_addr32[0]);
175                 g_string_append_printf(str, "%08x", rule->d_ip1.Ipv6.s6_addr32[1]);
176                 g_string_append_printf(str, "%08x", rule->d_ip1.Ipv6.s6_addr32[2]);
177                 g_string_append_printf(str, "%08x", rule->d_ip1.Ipv6.s6_addr32[3]);
178                 g_string_append_printf(str, "%08x", rule->d_ip2.Ipv6.s6_addr32[0]);
179                 g_string_append_printf(str, "%08x", rule->d_ip2.Ipv6.s6_addr32[1]);
180                 g_string_append_printf(str, "%08x", rule->d_ip2.Ipv6.s6_addr32[2]);
181                 g_string_append_printf(str, "%08x", rule->d_ip2.Ipv6.s6_addr32[3]);
182         }
183
184         g_string_append_printf(str, "_%04x", rule->s_port1);
185         g_string_append_printf(str, "%04x", rule->s_port2);
186
187         g_string_append_printf(str, "_%04x", rule->d_port1);
188         g_string_append_printf(str, "%04x", rule->d_port2);
189
190         g_string_append_printf(str, "_%s", (rule->ifname) ? rule->ifname : "");
191         g_string_append_printf(str, "_%u", rule->target);
192
193         rule->identifier = g_string_free(str, FALSE);
194         rule->key = g_str_hash(rule->identifier);
195
196         info->identifier = g_strdup(rule->identifier);
197         info->key = rule->key;
198
199         STC_LOGD("Identifier [%s]", rule->identifier);
200         STC_LOGD("Key [%u]", rule->key);
201 }
202
203 static void __fw_rule_free(void *data)
204 {
205         firewall_rule_s *rule = (firewall_rule_s *)data;
206
207         FREE(rule->chain);
208         FREE(rule->ifname);
209         FREE(rule->identifier);
210         FREE(rule);
211 }
212
213 static void __fw_data_free(gpointer value)
214 {
215         stc_fw_data_s *data = (stc_fw_data_s *)value;
216
217         g_slist_free_full(data->rules, __fw_rule_free);
218         data->rules = NULL;
219
220         FREE(data);
221 }
222
223 static gint __fw_rule_comp(gconstpointer a, gconstpointer b)
224 {
225         firewall_rule_s *data = (firewall_rule_s *)a;
226         firewall_rule_s *rule = (firewall_rule_s *)b;
227
228         if ((data->key == rule->key) &&
229                 (g_strcmp0(data->identifier, rule->identifier) == 0))
230                 return 0;
231
232         return -1;
233 }
234
235 static stc_error_e __fw_chain_add(const char *chain)
236 {
237         stc_fw_data_s *data;
238         stc_fw_data_s *lookup;
239
240         ret_value_msg_if(g_firewalls == NULL,
241                 STC_ERROR_FAIL,
242                 "firewall is not initialized!");
243
244         lookup = g_hash_table_lookup(g_firewalls, chain);
245         if (lookup) {
246                 STC_LOGD("chain already present");
247                 return STC_ERROR_ALREADY_DATA;
248         }
249
250         data = MALLOC0(stc_fw_data_s, 1);
251         if (!data) {
252                 STC_LOGE("data allocation failed");
253                 return STC_ERROR_OUT_OF_MEMORY;
254         }
255
256         data->target = STC_FW_CHAIN_TARGET_NONE;
257         data->priority = 0;
258         data->rules = NULL;
259
260         g_hash_table_insert(g_firewalls, g_strdup(chain), data);
261
262         return STC_ERROR_NONE;
263 }
264
265 static stc_error_e __fw_chain_remove(const char *chain)
266 {
267         stc_fw_data_s *lookup;
268
269         ret_value_msg_if(g_firewalls == NULL,
270                 STC_ERROR_FAIL,
271                 "firewall is not initialized!");
272
273         lookup = g_hash_table_lookup(g_firewalls, chain);
274         if (!lookup) {
275                 STC_LOGE("chain not found");
276                 return STC_ERROR_NO_DATA;
277         }
278
279         if (lookup->target != STC_FW_CHAIN_TARGET_NONE) {
280                 STC_LOGE("can't be applied bcz chain is set");
281                 return STC_ERROR_INVALID_PARAMETER;
282         }
283
284         g_slist_free_full(lookup->rules, __fw_rule_free);
285         lookup->rules = NULL;
286
287         g_hash_table_remove(g_firewalls, chain);
288
289         return STC_ERROR_NONE;
290 }
291
292 static stc_error_e __fw_chain_flush(const char *chain)
293 {
294         stc_fw_data_s *lookup;
295
296         ret_value_msg_if(g_firewalls == NULL,
297                 STC_ERROR_FAIL,
298                 "firewall is not initialized!");
299
300         lookup = g_hash_table_lookup(g_firewalls, chain);
301         if (!lookup) {
302                 STC_LOGE("chain not found");
303                 return STC_ERROR_NO_DATA;
304         }
305
306         if (lookup->target != STC_FW_CHAIN_TARGET_NONE) {
307                 STC_LOGE("can't be applied bcz chain is set");
308                 return STC_ERROR_INVALID_PARAMETER;
309         }
310
311         g_slist_free_full(lookup->rules, __fw_rule_free);
312         lookup->rules = NULL;
313
314         return STC_ERROR_NONE;
315 }
316
317 static stc_error_e __fw_chain_set(const char *chain, stc_fw_data_s value)
318 {
319         stc_fw_data_s *lookup;
320
321         ret_value_msg_if(g_firewalls == NULL,
322                 STC_ERROR_FAIL,
323                 "firewall is not initialized!");
324
325         lookup = g_hash_table_lookup(g_firewalls, chain);
326         if (!lookup) {
327                 STC_LOGE("chain not found");
328                 return STC_ERROR_NO_DATA;
329         }
330
331         lookup->target = value.target;
332         lookup->priority = value.priority;
333
334         return STC_ERROR_NONE;
335 }
336
337 static stc_fw_data_s *__fw_chain_get(const char *chain)
338 {
339         stc_fw_data_s *lookup;
340
341         ret_value_msg_if(g_firewalls == NULL, NULL,
342                 "firewall is not initialized!");
343
344         lookup = g_hash_table_lookup(g_firewalls, chain);
345         if (!lookup) {
346                 STC_LOGE("chain not found");
347                 return NULL;
348         }
349
350         return lookup;
351 }
352
353 static stc_error_e __fw_chain_unset(const char *chain)
354 {
355         stc_error_e ret = STC_ERROR_NONE;
356         stc_fw_data_s *lookup;
357
358         ret_value_msg_if(g_firewalls == NULL,
359                 STC_ERROR_FAIL,
360                 "firewall is not initialized!");
361
362         lookup = g_hash_table_lookup(g_firewalls, chain);
363         if (!lookup) {
364                 STC_LOGE("chain not found");
365                 return STC_ERROR_NO_DATA;
366         }
367
368         lookup->target = STC_FW_CHAIN_TARGET_NONE;
369         lookup->priority = 0;
370
371         return ret;
372 }
373
374 static void __fw_chain_make_params(gpointer key, gpointer value,
375                                 gpointer user_data)
376 {
377         char *chain = (char *)key;
378         stc_fw_data_s *data = (stc_fw_data_s *)value;
379         GVariantBuilder *builder = (GVariantBuilder *)user_data;
380         GVariantBuilder sub_builder;
381
382         g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
383
384         g_variant_builder_add(&sub_builder, "{sv}", CHAIN_NAME,
385                                         g_variant_new_string(chain));
386
387         g_variant_builder_add(&sub_builder, "{sv}", CHAIN_PRIORITY,
388                                 g_variant_new_uint32(data->priority));
389
390         g_variant_builder_add(&sub_builder, "{sv}", CHAIN_TARGET,
391                                 g_variant_new_uint16(data->target));
392
393         g_variant_builder_add_value(builder, g_variant_builder_end(&sub_builder));
394 }
395
396 static void __fw_rule_make_params(gpointer data, gpointer user_data)
397 {
398         firewall_rule_s *rule = (firewall_rule_s *)data;
399         GVariantBuilder *builder = (GVariantBuilder *)user_data;
400         GVariantBuilder sub_builder;
401
402         g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
403
404         g_variant_builder_add(&sub_builder, "{sv}", RULE_CHAIN,
405                                         g_variant_new_string(rule->chain));
406
407         if (rule->direction != STC_FW_DIRECTION_NONE)
408                 g_variant_builder_add(&sub_builder, "{sv}", RULE_DIRECTION,
409                                         g_variant_new_uint16(rule->direction));
410
411         if (rule->s_ip_type != STC_FW_IP_NONE)
412                 g_variant_builder_add(&sub_builder, "{sv}", RULE_SIPTYPE,
413                                         g_variant_new_uint16(rule->s_ip_type));
414
415         if (rule->d_ip_type != STC_FW_IP_NONE)
416                 g_variant_builder_add(&sub_builder, "{sv}", RULE_DIPTYPE,
417                                         g_variant_new_uint16(rule->d_ip_type));
418
419         if (rule->s_port_type != STC_FW_PORT_NONE)
420                 g_variant_builder_add(&sub_builder, "{sv}", RULE_SPORTTYPE,
421                                         g_variant_new_uint16(rule->s_port_type));
422
423         if (rule->d_port_type != STC_FW_PORT_NONE)
424                 g_variant_builder_add(&sub_builder, "{sv}", RULE_DPORTTYPE,
425                                         g_variant_new_uint16(rule->d_port_type));
426
427         if (rule->protocol != STC_FW_PROTOCOL_NONE)
428                 g_variant_builder_add(&sub_builder, "{sv}", RULE_PROTOCOL,
429                                         g_variant_new_uint16(rule->protocol));
430
431         if (rule->family != STC_FW_FAMILY_NONE)
432                 g_variant_builder_add(&sub_builder, "{sv}", RULE_FAMILY,
433                                         g_variant_new_uint16(rule->family));
434
435         if (rule->family == STC_FW_FAMILY_V4) {
436                 char *addr = NULL;
437
438                 switch (rule->s_ip_type) {
439                 case STC_FW_IP_RANGE:
440                 case STC_FW_IP_MASK:
441                         addr = g_try_malloc0(INET_ADDRSTRLEN);
442                         if (addr) {
443                                 inet_ntop(AF_INET, &(rule->s_ip2.Ipv4), addr, INET_ADDRSTRLEN);
444                                 g_variant_builder_add(&sub_builder, "{sv}", RULE_SIP2,
445                                                         g_variant_new_string(addr));
446                                 FREE(addr);
447                         }
448                 case STC_FW_IP_SINGLE:
449                         addr = g_try_malloc0(INET_ADDRSTRLEN);
450                         if (addr) {
451                                 inet_ntop(AF_INET, &(rule->s_ip1.Ipv4), addr, INET_ADDRSTRLEN);
452                                 g_variant_builder_add(&sub_builder, "{sv}", RULE_SIP1,
453                                                         g_variant_new_string(addr));
454                                 FREE(addr);
455                         }
456                         break;
457                 default:
458                         break;
459                 }
460
461                 switch (rule->d_ip_type) {
462                 case STC_FW_IP_RANGE:
463                 case STC_FW_IP_MASK:
464                         addr = g_try_malloc0(INET_ADDRSTRLEN);
465                         if (addr) {
466                                 inet_ntop(AF_INET, &(rule->d_ip2.Ipv4), addr, INET_ADDRSTRLEN);
467                                 g_variant_builder_add(&sub_builder, "{sv}", RULE_DIP2,
468                                                         g_variant_new_string(addr));
469                                 FREE(addr);
470                         }
471                 case STC_FW_IP_SINGLE:
472                         addr = g_try_malloc0(INET_ADDRSTRLEN);
473                         if (addr) {
474                                 inet_ntop(AF_INET, &(rule->d_ip1.Ipv4), addr, INET_ADDRSTRLEN);
475                                 g_variant_builder_add(&sub_builder, "{sv}", RULE_DIP1,
476                                                         g_variant_new_string(addr));
477                                 FREE(addr);
478                         }
479                         break;
480                 default:
481                         break;
482                 }
483         } else if (rule->family == STC_FW_FAMILY_V6) {
484                 char *addr = NULL;
485
486                 switch (rule->s_ip_type) {
487                 case STC_FW_IP_RANGE:
488                 case STC_FW_IP_MASK:
489                         addr = g_try_malloc0(INET6_ADDRSTRLEN);
490                         if (addr) {
491                                 inet_ntop(AF_INET6, &(rule->s_ip2.Ipv6), addr, INET6_ADDRSTRLEN);
492                                 g_variant_builder_add(&sub_builder, "{sv}", RULE_SIP2,
493                                                         g_variant_new_string(addr));
494                                 FREE(addr);
495                         }
496                 case STC_FW_IP_SINGLE:
497                         addr = g_try_malloc0(INET6_ADDRSTRLEN);
498                         if (addr) {
499                                 inet_ntop(AF_INET6, &(rule->s_ip1.Ipv6), addr, INET6_ADDRSTRLEN);
500                                 g_variant_builder_add(&sub_builder, "{sv}", RULE_SIP1,
501                                                         g_variant_new_string(addr));
502                                 FREE(addr);
503                         }
504                         break;
505                 default:
506                         break;
507                 }
508
509                 switch (rule->d_ip_type) {
510                 case STC_FW_IP_RANGE:
511                 case STC_FW_IP_MASK:
512                         addr = g_try_malloc0(INET6_ADDRSTRLEN);
513                         if (addr) {
514                                 inet_ntop(AF_INET6, &(rule->d_ip2.Ipv6), addr, INET6_ADDRSTRLEN);
515                                 g_variant_builder_add(&sub_builder, "{sv}", RULE_DIP2,
516                                                         g_variant_new_string(addr));
517                                 FREE(addr);
518                         }
519                 case STC_FW_IP_SINGLE:
520                         addr = g_try_malloc0(INET6_ADDRSTRLEN);
521                         if (addr) {
522                                 inet_ntop(AF_INET6, &(rule->d_ip1.Ipv6), addr, INET6_ADDRSTRLEN);
523                                 g_variant_builder_add(&sub_builder, "{sv}", RULE_DIP1,
524                                                         g_variant_new_string(addr));
525                                 FREE(addr);
526                         }
527                         break;
528                 default:
529                         break;
530                 }
531         }
532
533         g_variant_builder_add(&sub_builder, "{sv}", RULE_SPORT1,
534                                 g_variant_new_uint32(rule->s_port1));
535
536         g_variant_builder_add(&sub_builder, "{sv}", RULE_SPORT2,
537                                 g_variant_new_uint32(rule->s_port2));
538
539         g_variant_builder_add(&sub_builder, "{sv}", RULE_DPORT1,
540                                 g_variant_new_uint32(rule->d_port1));
541
542         g_variant_builder_add(&sub_builder, "{sv}", RULE_DPORT2,
543                                 g_variant_new_uint32(rule->d_port2));
544
545         if (rule->ifname)
546                 g_variant_builder_add(&sub_builder, "{sv}", RULE_IFNAME,
547                                         g_variant_new_string(rule->ifname));
548
549         if (rule->target != STC_FW_RULE_TARGET_NONE)
550                 g_variant_builder_add(&sub_builder, "{sv}", RULE_TARGET,
551                                         g_variant_new_uint16(rule->target));
552
553         g_variant_builder_add(&sub_builder, "{sv}", RULE_IDENTIFIER,
554                                 g_variant_new_string(rule->identifier));
555
556         g_variant_builder_add(&sub_builder, "{sv}", RULE_KEY,
557                                 g_variant_new_uint32(rule->key));
558
559         g_variant_builder_add_value(builder, g_variant_builder_end(&sub_builder));
560 }
561
562 static void __fw_rule_set_to_chain(gpointer data, gpointer user_data)
563 {
564         firewall_rule_s *info = (firewall_rule_s *)data;
565         char *chain = (char *)user_data;
566         firewall_rule_s rule;
567
568         if (chain && (g_strcmp0(info->chain, chain) != 0))
569                 return;
570
571         memset(&rule, 0, sizeof(firewall_rule_s));
572         memcpy(&rule, info, sizeof(firewall_rule_s));
573         rule.chain = g_strdup(info->chain);
574         rule.ifname = g_strdup(info->ifname);
575         switch (rule.target) {
576         case STC_FW_RULE_TARGET_ACCEPT:
577                 rule.target_str = g_strdup(FIREWALL_RULE_TARGET_ACCEPT);
578                 break;
579         case STC_FW_RULE_TARGET_DROP:
580                 rule.target_str = g_strdup(FIREWALL_RULE_TARGET_DROP);
581                 break;
582         case STC_FW_RULE_TARGET_LOG:
583                 rule.target_str = g_strdup(FIREWALL_RULE_TARGET_LOG);
584                 break;
585         default:
586                 break;
587         }
588
589         firewall_rule_add(&rule);
590
591         FREE(rule.chain);
592         FREE(rule.ifname);
593         FREE(rule.target_str);
594 }
595
596 static void __fw_foreach_to_make_rule_param(gpointer key, gpointer value,
597                                 gpointer user_data)
598 {
599         stc_fw_data_s *data = (stc_fw_data_s *)value;
600
601         g_slist_foreach(data->rules, __fw_rule_make_params, user_data);
602 }
603
604 static void __fw_foreach_to_set_rule_to_chain(gpointer key, gpointer value,
605                                 gpointer user_data)
606 {
607         stc_fw_data_s *data = (stc_fw_data_s *)value;
608         char *chain = (char *)user_data;
609
610         if (chain || (data->target != STC_FW_CHAIN_TARGET_NONE))
611                 g_slist_foreach(data->rules, __fw_rule_set_to_chain, user_data);
612 }
613
614 static void __fw_foreach_to_set_chain(gpointer key, gpointer value,
615                                 gpointer user_data)
616 {
617         char *chain = (char *)key;
618         stc_fw_data_s *data = (stc_fw_data_s *)value;
619
620         if (data->target != STC_FW_CHAIN_TARGET_NONE) {
621                 firewall_chain_s info;
622                 memset(&info, 0, sizeof(firewall_chain_s));
623                 info.chain = chain;
624                 info.target = data->target;
625                 info.priority = data->priority;
626                 firewall_chain_set(&info);
627         }
628 }
629
630 static void __fw_foreach_to_add_chain(gpointer key, gpointer value,
631                                 gpointer user_data)
632 {
633         char *chain = (char *)key;
634         stc_fw_data_s *data = (stc_fw_data_s *)value;
635
636         if (data->target != STC_FW_CHAIN_TARGET_NONE) {
637                 firewall_chain_s info;
638                 memset(&info, 0, sizeof(firewall_chain_s));
639                 info.chain = chain;
640                 info.target = data->target;
641                 info.priority = data->priority;
642                 firewall_chain_add(&info);
643         }
644 }
645
646 static void __fw_chain_foreach(GHFunc func, void *user_data)
647 {
648         g_hash_table_foreach(g_firewalls, func, user_data);
649 }
650
651 stc_cb_ret_e __fw_table_chain_info_cb(const firewall_chain_s *info,
652                                 void *user_data)
653 {
654         stc_fw_data_s *data;
655
656         data = MALLOC0(stc_fw_data_s, 1);
657         if (!data) {
658                 STC_LOGE("data allocation failed");
659                 return STC_CONTINUE;
660         }
661
662         data->target = info->target;
663         data->priority = info->priority;
664         data->rules = NULL;
665
666         g_hash_table_insert(g_firewalls, g_strdup(info->chain), data);
667
668         return STC_CONTINUE;
669 }
670
671 stc_cb_ret_e __fw_table_rule_info_cb(const firewall_rule_s *info,
672                                 void *user_data)
673 {
674         stc_fw_data_s *lookup;
675         firewall_rule_s *rule;
676
677         lookup = g_hash_table_lookup(g_firewalls, info->chain);
678         if (!lookup) {
679                 STC_LOGE("chain not found");
680                 return STC_CONTINUE;
681         }
682
683         rule = MALLOC0(firewall_rule_s, 1);
684         if (!rule) {
685                 STC_LOGE("rule allocation failed");
686                 return STC_CONTINUE;
687         }
688
689         memset(rule, 0, sizeof(firewall_rule_s));
690         __fw_rule_copy(rule, info);
691
692         lookup->rules = g_slist_append(lookup->rules, rule);
693
694         return STC_CONTINUE;
695 }
696
697 static stc_error_e __fw_rule_add(firewall_rule_s *info)
698 {
699         stc_fw_data_s *lookup;
700         firewall_rule_s *rule;
701         GSList *comp;
702
703         ret_value_msg_if(g_firewalls == NULL,
704                 STC_ERROR_FAIL,
705                 "firewall is not initialized!");
706
707         lookup = g_hash_table_lookup(g_firewalls, info->chain);
708         if (!lookup) {
709                 STC_LOGE("chain not found");
710                 return STC_ERROR_NO_DATA;
711         }
712
713         if (lookup->target != STC_FW_CHAIN_TARGET_NONE) {
714                 STC_LOGE("can't be applied bcz chain is set");
715                 return STC_ERROR_INVALID_PARAMETER;
716         }
717
718         rule = MALLOC0(firewall_rule_s, 1);
719         if (!rule) {
720                 STC_LOGE("rule allocation failed");
721                 return STC_ERROR_OUT_OF_MEMORY;
722         }
723
724         memset(rule, 0, sizeof(firewall_rule_s));
725         __fw_rule_copy(rule, info);
726         __fw_rule_make_key(rule, info);
727
728         comp = g_slist_find_custom(lookup->rules, rule, __fw_rule_comp);
729         if (comp) {
730                 STC_LOGD("rule already present");
731                 return STC_ERROR_ALREADY_DATA;
732         }
733
734         lookup->rules = g_slist_append(lookup->rules, rule);
735
736         return STC_ERROR_NONE;
737 }
738
739 static stc_error_e __fw_rule_remove(const firewall_rule_s *info)
740 {
741         stc_fw_data_s *lookup;
742         GSList *rule_list;
743         GSList *comp;
744         firewall_rule_s *rule;
745
746         ret_value_msg_if(g_firewalls == NULL,
747                 STC_ERROR_FAIL,
748                 "firewall is not initialized!");
749
750         lookup = g_hash_table_lookup(g_firewalls, info->chain);
751         if (!lookup) {
752                 STC_LOGE("chain not found");
753                 return STC_ERROR_NO_DATA;
754         }
755
756         if (lookup->target != STC_FW_CHAIN_TARGET_NONE) {
757                 STC_LOGE("can't be applied bcz chain is set");
758                 return STC_ERROR_INVALID_PARAMETER;
759         }
760
761         rule_list = lookup->rules;
762         comp = g_slist_find_custom(rule_list, info, __fw_rule_comp);
763         if (!comp) {
764                 STC_LOGD("rule not found");
765                 return STC_ERROR_NO_DATA;
766         }
767
768         rule = comp->data;
769         lookup->rules = g_slist_remove(lookup->rules, rule);
770         __fw_rule_free(rule);
771
772         return STC_ERROR_NONE;
773 }
774
775 static stc_error_e __fw_rule_update(const firewall_rule_s *info)
776 {
777         stc_fw_data_s *lookup;
778         GSList *rule_list;
779         GSList *comp;
780         firewall_rule_s *rule;
781
782         ret_value_msg_if(g_firewalls == NULL,
783                 STC_ERROR_FAIL,
784                 "firewall is not initialized!");
785
786         lookup = g_hash_table_lookup(g_firewalls, info->chain);
787         if (!lookup) {
788                 STC_LOGE("chain not found");
789                 return STC_ERROR_NO_DATA;
790         }
791
792         if (lookup->target != STC_FW_CHAIN_TARGET_NONE) {
793                 STC_LOGE("can't be applied bcz chain is set");
794                 return STC_ERROR_INVALID_PARAMETER;
795         }
796
797         rule_list = lookup->rules;
798         comp = g_slist_find_custom(rule_list, info, __fw_rule_comp);
799         if (!comp) {
800                 STC_LOGD("rule not found");
801                 return STC_ERROR_NO_DATA;
802         }
803
804         rule = comp->data;
805         __fw_rule_copy(rule, info);
806
807         return STC_ERROR_NONE;
808 }
809
810 static void __fw_rule_extract(const char *key, GVariant *value,
811                         void *user_data)
812 {
813         __STC_LOG_FUNC_ENTER__;
814
815         firewall_rule_s *rule = (firewall_rule_s *)user_data;
816         if (rule == NULL) {
817                 __STC_LOG_FUNC_EXIT__;
818                 return;
819         }
820
821         if (g_strcmp0(key, RULE_CHAIN) == 0) {
822                 guint str_length;
823                 const gchar *str = g_variant_get_string(value, &str_length);
824                 rule->chain = g_strdup(str);
825                 STC_LOGD("%s: [%s]", RULE_CHAIN, rule->chain);
826
827         } else if (g_strcmp0(key, RULE_DIRECTION) == 0) {
828                 rule->direction = g_variant_get_uint16(value);
829                 STC_LOGD("%s: [%u]", RULE_DIRECTION, rule->direction);
830
831         } else if (g_strcmp0(key, RULE_SIPTYPE) == 0) {
832                 rule->s_ip_type = g_variant_get_uint16(value);
833                 STC_LOGD("%s: [%u]", RULE_SIPTYPE, rule->s_ip_type);
834
835         } else if (g_strcmp0(key, RULE_DIPTYPE) == 0) {
836                 rule->d_ip_type = g_variant_get_uint16(value);
837                 STC_LOGD("%s: [%u]", RULE_DIPTYPE, rule->d_ip_type);
838
839         } else if (g_strcmp0(key, RULE_SPORTTYPE) == 0) {
840                 rule->s_port_type = g_variant_get_uint16(value);
841                 STC_LOGD("%s: [%u]", RULE_SPORTTYPE, rule->s_port_type);
842
843         } else if (g_strcmp0(key, RULE_DPORTTYPE) == 0) {
844                 rule->d_port_type = g_variant_get_uint16(value);
845                 STC_LOGD("%s: [%u]", RULE_DPORTTYPE, rule->d_port_type);
846
847         } else if (g_strcmp0(key, RULE_PROTOCOL) == 0) {
848                 rule->protocol = g_variant_get_uint16(value);
849                 STC_LOGD("%s: [%u]", RULE_PROTOCOL, rule->protocol);
850
851         } else if (g_strcmp0(key, RULE_FAMILY) == 0) {
852                 rule->family = g_variant_get_uint16(value);
853                 STC_LOGD("%s: [%u]", RULE_FAMILY, rule->family);
854
855         } else if (g_strcmp0(key, RULE_SIP1) == 0) {
856                 guint str_length;
857                 const gchar *str = g_variant_get_string(value, &str_length);
858                 if (rule->family == STC_FW_FAMILY_V4) {
859                         inet_pton(AF_INET, str, &(rule->s_ip1.Ipv4));
860                         STC_LOGD("%s: [%08x]", RULE_SIP1, rule->s_ip1.Ipv4.s_addr);
861                 } else if (rule->family == STC_FW_FAMILY_V6) {
862                         inet_pton(AF_INET6, str, &(rule->s_ip1.Ipv6));
863                         STC_LOGD("%s: [%08x:%08x:%08x:%08x]", RULE_SIP1,
864                                 rule->s_ip1.Ipv6.s6_addr32[0], rule->s_ip1.Ipv6.s6_addr32[1],
865                                 rule->s_ip1.Ipv6.s6_addr32[2], rule->s_ip1.Ipv6.s6_addr32[3]);
866                 }
867
868         } else if (g_strcmp0(key, RULE_SIP2) == 0) {
869                 guint str_length;
870                 const gchar *str = g_variant_get_string(value, &str_length);
871                 if (rule->family == STC_FW_FAMILY_V4) {
872                         inet_pton(AF_INET, str, &(rule->s_ip2.Ipv4));
873                         STC_LOGD("%s: [%08x]", RULE_SIP2, rule->s_ip2.Ipv4.s_addr);
874                 } else if (rule->family == STC_FW_FAMILY_V6) {
875                         inet_pton(AF_INET6, str, &(rule->s_ip2.Ipv6));
876                         STC_LOGD("%s: [%08x:%08x:%08x:%08x]", RULE_SIP2,
877                                 rule->s_ip2.Ipv6.s6_addr32[0], rule->s_ip2.Ipv6.s6_addr32[1],
878                                 rule->s_ip2.Ipv6.s6_addr32[2], rule->s_ip2.Ipv6.s6_addr32[3]);
879                 }
880
881         } else if (g_strcmp0(key, RULE_DIP1) == 0) {
882                 guint str_length;
883                 const gchar *str = g_variant_get_string(value, &str_length);
884                 if (rule->family == STC_FW_FAMILY_V4) {
885                         inet_pton(AF_INET, str, &(rule->d_ip1.Ipv4));
886                         STC_LOGD("%s: [%08x]", RULE_DIP1, rule->d_ip1.Ipv4.s_addr);
887                 } else if (rule->family == STC_FW_FAMILY_V6) {
888                         inet_pton(AF_INET6, str, &(rule->d_ip1.Ipv6));
889                         STC_LOGD("%s: [%08x:%08x:%08x:%08x]", RULE_DIP1,
890                                 rule->d_ip1.Ipv6.s6_addr32[0], rule->d_ip1.Ipv6.s6_addr32[1],
891                                 rule->d_ip1.Ipv6.s6_addr32[2], rule->d_ip1.Ipv6.s6_addr32[3]);
892                 }
893
894         } else if (g_strcmp0(key, RULE_DIP2) == 0) {
895                 guint str_length;
896                 const gchar *str = g_variant_get_string(value, &str_length);
897                 if (rule->family == STC_FW_FAMILY_V4) {
898                         inet_pton(AF_INET, str, &(rule->d_ip2.Ipv4));
899                         STC_LOGD("%s: [%08x]", RULE_DIP2, rule->d_ip2.Ipv4.s_addr);
900                 } else if (rule->family == STC_FW_FAMILY_V6) {
901                         inet_pton(AF_INET6, str, &(rule->d_ip2.Ipv6));
902                         STC_LOGD("%s: [%08x:%08x:%08x:%08x]", RULE_DIP2,
903                                 rule->d_ip2.Ipv6.s6_addr32[0], rule->d_ip2.Ipv6.s6_addr32[1],
904                                 rule->d_ip2.Ipv6.s6_addr32[2], rule->d_ip2.Ipv6.s6_addr32[3]);
905                 }
906
907         } else if (g_strcmp0(key, RULE_SPORT1) == 0) {
908                 rule->s_port1 = g_variant_get_uint32(value);
909                 STC_LOGD("%s: [%04x]", RULE_SPORT1, rule->s_port1);
910
911         } else if (g_strcmp0(key, RULE_SPORT2) == 0) {
912                 rule->s_port2 = g_variant_get_uint32(value);
913                 STC_LOGD("%s: [%04x]", RULE_SPORT2, rule->s_port2);
914
915         } else if (g_strcmp0(key, RULE_DPORT1) == 0) {
916                 rule->d_port1 = g_variant_get_uint32(value);
917                 STC_LOGD("%s: [%04x]", RULE_DPORT1, rule->d_port1);
918
919         } else if (g_strcmp0(key, RULE_DPORT2) == 0) {
920                 rule->d_port2 = g_variant_get_uint32(value);
921                 STC_LOGD("%s: [%04x]", RULE_DPORT2, rule->d_port2);
922
923         } else if (g_strcmp0(key, RULE_IFNAME) == 0) {
924                 guint str_length;
925                 const gchar *str = g_variant_get_string(value, &str_length);
926                 rule->ifname = g_strdup(str);
927                 STC_LOGD("%s: [%s]", RULE_IFNAME, rule->ifname);
928
929         } else if (g_strcmp0(key, RULE_TARGET) == 0) {
930                 rule->target = g_variant_get_uint16(value);
931                 STC_LOGD("%s: [%u]", RULE_TARGET, rule->target);
932
933         } else if (g_strcmp0(key, RULE_IDENTIFIER) == 0) {
934                 guint str_length;
935                 const gchar *str = g_variant_get_string(value, &str_length);
936                 rule->identifier = g_strdup(str);
937                 STC_LOGD("%s: [%s]", RULE_IDENTIFIER, rule->identifier);
938
939         } else if (g_strcmp0(key, RULE_KEY) == 0) {
940                 rule->key = g_variant_get_uint32(value);
941                 STC_LOGD("%s: [%u]", RULE_KEY, rule->key);
942
943         } else {
944                 STC_LOGD("Unknown rule [%s]", key);
945         }
946
947         __STC_LOG_FUNC_EXIT__;
948 }
949
950 gboolean __validate_fw_rule(firewall_rule_s *rule)
951 {
952         __STC_LOG_FUNC_ENTER__;
953
954         if (rule == NULL) {
955                 __STC_LOG_FUNC_EXIT__;
956                 return FALSE;
957         }
958
959         if (rule->chain == NULL) {
960                 __STC_LOG_FUNC_EXIT__;
961                 return FALSE;
962         }
963
964         if (rule->direction > STC_FW_DIRECTION_OUT) {
965                 __STC_LOG_FUNC_EXIT__;
966                 return FALSE;
967         }
968
969         if (rule->s_ip_type > STC_FW_IP_RANGE) {
970                 __STC_LOG_FUNC_EXIT__;
971                 return FALSE;
972         }
973
974         if (rule->d_ip_type > STC_FW_IP_RANGE) {
975                 __STC_LOG_FUNC_EXIT__;
976                 return FALSE;
977         }
978
979         if (rule->s_port_type > STC_FW_PORT_RANGE) {
980                 __STC_LOG_FUNC_EXIT__;
981                 return FALSE;
982         }
983
984         if (rule->d_port_type > STC_FW_PORT_RANGE) {
985                 __STC_LOG_FUNC_EXIT__;
986                 return FALSE;
987         }
988
989         if (rule->protocol > STC_FW_PROTOCOL_ALL) {
990                 __STC_LOG_FUNC_EXIT__;
991                 return FALSE;
992         }
993
994         if (rule->family > STC_FW_FAMILY_V6) {
995                 __STC_LOG_FUNC_EXIT__;
996                 return FALSE;
997         }
998
999         __STC_LOG_FUNC_EXIT__;
1000         return TRUE;
1001 }
1002
1003 void stc_firewall_init(void)
1004 {
1005         int ret = STC_ERROR_NONE;
1006
1007         g_firewalls = g_hash_table_new_full(g_str_hash,
1008                                         g_str_equal, g_free, __fw_data_free);
1009
1010         ret = table_firewall_get_lock(LOCK_NAME, &g_lock_state);
1011         if (ret != STC_ERROR_NONE)
1012                 table_firewall_insert_lock(LOCK_NAME, FIREWALL_UNLOCKED);
1013
1014         if (g_lock_state == FIREWALL_UNKONWN)
1015                 g_lock_state = FIREWALL_UNLOCKED;
1016
1017         table_firewall_foreach_chain(__fw_table_chain_info_cb, NULL);
1018         table_firewall_foreach_rule(__fw_table_rule_info_cb, NULL);
1019 }
1020
1021 void stc_firewall_update(void)
1022 {
1023         __fw_chain_foreach(__fw_foreach_to_add_chain, NULL);
1024         __fw_chain_foreach(__fw_foreach_to_set_rule_to_chain, NULL);
1025         __fw_chain_foreach(__fw_foreach_to_set_chain, NULL);
1026 }
1027
1028 void stc_firewall_deinit(void)
1029 {
1030         if (g_firewalls) {
1031                 g_hash_table_destroy(g_firewalls);
1032                 g_firewalls = NULL;
1033         }
1034 }
1035
1036 gboolean handle_firewall_lock(StcFirewall *object,
1037                                         GDBusMethodInvocation *invocation,
1038                                         void *user_data)
1039 {
1040         __STC_LOG_FUNC_ENTER__;
1041         int ret = STC_ERROR_NONE;
1042
1043         ret = table_firewall_update_lock(LOCK_NAME, FIREWALL_LOCKED);
1044         if (ret != STC_ERROR_NONE)
1045                 table_firewall_insert_lock(LOCK_NAME, FIREWALL_LOCKED);
1046
1047         g_lock_state = FIREWALL_LOCKED;
1048
1049         STC_DBUS_REPLY_ERROR_NONE(invocation);
1050         __STC_LOG_FUNC_EXIT__;
1051         return TRUE;
1052 }
1053
1054 gboolean handle_firewall_unlock(StcFirewall *object,
1055                                         GDBusMethodInvocation *invocation,
1056                                         void *user_data)
1057 {
1058         __STC_LOG_FUNC_ENTER__;
1059         int ret = STC_ERROR_NONE;
1060
1061         ret = table_firewall_update_lock(LOCK_NAME, FIREWALL_UNLOCKED);
1062         if (ret != STC_ERROR_NONE)
1063                 table_firewall_insert_lock(LOCK_NAME, FIREWALL_UNLOCKED);
1064
1065         g_lock_state = FIREWALL_UNLOCKED;
1066
1067         STC_DBUS_REPLY_ERROR_NONE(invocation);
1068         __STC_LOG_FUNC_EXIT__;
1069         return TRUE;
1070 }
1071
1072 gboolean handle_firewall_get_lock(StcFirewall *object,
1073                                         GDBusMethodInvocation *invocation,
1074                                         void *user_data)
1075 {
1076         __STC_LOG_FUNC_ENTER__;
1077         int ret = STC_ERROR_NONE;
1078         GVariant *return_parameters = NULL;
1079
1080         if (g_lock_state == FIREWALL_UNKONWN) {
1081                 ret = table_firewall_get_lock(LOCK_NAME, &g_lock_state);
1082                 if (ret != STC_ERROR_NONE)
1083                         table_firewall_insert_lock(LOCK_NAME, FIREWALL_UNLOCKED);
1084
1085                 if (g_lock_state == FIREWALL_UNKONWN)
1086                         g_lock_state = FIREWALL_UNLOCKED;
1087         }
1088
1089         return_parameters = g_variant_new("(i)", g_lock_state);
1090         STC_DBUS_REPLY(invocation, return_parameters);
1091         __STC_LOG_FUNC_EXIT__;
1092         return TRUE;
1093 }
1094
1095 gboolean handle_firewall_add_chain(StcFirewall *object,
1096                                         GDBusMethodInvocation *invocation,
1097                                         gchar *chain,
1098                                         void *user_data)
1099 {
1100         __STC_LOG_FUNC_ENTER__;
1101         firewall_chain_s info;
1102         int ret = STC_ERROR_NONE;
1103
1104         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1105
1106         if (chain == NULL) {
1107                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1108                                                 STC_ERROR_INVALID_PARAMETER);
1109                 __STC_LOG_FUNC_EXIT__;
1110                 return TRUE;
1111         }
1112
1113         ret = __fw_chain_add(chain);
1114         if (ret == STC_ERROR_NONE) {
1115                 memset(&info, 0, sizeof(firewall_chain_s));
1116                 info.chain = chain;
1117                 info.priority = 0;
1118                 info.target = STC_FW_CHAIN_TARGET_NONE;
1119                 table_firewall_insert_chain(&info);
1120         } else {
1121                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1122                 __STC_LOG_FUNC_EXIT__;
1123                 return TRUE;
1124         }
1125
1126         STC_DBUS_REPLY_ERROR_NONE(invocation);
1127         __STC_LOG_FUNC_EXIT__;
1128         return TRUE;
1129 }
1130
1131 gboolean handle_firewall_remove_chain(StcFirewall *object,
1132                                         GDBusMethodInvocation *invocation,
1133                                         gchar *chain,
1134                                         void *user_data)
1135 {
1136         __STC_LOG_FUNC_ENTER__;
1137         firewall_chain_s info;
1138         int ret = STC_ERROR_NONE;
1139
1140         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1141
1142         if (chain == NULL) {
1143                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1144                                                 STC_ERROR_INVALID_PARAMETER);
1145                 __STC_LOG_FUNC_EXIT__;
1146                 return TRUE;
1147         }
1148
1149         ret = __fw_chain_remove(chain);
1150         if (ret == STC_ERROR_NONE) {
1151                 memset(&info, 0, sizeof(firewall_chain_s));
1152                 info.chain = chain;
1153                 table_firewall_flush_chain(&info);
1154                 table_firewall_delete_chain(&info);
1155         } else {
1156                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1157                 __STC_LOG_FUNC_EXIT__;
1158                 return TRUE;
1159         }
1160
1161         STC_DBUS_REPLY_ERROR_NONE(invocation);
1162         __STC_LOG_FUNC_EXIT__;
1163         return TRUE;
1164 }
1165
1166 gboolean handle_firewall_flush_chain(StcFirewall *object,
1167                                         GDBusMethodInvocation *invocation,
1168                                         gchar *chain,
1169                                         void *user_data)
1170 {
1171         __STC_LOG_FUNC_ENTER__;
1172         firewall_chain_s info;
1173         int ret = STC_ERROR_NONE;
1174
1175         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1176
1177         if (chain == NULL) {
1178                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1179                                                 STC_ERROR_INVALID_PARAMETER);
1180                 __STC_LOG_FUNC_EXIT__;
1181                 return TRUE;
1182         }
1183
1184         ret = __fw_chain_flush(chain);
1185         if (ret == STC_ERROR_NONE) {
1186                 memset(&info, 0, sizeof(firewall_chain_s));
1187                 info.chain = chain;
1188                 table_firewall_flush_chain(&info);
1189         } else {
1190                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1191                 __STC_LOG_FUNC_EXIT__;
1192                 return TRUE;
1193         }
1194
1195         STC_DBUS_REPLY_ERROR_NONE(invocation);
1196         __STC_LOG_FUNC_EXIT__;
1197         return TRUE;
1198 }
1199
1200 gboolean handle_firewall_get_all_chain(StcFirewall *object,
1201                                         GDBusMethodInvocation *invocation,
1202                                         void *user_data)
1203 {
1204         __STC_LOG_FUNC_ENTER__;
1205         GVariantBuilder *builder = NULL;
1206         GVariant *return_parameters = NULL;
1207
1208         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1209
1210         builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
1211
1212         __fw_chain_foreach(__fw_chain_make_params, builder);
1213
1214         return_parameters = g_variant_new("(aa{sv})", builder);
1215         g_variant_builder_unref(builder);
1216
1217         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
1218         STC_DBUS_REPLY(invocation, return_parameters);
1219         __STC_LOG_FUNC_EXIT__;
1220         return TRUE;
1221 }
1222
1223 gboolean handle_firewall_set_chain(StcFirewall *object,
1224                                         GDBusMethodInvocation *invocation,
1225                                         gchar *chain,
1226                                         unsigned int target,
1227                                         void *user_data)
1228 {
1229         __STC_LOG_FUNC_ENTER__;
1230         stc_fw_data_s *lookup = NULL;
1231         stc_fw_data_s data;
1232         firewall_chain_s info;
1233         uint priority;
1234         int ret = STC_ERROR_NONE;
1235
1236         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1237
1238         if (chain == NULL ||
1239                 target > STC_FW_CHAIN_TARGET_OUTPUT) {
1240                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1241                                                 STC_ERROR_INVALID_PARAMETER);
1242                 __STC_LOG_FUNC_EXIT__;
1243                 return TRUE;
1244         }
1245
1246         lookup = __fw_chain_get(chain);
1247         if (lookup == NULL) {
1248                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1249                                                 STC_ERROR_NO_DATA);
1250                 __STC_LOG_FUNC_EXIT__;
1251                 return TRUE;
1252         }
1253
1254         if (lookup->target != STC_FW_CHAIN_TARGET_NONE) {
1255                 STC_LOGE("chain is already set");
1256                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1257                                                 STC_ERROR_INVALID_PARAMETER);
1258                 __STC_LOG_FUNC_EXIT__;
1259                 return TRUE;
1260         }
1261
1262         /* stc-iptables */
1263         memset(&info, 0, sizeof(firewall_chain_s));
1264         info.chain = chain;
1265         info.target = target;
1266
1267         ret = firewall_chain_add(&info);
1268         if (ret != STC_ERROR_NONE) {
1269                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1270                 __STC_LOG_FUNC_EXIT__;
1271                 return TRUE;
1272         }
1273
1274         __fw_chain_foreach(__fw_foreach_to_set_rule_to_chain, chain);
1275
1276         ret = firewall_chain_set(&info);
1277         if (ret != STC_ERROR_NONE) {
1278                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1279                 __STC_LOG_FUNC_EXIT__;
1280                 return TRUE;
1281         }
1282         /* stc-iptables */
1283
1284         priority = g_chain_priority + 1;
1285
1286         memset(&data, 0, sizeof(stc_fw_data_s));
1287         data.target = target;
1288         data.priority = priority;
1289
1290         ret = __fw_chain_set(chain, data);
1291         if (ret == STC_ERROR_NONE) {
1292                 info.priority = priority;
1293                 table_firewall_update_chain(&info);
1294                 g_chain_priority = priority;
1295         } else {
1296                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1297                 __STC_LOG_FUNC_EXIT__;
1298                 return TRUE;
1299         }
1300
1301         STC_DBUS_REPLY_ERROR_NONE(invocation);
1302         __STC_LOG_FUNC_EXIT__;
1303         return TRUE;
1304 }
1305
1306 gboolean handle_firewall_unset_chain(StcFirewall *object,
1307                                         GDBusMethodInvocation *invocation,
1308                                         gchar *chain,
1309                                         void *user_data)
1310 {
1311         __STC_LOG_FUNC_ENTER__;
1312         stc_fw_data_s *lookup = NULL;
1313         firewall_chain_s info;
1314         int ret = STC_ERROR_NONE;
1315
1316         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1317
1318         if (chain == NULL) {
1319                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1320                                                 STC_ERROR_INVALID_PARAMETER);
1321                 __STC_LOG_FUNC_EXIT__;
1322                 return TRUE;
1323         }
1324
1325         lookup = __fw_chain_get(chain);
1326         if (lookup == NULL) {
1327                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1328                                                 STC_ERROR_NO_DATA);
1329                 __STC_LOG_FUNC_EXIT__;
1330                 return TRUE;
1331         }
1332
1333         if (lookup->target == STC_FW_CHAIN_TARGET_NONE) {
1334                 STC_LOGE("chain is not set");
1335                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1336                                                 STC_ERROR_INVALID_PARAMETER);
1337                 __STC_LOG_FUNC_EXIT__;
1338                 return TRUE;
1339         }
1340
1341         /* stc-iptables */
1342         memset(&info, 0, sizeof(firewall_chain_s));
1343         info.chain = chain;
1344         info.target = lookup->target;
1345
1346         ret = firewall_chain_unset(&info);
1347         if (ret != STC_ERROR_NONE) {
1348                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1349                 __STC_LOG_FUNC_EXIT__;
1350                 return TRUE;
1351         }
1352
1353         ret = firewall_chain_remove(&info);
1354         if (ret != STC_ERROR_NONE) {
1355                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1356                 __STC_LOG_FUNC_EXIT__;
1357                 return TRUE;
1358         }
1359         /* stc-iptables */
1360
1361         ret = __fw_chain_unset(chain);
1362         if (ret == STC_ERROR_NONE) {
1363                 info.target = STC_FW_CHAIN_TARGET_NONE;
1364                 info.priority = 0;
1365                 table_firewall_update_chain(&info);
1366         } else {
1367                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1368                 __STC_LOG_FUNC_EXIT__;
1369                 return TRUE;
1370         }
1371
1372         STC_DBUS_REPLY_ERROR_NONE(invocation);
1373         __STC_LOG_FUNC_EXIT__;
1374         return TRUE;
1375 }
1376
1377 gboolean handle_firewall_add_rule(StcFirewall *object,
1378                                    GDBusMethodInvocation *invocation,
1379                                    GVariant *parameters,
1380                                    void *user_data)
1381 {
1382         __STC_LOG_FUNC_ENTER__;
1383         GVariantIter *iter = NULL;
1384         firewall_rule_s *rule;
1385         int ret = STC_ERROR_NONE;
1386
1387         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1388
1389         rule = MALLOC0(firewall_rule_s, 1);
1390         if (!rule) {
1391                 STC_LOGE("rule allocation failed");
1392                 return STC_ERROR_OUT_OF_MEMORY;
1393         }
1394
1395         memset(rule, 0, sizeof(firewall_rule_s));
1396
1397         g_variant_get(parameters, "a{sv}", &iter);
1398         if (iter != NULL) {
1399                 stc_manager_gdbus_dict_foreach(iter,
1400                                                __fw_rule_extract,
1401                                                rule);
1402                 g_variant_iter_free(iter);
1403         }
1404
1405         if (__validate_fw_rule(rule) == FALSE) {
1406                 __fw_rule_free(rule);
1407                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1408                                                  STC_ERROR_INVALID_PARAMETER);
1409                 __STC_LOG_FUNC_EXIT__;
1410                 return TRUE;
1411         }
1412
1413         ret = __fw_rule_add(rule);
1414         if (ret == STC_ERROR_NONE) {
1415                 table_firewall_insert_rule(rule);
1416         } else {
1417                 __fw_rule_free(rule);
1418                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1419                 __STC_LOG_FUNC_EXIT__;
1420                 return TRUE;
1421         }
1422
1423         __fw_rule_free(rule);
1424         STC_DBUS_REPLY_ERROR_NONE(invocation);
1425         __STC_LOG_FUNC_EXIT__;
1426         return TRUE;
1427 }
1428
1429 gboolean handle_firewall_remove_rule(StcFirewall *object,
1430                                    GDBusMethodInvocation *invocation,
1431                                    GVariant *parameters,
1432                                    void *user_data)
1433 {
1434         __STC_LOG_FUNC_ENTER__;
1435         GVariantIter *iter = NULL;
1436         firewall_rule_s *rule;
1437         int ret = STC_ERROR_NONE;
1438
1439         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1440
1441         rule = MALLOC0(firewall_rule_s, 1);
1442         if (!rule) {
1443                 STC_LOGE("rule allocation failed");
1444                 return STC_ERROR_OUT_OF_MEMORY;
1445         }
1446
1447         memset(rule, 0, sizeof(firewall_rule_s));
1448
1449         g_variant_get(parameters, "a{sv}", &iter);
1450         if (iter != NULL) {
1451                 stc_manager_gdbus_dict_foreach(iter,
1452                                                __fw_rule_extract,
1453                                                rule);
1454                 g_variant_iter_free(iter);
1455         }
1456
1457         if (__validate_fw_rule(rule) == FALSE) {
1458                 __fw_rule_free(rule);
1459                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1460                                                  STC_ERROR_INVALID_PARAMETER);
1461                 __STC_LOG_FUNC_EXIT__;
1462                 return TRUE;
1463         }
1464
1465         ret = __fw_rule_remove(rule);
1466         if (ret == STC_ERROR_NONE) {
1467                 table_firewall_delete_rule(rule);
1468         } else {
1469                 __fw_rule_free(rule);
1470                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1471                 __STC_LOG_FUNC_EXIT__;
1472                 return TRUE;
1473         }
1474
1475         __fw_rule_free(rule);
1476         STC_DBUS_REPLY_ERROR_NONE(invocation);
1477         __STC_LOG_FUNC_EXIT__;
1478         return TRUE;
1479 }
1480
1481 gboolean handle_firewall_update_rule(StcFirewall *object,
1482                                    GDBusMethodInvocation *invocation,
1483                                    GVariant *parameters,
1484                                    void *user_data)
1485 {
1486         __STC_LOG_FUNC_ENTER__;
1487         GVariantIter *iter = NULL;
1488         firewall_rule_s *rule;
1489         int ret = STC_ERROR_NONE;
1490
1491         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1492
1493         rule = MALLOC0(firewall_rule_s, 1);
1494         if (!rule) {
1495                 STC_LOGE("rule allocation failed");
1496                 return STC_ERROR_OUT_OF_MEMORY;
1497         }
1498
1499         memset(rule, 0, sizeof(firewall_rule_s));
1500
1501         g_variant_get(parameters, "a{sv}", &iter);
1502         if (iter != NULL) {
1503                 stc_manager_gdbus_dict_foreach(iter,
1504                                                __fw_rule_extract,
1505                                                rule);
1506                 g_variant_iter_free(iter);
1507         }
1508
1509         if (__validate_fw_rule(rule) == FALSE) {
1510                 __fw_rule_free(rule);
1511                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1512                                                  STC_ERROR_INVALID_PARAMETER);
1513                 __STC_LOG_FUNC_EXIT__;
1514                 return TRUE;
1515         }
1516
1517         ret = __fw_rule_update(rule);
1518         if (ret == STC_ERROR_NONE) {
1519                 table_firewall_update_rule(rule);
1520         } else {
1521                 __fw_rule_free(rule);
1522                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1523                 __STC_LOG_FUNC_EXIT__;
1524                 return TRUE;
1525         }
1526
1527         __fw_rule_free(rule);
1528         STC_DBUS_REPLY_ERROR_NONE(invocation);
1529         __STC_LOG_FUNC_EXIT__;
1530         return TRUE;
1531 }
1532
1533 gboolean handle_firewall_get_all_rule(StcFirewall *object,
1534                                    GDBusMethodInvocation *invocation,
1535                                    void *user_data)
1536 {
1537         __STC_LOG_FUNC_ENTER__;
1538         GVariantBuilder *builder = NULL;
1539         GVariant *return_parameters = NULL;
1540
1541         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1542
1543         builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
1544
1545         __fw_chain_foreach(__fw_foreach_to_make_rule_param, builder);
1546
1547         return_parameters = g_variant_new("(aa{sv})", builder);
1548         g_variant_builder_unref(builder);
1549
1550         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
1551         STC_DBUS_REPLY(invocation, return_parameters);
1552         __STC_LOG_FUNC_EXIT__;
1553         return TRUE;
1554 }