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