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