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