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