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