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