Fix for 4 Svace issues.
[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_LOG &&
1169                 (rule->log_prefix == NULL ||
1170                 rule->log_prefix[0] == '\0')) {
1171                 __STC_LOG_FUNC_EXIT__;
1172                 return FALSE;
1173         }
1174
1175         if (rule->target == STC_FW_RULE_TARGET_NFLOG &&
1176                 (rule->nflog_prefix == NULL ||
1177                 rule->nflog_prefix[0] == '\0')) {
1178                 __STC_LOG_FUNC_EXIT__;
1179                 return FALSE;
1180         }
1181
1182         __STC_LOG_FUNC_EXIT__;
1183         return TRUE;
1184 }
1185
1186 void stc_firewall_init(void)
1187 {
1188         int ret = STC_ERROR_NONE;
1189
1190         g_firewalls = g_hash_table_new_full(g_str_hash,
1191                                         g_str_equal, g_free, __fw_data_free);
1192
1193         ret = table_firewall_get_lock(LOCK_NAME, &g_lock_state);
1194         if (ret != STC_ERROR_NONE)
1195                 table_firewall_insert_lock(LOCK_NAME, FIREWALL_UNLOCKED);
1196
1197         if (g_lock_state == FIREWALL_UNKONWN)
1198                 g_lock_state = FIREWALL_UNLOCKED;
1199
1200         table_firewall_foreach_chain(__fw_table_chain_info_cb, NULL);
1201         table_firewall_foreach_rule(__fw_table_rule_info_cb, NULL);
1202 }
1203
1204 void stc_firewall_update(void)
1205 {
1206         __fw_chain_foreach(__fw_foreach_to_add_chain, NULL);
1207         __fw_chain_foreach(__fw_foreach_to_set_rule_to_chain, NULL);
1208         __fw_chain_foreach(__fw_foreach_to_set_chain, NULL);
1209 }
1210
1211 void stc_firewall_deinit(void)
1212 {
1213         if (g_firewalls) {
1214                 g_hash_table_destroy(g_firewalls);
1215                 g_firewalls = NULL;
1216         }
1217 }
1218
1219 gboolean handle_firewall_lock(StcFirewall *object,
1220                                         GDBusMethodInvocation *invocation,
1221                                         void *user_data)
1222 {
1223         __STC_LOG_FUNC_ENTER__;
1224         int ret = STC_ERROR_NONE;
1225
1226         ret = table_firewall_update_lock(LOCK_NAME, FIREWALL_LOCKED);
1227         if (ret != STC_ERROR_NONE)
1228                 table_firewall_insert_lock(LOCK_NAME, FIREWALL_LOCKED);
1229
1230         g_lock_state = FIREWALL_LOCKED;
1231
1232         STC_DBUS_REPLY_ERROR_NONE(invocation);
1233         __STC_LOG_FUNC_EXIT__;
1234         return TRUE;
1235 }
1236
1237 gboolean handle_firewall_unlock(StcFirewall *object,
1238                                         GDBusMethodInvocation *invocation,
1239                                         void *user_data)
1240 {
1241         __STC_LOG_FUNC_ENTER__;
1242         int ret = STC_ERROR_NONE;
1243
1244         ret = table_firewall_update_lock(LOCK_NAME, FIREWALL_UNLOCKED);
1245         if (ret != STC_ERROR_NONE)
1246                 table_firewall_insert_lock(LOCK_NAME, FIREWALL_UNLOCKED);
1247
1248         g_lock_state = FIREWALL_UNLOCKED;
1249
1250         STC_DBUS_REPLY_ERROR_NONE(invocation);
1251         __STC_LOG_FUNC_EXIT__;
1252         return TRUE;
1253 }
1254
1255 gboolean handle_firewall_get_lock(StcFirewall *object,
1256                                         GDBusMethodInvocation *invocation,
1257                                         void *user_data)
1258 {
1259         __STC_LOG_FUNC_ENTER__;
1260         int ret = STC_ERROR_NONE;
1261         GVariant *return_parameters = NULL;
1262
1263         if (g_lock_state == FIREWALL_UNKONWN) {
1264                 ret = table_firewall_get_lock(LOCK_NAME, &g_lock_state);
1265                 if (ret != STC_ERROR_NONE)
1266                         table_firewall_insert_lock(LOCK_NAME, FIREWALL_UNLOCKED);
1267
1268                 if (g_lock_state == FIREWALL_UNKONWN)
1269                         g_lock_state = FIREWALL_UNLOCKED;
1270         }
1271
1272         return_parameters = g_variant_new("(i)", g_lock_state);
1273         STC_DBUS_REPLY(invocation, return_parameters);
1274         __STC_LOG_FUNC_EXIT__;
1275         return TRUE;
1276 }
1277
1278 gboolean handle_firewall_add_chain(StcFirewall *object,
1279                                         GDBusMethodInvocation *invocation,
1280                                         gchar *chain,
1281                                         void *user_data)
1282 {
1283         __STC_LOG_FUNC_ENTER__;
1284         firewall_chain_s info;
1285         int ret = STC_ERROR_NONE;
1286
1287         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1288
1289         if (chain == NULL) {
1290                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1291                                                 STC_ERROR_INVALID_PARAMETER);
1292                 __STC_LOG_FUNC_EXIT__;
1293                 return TRUE;
1294         }
1295
1296         ret = __fw_chain_add(chain);
1297         if (ret == STC_ERROR_NONE) {
1298                 memset(&info, 0, sizeof(firewall_chain_s));
1299                 info.chain = chain;
1300                 info.priority = 0;
1301                 info.target = STC_FW_CHAIN_TARGET_NONE;
1302                 table_firewall_insert_chain(&info);
1303         } else {
1304                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1305                 __STC_LOG_FUNC_EXIT__;
1306                 return TRUE;
1307         }
1308
1309         STC_DBUS_REPLY_ERROR_NONE(invocation);
1310         __STC_LOG_FUNC_EXIT__;
1311         return TRUE;
1312 }
1313
1314 gboolean handle_firewall_remove_chain(StcFirewall *object,
1315                                         GDBusMethodInvocation *invocation,
1316                                         gchar *chain,
1317                                         void *user_data)
1318 {
1319         __STC_LOG_FUNC_ENTER__;
1320         firewall_chain_s info;
1321         int ret = STC_ERROR_NONE;
1322
1323         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1324
1325         if (chain == NULL) {
1326                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1327                                                 STC_ERROR_INVALID_PARAMETER);
1328                 __STC_LOG_FUNC_EXIT__;
1329                 return TRUE;
1330         }
1331
1332         ret = __fw_chain_remove(chain);
1333         if (ret == STC_ERROR_NONE) {
1334                 memset(&info, 0, sizeof(firewall_chain_s));
1335                 info.chain = chain;
1336                 table_firewall_flush_chain(&info);
1337                 table_firewall_delete_chain(&info);
1338         } else {
1339                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1340                 __STC_LOG_FUNC_EXIT__;
1341                 return TRUE;
1342         }
1343
1344         STC_DBUS_REPLY_ERROR_NONE(invocation);
1345         __STC_LOG_FUNC_EXIT__;
1346         return TRUE;
1347 }
1348
1349 gboolean handle_firewall_flush_chain(StcFirewall *object,
1350                                         GDBusMethodInvocation *invocation,
1351                                         gchar *chain,
1352                                         void *user_data)
1353 {
1354         __STC_LOG_FUNC_ENTER__;
1355         firewall_chain_s info;
1356         int ret = STC_ERROR_NONE;
1357
1358         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1359
1360         if (chain == NULL) {
1361                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1362                                                 STC_ERROR_INVALID_PARAMETER);
1363                 __STC_LOG_FUNC_EXIT__;
1364                 return TRUE;
1365         }
1366
1367         ret = __fw_chain_flush(chain);
1368         if (ret == STC_ERROR_NONE) {
1369                 memset(&info, 0, sizeof(firewall_chain_s));
1370                 info.chain = chain;
1371                 table_firewall_flush_chain(&info);
1372         } else {
1373                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1374                 __STC_LOG_FUNC_EXIT__;
1375                 return TRUE;
1376         }
1377
1378         STC_DBUS_REPLY_ERROR_NONE(invocation);
1379         __STC_LOG_FUNC_EXIT__;
1380         return TRUE;
1381 }
1382
1383 gboolean handle_firewall_get_all_chain(StcFirewall *object,
1384                                         GDBusMethodInvocation *invocation,
1385                                         void *user_data)
1386 {
1387         __STC_LOG_FUNC_ENTER__;
1388         GVariantBuilder *builder = NULL;
1389         GVariant *return_parameters = NULL;
1390
1391         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1392
1393         builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
1394
1395         __fw_chain_foreach(__fw_chain_make_params, builder);
1396
1397         return_parameters = g_variant_new("(aa{sv})", builder);
1398         g_variant_builder_unref(builder);
1399
1400         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
1401         STC_DBUS_REPLY(invocation, return_parameters);
1402         __STC_LOG_FUNC_EXIT__;
1403         return TRUE;
1404 }
1405
1406 gboolean handle_firewall_set_chain(StcFirewall *object,
1407                                         GDBusMethodInvocation *invocation,
1408                                         gchar *chain,
1409                                         unsigned int target,
1410                                         void *user_data)
1411 {
1412         __STC_LOG_FUNC_ENTER__;
1413         stc_fw_data_s *lookup = NULL;
1414         stc_fw_data_s data;
1415         firewall_chain_s info;
1416         uint priority;
1417         int ret = STC_ERROR_NONE;
1418
1419         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1420
1421         if (chain == NULL ||
1422                 target >= STC_FW_CHAIN_TARGET_MAX) {
1423                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1424                                                 STC_ERROR_INVALID_PARAMETER);
1425                 __STC_LOG_FUNC_EXIT__;
1426                 return TRUE;
1427         }
1428
1429         lookup = __fw_chain_get(chain);
1430         if (lookup == NULL) {
1431                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1432                                                 STC_ERROR_NO_DATA);
1433                 __STC_LOG_FUNC_EXIT__;
1434                 return TRUE;
1435         }
1436
1437         if (lookup->target != STC_FW_CHAIN_TARGET_NONE) {
1438                 STC_LOGE("chain is already set");
1439                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1440                                                 STC_ERROR_INVALID_PARAMETER);
1441                 __STC_LOG_FUNC_EXIT__;
1442                 return TRUE;
1443         }
1444
1445         /* stc-iptables */
1446         memset(&info, 0, sizeof(firewall_chain_s));
1447         info.chain = chain;
1448         info.target = target;
1449
1450         ret = firewall_chain_add(&info);
1451         if (ret != STC_ERROR_NONE) {
1452                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1453                 __STC_LOG_FUNC_EXIT__;
1454                 return TRUE;
1455         }
1456
1457         __fw_chain_foreach(__fw_foreach_to_set_rule_to_chain, chain);
1458         ret = firewall_chain_set(&info);
1459         if (ret != STC_ERROR_NONE) {
1460                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1461                 __STC_LOG_FUNC_EXIT__;
1462                 return TRUE;
1463         }
1464         /* stc-iptables */
1465
1466         priority = g_chain_priority + 1;
1467
1468         memset(&data, 0, sizeof(stc_fw_data_s));
1469         data.target = target;
1470         data.priority = priority;
1471
1472         ret = __fw_chain_set(chain, data);
1473         if (ret == STC_ERROR_NONE) {
1474                 info.priority = priority;
1475                 table_firewall_update_chain(&info);
1476                 g_chain_priority = priority;
1477         } else {
1478                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1479                 __STC_LOG_FUNC_EXIT__;
1480                 return TRUE;
1481         }
1482
1483         STC_DBUS_REPLY_ERROR_NONE(invocation);
1484         __STC_LOG_FUNC_EXIT__;
1485         return TRUE;
1486 }
1487
1488 gboolean handle_firewall_unset_chain(StcFirewall *object,
1489                                         GDBusMethodInvocation *invocation,
1490                                         gchar *chain,
1491                                         void *user_data)
1492 {
1493         __STC_LOG_FUNC_ENTER__;
1494         stc_fw_data_s *lookup = NULL;
1495         firewall_chain_s info;
1496         int ret = STC_ERROR_NONE;
1497
1498         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1499
1500         if (chain == NULL) {
1501                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1502                                                 STC_ERROR_INVALID_PARAMETER);
1503                 __STC_LOG_FUNC_EXIT__;
1504                 return TRUE;
1505         }
1506
1507         lookup = __fw_chain_get(chain);
1508         if (lookup == NULL) {
1509                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1510                                                 STC_ERROR_NO_DATA);
1511                 __STC_LOG_FUNC_EXIT__;
1512                 return TRUE;
1513         }
1514
1515         if (lookup->target == STC_FW_CHAIN_TARGET_NONE) {
1516                 STC_LOGE("chain is not set");
1517                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1518                                                 STC_ERROR_INVALID_PARAMETER);
1519                 __STC_LOG_FUNC_EXIT__;
1520                 return TRUE;
1521         }
1522
1523         /* stc-iptables */
1524         memset(&info, 0, sizeof(firewall_chain_s));
1525         info.chain = chain;
1526         info.target = lookup->target;
1527
1528         ret = firewall_chain_unset(&info);
1529         if (ret != STC_ERROR_NONE) {
1530                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1531                 __STC_LOG_FUNC_EXIT__;
1532                 return TRUE;
1533         }
1534
1535         ret = firewall_chain_remove(&info);
1536         if (ret != STC_ERROR_NONE) {
1537                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1538                 __STC_LOG_FUNC_EXIT__;
1539                 return TRUE;
1540         }
1541         /* stc-iptables */
1542
1543         ret = __fw_chain_unset(chain);
1544         if (ret == STC_ERROR_NONE) {
1545                 info.target = STC_FW_CHAIN_TARGET_NONE;
1546                 info.priority = 0;
1547                 table_firewall_update_chain(&info);
1548         } else {
1549                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1550                 __STC_LOG_FUNC_EXIT__;
1551                 return TRUE;
1552         }
1553
1554         STC_DBUS_REPLY_ERROR_NONE(invocation);
1555         __STC_LOG_FUNC_EXIT__;
1556         return TRUE;
1557 }
1558
1559 gboolean handle_firewall_add_rule(StcFirewall *object,
1560                                    GDBusMethodInvocation *invocation,
1561                                    GVariant *parameters,
1562                                    void *user_data)
1563 {
1564         __STC_LOG_FUNC_ENTER__;
1565         GVariantIter *iter = NULL;
1566         firewall_rule_s *rule;
1567         int ret = STC_ERROR_NONE;
1568
1569         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1570
1571         rule = MALLOC0(firewall_rule_s, 1);
1572         if (!rule) {
1573                 STC_LOGE("rule allocation failed");
1574                 return STC_ERROR_OUT_OF_MEMORY;
1575         }
1576
1577         memset(rule, 0, sizeof(firewall_rule_s));
1578
1579         g_variant_get(parameters, "a{sv}", &iter);
1580         if (iter != NULL) {
1581                 stc_manager_gdbus_dict_foreach(iter,
1582                                                __fw_rule_extract,
1583                                                rule);
1584                 g_variant_iter_free(iter);
1585         }
1586
1587         if (__validate_fw_rule(rule) == FALSE) {
1588                 __fw_rule_free(rule);
1589                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1590                                                  STC_ERROR_INVALID_PARAMETER);
1591                 __STC_LOG_FUNC_EXIT__;
1592                 return TRUE;
1593         }
1594
1595         ret = __fw_rule_add(rule);
1596         if (ret == STC_ERROR_NONE) {
1597                 table_firewall_insert_rule(rule);
1598         } else {
1599                 __fw_rule_free(rule);
1600                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1601                 __STC_LOG_FUNC_EXIT__;
1602                 return TRUE;
1603         }
1604
1605         __fw_rule_free(rule);
1606         STC_DBUS_REPLY_ERROR_NONE(invocation);
1607         __STC_LOG_FUNC_EXIT__;
1608         return TRUE;
1609 }
1610
1611 gboolean handle_firewall_remove_rule(StcFirewall *object,
1612                                    GDBusMethodInvocation *invocation,
1613                                    GVariant *parameters,
1614                                    void *user_data)
1615 {
1616         __STC_LOG_FUNC_ENTER__;
1617         GVariantIter *iter = NULL;
1618         firewall_rule_s *rule;
1619         int ret = STC_ERROR_NONE;
1620
1621         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1622
1623         rule = MALLOC0(firewall_rule_s, 1);
1624         if (!rule) {
1625                 STC_LOGE("rule allocation failed");
1626                 return STC_ERROR_OUT_OF_MEMORY;
1627         }
1628
1629         memset(rule, 0, sizeof(firewall_rule_s));
1630
1631         g_variant_get(parameters, "a{sv}", &iter);
1632         if (iter != NULL) {
1633                 stc_manager_gdbus_dict_foreach(iter,
1634                                                __fw_rule_extract,
1635                                                rule);
1636                 g_variant_iter_free(iter);
1637         }
1638
1639         if (__validate_fw_rule(rule) == FALSE) {
1640                 __fw_rule_free(rule);
1641                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1642                                                  STC_ERROR_INVALID_PARAMETER);
1643                 __STC_LOG_FUNC_EXIT__;
1644                 return TRUE;
1645         }
1646
1647         ret = __fw_rule_remove(rule);
1648         if (ret == STC_ERROR_NONE) {
1649                 table_firewall_delete_rule(rule);
1650         } else {
1651                 __fw_rule_free(rule);
1652                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1653                 __STC_LOG_FUNC_EXIT__;
1654                 return TRUE;
1655         }
1656
1657         __fw_rule_free(rule);
1658         STC_DBUS_REPLY_ERROR_NONE(invocation);
1659         __STC_LOG_FUNC_EXIT__;
1660         return TRUE;
1661 }
1662
1663 gboolean handle_firewall_update_rule(StcFirewall *object,
1664                                    GDBusMethodInvocation *invocation,
1665                                    GVariant *parameters,
1666                                    void *user_data)
1667 {
1668         __STC_LOG_FUNC_ENTER__;
1669         GVariantIter *iter = NULL;
1670         firewall_rule_s *rule;
1671         guint key;
1672         int ret = STC_ERROR_NONE;
1673
1674         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1675
1676         rule = MALLOC0(firewall_rule_s, 1);
1677         if (!rule) {
1678                 STC_LOGE("rule allocation failed");
1679                 return STC_ERROR_OUT_OF_MEMORY;
1680         }
1681
1682         memset(rule, 0, sizeof(firewall_rule_s));
1683
1684         g_variant_get(parameters, "a{sv}", &iter);
1685         if (iter != NULL) {
1686                 stc_manager_gdbus_dict_foreach(iter,
1687                                                __fw_rule_extract,
1688                                                rule);
1689                 g_variant_iter_free(iter);
1690         }
1691
1692         if (__validate_fw_rule(rule) == FALSE) {
1693                 __fw_rule_free(rule);
1694                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
1695                                                  STC_ERROR_INVALID_PARAMETER);
1696                 __STC_LOG_FUNC_EXIT__;
1697                 return TRUE;
1698         }
1699
1700         key = rule->key;
1701         ret = __fw_rule_update(rule);
1702         if (ret == STC_ERROR_NONE) {
1703                 table_firewall_update_rule(rule, key);
1704         } else {
1705                 __fw_rule_free(rule);
1706                 STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
1707                 __STC_LOG_FUNC_EXIT__;
1708                 return TRUE;
1709         }
1710
1711         __fw_rule_free(rule);
1712         STC_DBUS_REPLY_ERROR_NONE(invocation);
1713         __STC_LOG_FUNC_EXIT__;
1714         return TRUE;
1715 }
1716
1717 gboolean handle_firewall_get_all_rule(StcFirewall *object,
1718                                    GDBusMethodInvocation *invocation,
1719                                    void *user_data)
1720 {
1721         __STC_LOG_FUNC_ENTER__;
1722         GVariantBuilder *builder = NULL;
1723         GVariant *return_parameters = NULL;
1724
1725         STC_FIREWALL_CHECK_LOCK_STATE(invocation);
1726
1727         builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
1728
1729         __fw_chain_foreach(__fw_foreach_to_make_rule_param, builder);
1730         __fw_chain_foreach(__fw_foreach_to_print_rule, NULL);
1731
1732         return_parameters = g_variant_new("(aa{sv})", builder);
1733         g_variant_builder_unref(builder);
1734
1735         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
1736         STC_DBUS_REPLY(invocation, return_parameters);
1737         __STC_LOG_FUNC_EXIT__;
1738         return TRUE;
1739 }